Check-in [e6d3302781]
Not logged in

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:update curl to version 7.75.0
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: e6d330278195a5e50c4044be384b198913bef783
User & Date: chw 2021-02-04 10:39:14.336
Context
2021-02-05
14:53
add tclbsd upstream changes check-in: ccbc197a5c user: chw tags: trunk
2021-02-04
12:45
merge with trunk check-in: 1f2ba6d33c user: chw tags: wtf-8-experiment
10:39
update curl to version 7.75.0 check-in: e6d3302781 user: chw tags: trunk
07:02
add tclbsd to posix builds check-in: b9f47cf914 user: chw tags: trunk
Changes
Unified Diff Ignore Whitespace Patch
Changes to jni/curl/CHANGES.
1
2
3
4
5
6
7
8
































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































9
10
11
12
13
14
15
                                  _   _ ____  _
                              ___| | | |  _ \| |
                             / __| | | | |_) | |
                            | (__| |_| |  _ <| |___
                             \___|\___/|_| \_\_____|

                                  Changelog

































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































Version 7.74.0 (9 Dec 2020)

Daniel Stenberg (9 Dec 2020)
- RELEASE-NOTES: synced
  
  for 7.74.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
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
                                  _   _ ____  _
                              ___| | | |  _ \| |
                             / __| | | | |_) | |
                            | (__| |_| |  _ <| |___
                             \___|\___/|_| \_\_____|

                                  Changelog

Version 7.75.0 (3 Feb 2021)

Daniel Stenberg (3 Feb 2021)
- RELEASE-NOTES: synced

- THANKS: added contributors from 7.75.0

- copyright: fix year ranges in need of updates

- TODO: remove items for next SONAME bump etc
  
  We want to avoid that completely, so we don't plan for things after such
  an event.

- [Jay Satiro brought this change]

  ngtcp2: Fix build error due to change in ngtcp2_settings
  
  - Separate ngtcp2_transport_params.
  
  ngtcp2/ngtcp2@05d7adc made ngtcp2_transport_params separate from
  ngtcp2_settings.
  
  ngtcp2 master is required to build curl with http3 support.
  
  Closes #6554

- vtls: remove md5sum
  
  As it is not used anymore.
  
  Reported-by: Jacob Hoffman-Andrews
  Bug: https://curl.se/mail/lib-2021-02/0000.html
  
  Closes #6557

- [Alessandro Ghedini brought this change]

  quiche: don't use primary_ip / primary_port
  
  Closes #6555

Alessandro Ghedini (1 Feb 2021)
- travis: enable quiche's FFI feature

Daniel Stenberg (30 Jan 2021)
- [Dmitry Wagin brought this change]

  http: improve AWS HTTP v4 Signature auth
  
  - Add support services without region and service prefixes in
  the URL endpoint (ex. Min.IO, GCP, Yandex Cloud, Mail.Ru Cloud Solutions, etc)
  by providing region and service parameters via aws-sigv4 option.
  - Add [:region[:service]] suffix to aws-sigv4 option;
  - Fix memory allocation errors.
  - Refactor memory management.
  - Use Curl_http_method instead() STRING_CUSTOMREQUEST.
  - Refactor canonical headers generating.
  - Remove repeated sha256_to_hex() usage.
  - Add some docs fixes.
  - Add some codestyle fixes.
  - Add overloaded strndup() for debug - curl_dbg_strndup().
  - Update tests.
  
  Closes #6524

- hyper: fix CONNECT to set 'data' as userdata
  
  Follow-up to 14e075d1a7fd

- [Layla brought this change]

  connect: fix compile errors in `Curl_conninfo_local`
  
  .. for the `#else` (`!HAVE_GETSOCKNAME`) case
  
  Fixes https://github.com/curl/curl/issues/6548
  Closes #6549
  
  Signed-off-by: Layla <layla@insightfulvr.com>

- [Michał Antoniak brought this change]

  transfer: fix GCC 10 warning with flag '-Wint-in-bool-context'
  
  ... and return the error code from the Curl_mime_rewind call.
  
  Closes #6537

- [Michał Antoniak brought this change]

  avoid warning: enum constant in boolean context

- copyright: fix missing year (range) updates

- RELEASE-NOTES: synced

- openssl: lowercase the hostname before using it for SNI
  
  ... because it turns out several servers out there don't actually behave
  correctly otherwise in spite of the fact that the SNI field is
  specifically said to be case insensitive in RFC 6066 section 3.
  
  Reported-by: David Earl
  Fixes #6540
  Closes #6543

- KNOWN_BUGS: cmake: ExternalProject_Add does not set CURL_CA_PATH
  
  Closes #6313

- KNOWN_BUGS: Multi perform hangs waiting for threaded resolver
  
  Closes #4852

- KNOWN_BUGS: "pulseUI VPN client" is known to be buggy
  
  First entry in the new section "applications" for known problems in
  libcurl using applications.
  
  Closes #6306

- tool_writeout: make %{errormsg} blank for no errors
  
  Closes #6539

Jay Satiro (27 Jan 2021)
- [Gisle Vanem brought this change]

  build: fix djgpp builds
  
  - Update build instructions in packages/DOS/README
  
  - Extend 'VPATH' with 'vquic' and 'vssh'.
  
  - Allow 'Makefile.dist' to build both 'lib' and 'src'.
  
  - Allow using the Windows hosted djgpp cross compiler to build for MSDOS
    under Windows.
  
  - 'USE_SSL' -> 'USE_OPENSSL'
  
  - Added a 'link_EXE' macro. Etc, etc.
  
  - Linking 'curl.exe' needs '$(CURLX_CFILES)' too.
  
  - Do not pick-up '../lib/djgpp/*.o' files. Recompile locally.
  
  - Generate a gzipped 'tool_hugehelp.c' if 'USE_ZLIB=1'.
  
  - Remove 'djgpp-clean'
  
  - Adapt to new C-ares directory structure
  
  - Use conditional variable assignments
  
  Clarify the 'conditional variable assignment' in 'common.dj'.
  
  Closes https://github.com/curl/curl/pull/6382

Daniel Stenberg (27 Jan 2021)
- [Ikko Ashimine brought this change]

  hyper: fix typo in c-hyper.c
  
  settting -> setting
  
  Closes #6538

- libssh2: fix CURL_LIBSSH2_DEBUG-enabled build
  
  Follow-up to 2dcc940959772a
  
  Reported-by: Gisle Vanem
  Bug: https://github.com/curl/curl/commit/2dcc940959772a652f6813fb6bd3092095a4877b#commitcomment-46420088

Jay Satiro (27 Jan 2021)
- asyn-thread: fix build for when getaddrinfo missing
  
  This is a follow-up to 8315343 which several days ago moved the resolver
  pointer into the async struct but did not update the code that uses it
  when getaddrinfo is not present.
  
  Closes https://github.com/curl/curl/pull/6536

Daniel Stenberg (27 Jan 2021)
- urldata: move 'ints' to the end of 'connectdata'
  
  To optimize storage slightly.
  
  Closes #6534

- urldata: store ip version in a single byte
  
  Closes #6534

- urldata: remove duplicate 'upkeep_interval_ms' from connectdata
  
  ... and rely only on the value already set in Curl_easy.
  
  Closes #6534

- urldata: remove 'local_ip' from the connectdata struct
  
  As the info is already stored in the transfer handle anyway, there's no
  need to carry around a duplicate buffer for the life-time of the handle.
  
  Closes #6534

- urldata: remove duplicate port number storage
  
  ... and use 'int' for ports. We don't use 'unsigned short' since -1 is
  still often used internally to signify "unknown value" and 0 - 65535 are
  all valid port numbers.
  
  Closes #6534

- urldata: remove the duplicate 'ip_addr_str' field
  
  ... as the numerical IP address is already stored and kept in 'primary_ip'.
  
  Closes #6534

- select: convert Curl_select() to private static function
  
  The old function should not be used anywhere anymore (the only remaining
  gskit use has to be fixed to instead use Curl_poll or none at all).
  
  The static function version is now called our_select() and is only built
  if necessary.
  
  Closes #6531

- Curl_chunker: shrink the struct
  
  ... by removing a field, converting the hex index into a byte and
  rearranging the order. Cuts it down from 48 bytes to 32 on x86_64.
  
  Closes #6527

- curl: include the file name in --xattr/--remote-time error msgs

- curl: s/config->global/global/ in single_transfer()

- curl: move fprintf outputs to warnf
  
  For setting and getting time of the download. To make the outputs
  respect --silent etc.
  
  Reported-by: Viktor Szakats
  Fixes #6533
  Closes #6535

- [Tatsuhiro Tsujikawa brought this change]

  ngtcp2: Fix http3 upload stall
  
  Closes #6521

- [Tatsuhiro Tsujikawa brought this change]

  ngtcp2: Fix stack buffer overflow
  
  Closes #6521

- warnless.h: remove the prototype for curlx_ultosi
  
  Follow-up to 217552503ff3

- warnless: remove curlx_ultosi
  
  ... not used anywhere
  
  Closes #6530

- [Patrick Monnerat brought this change]

  lib: remove conn->data uses
  
  Closes #6515

- pingpong: remove the 'conn' struct member
  
  ... as it's superfluous now when Curl_easy is passed in and we can
  derive the connection from that instead and avoid the duplicate copy.
  
  Closes #6525

- hostip/proxy: remove conn->data use
  
  Closes #6513

- url: reduce conn->data references
  
  ... there are a few left but let's keep them to last
  
  Closes #6512

- scripts/singleuse: add curl_easy_option*

Jay Satiro (25 Jan 2021)
- test410: fix for windows
  
  - Pass the very long request header via file instead of command line.
  
  Prior to this change the 49k very long request header string was passed
  via command line and on Windows that is too long so it was truncated and
  the test would fail (specifically msys CI).
  
  Closes https://github.com/curl/curl/pull/6516

Daniel Stenberg (25 Jan 2021)
- libssh2: move data from connection object to transfer object
  
  Readdir data, filenames and attributes are strictly related to the
  transfer and not the connection. This also reduces the total size of the
  fixed connectdata struct.
  
  Closes #6519

- RELEASE-NOTES: synced

- [Patrick Monnerat brought this change]

  lib: remove conn->data uses
  
  Closes #6499

- hyper: remove the conn->data references
  
  Closes #6508

- travis: build ngtcp2 --with-gnutls
  
  ... since they disable it by default since a few days back.
  
  Closes #6506
  Fixes #6493

- hostip: remove conn->data from resolver functions
  
  This also moves the 'async' struct from the connectdata struct into the
  Curl_easy struct, which seems like a better home for it.
  
  Closes #6497

Jay Satiro (22 Jan 2021)
- strerror: skip errnum >= 0 assertion on windows
  
  On Windows an error number may be greater than INT_MAX and negative once
  cast to int.
  
  The assertion is checked only in debug builds.
  
  Closes https://github.com/curl/curl/pull/6504

Daniel Stenberg (21 Jan 2021)
- doh: make Curl_doh_is_resolved survive a NULL pointer
  
  ... if Curl_doh() returned a NULL, this function gets called anyway as
  in a asynch procedure. Then the doh struct pointer is NULL and signifies
  an OOM situation.
  
  Follow-up to 6246a1d8c6776

- wolfssh: remove conn->data references
  
  ... and repair recent build breakage
  
  Closes #6507

- http: empty reply connection are not left intact
  
  ... so mark the connection as closed in this condition to prevent that
  verbose message to wrongly appear.
  
  Reported-by: Matt Holt
  Bug: https://twitter.com/mholt6/status/1352130240265375744
  Closes #6503

- chunk/encoding: remove conn->data references
  
  ... by anchoring more functions on Curl_easy instead of connectdata
  
  Closes #6498

Jay Satiro (20 Jan 2021)
- [Erik Olsson brought this change]

  lib: save a bit of space with some structure packing
  
  - Reorder some internal struct members so that less padding is used.
  
  This is an attempt at saving a bit of space by packing some structs
  (using pahole to find the holes) where it might make sense to do
  so without losing readability.
  
  I.e., I tried to avoid separating fields that seem grouped
  together (like the cwd... fields in struct ftp_conn for instance).
  Also abstained from touching fields behind conditional macros as
  that quickly can get complicated.
  
  Closes https://github.com/curl/curl/pull/6483

Daniel Stenberg (20 Jan 2021)
- INSTALL.md: fix typo
  
  Found-by: Marcel Raad

- [Fabian Keil brought this change]

  http: get CURLOPT_REQUEST_TARGET working with a HTTP proxy
  
  Added test 1613 to verify.
  
  Closes #6490

- Merge branch 'bagder/curl_range-data-conn'

- ftp: remove conn->data leftover

- curl_range: remove conn->data
  
  Closes #6496

- INSTALL: now at 85 operating systems

- quiche: fix unused parameter ‘conn’
  
  Follow-up to 2bdec0b3

- transfer: fix ‘conn’ undeclared mistake for iconv build
  
  Follow-up to 219d9f8620d

- doh: allocate state struct on demand
  
  ... instead of having it static within the Curl_easy struct. This takes
  away 1176 bytes (18%) from the Curl_easy struct that aren't used very
  often and instead makes the code allocate it when needed.
  
  Closes #6492

- socks: use the download buffer instead
  
  The SOCKS code now uses the generic download buffer for temporary
  storage during the connection procedure, instead of having its own
  private 600 byte buffer that adds to the connectdata struct size. This
  works fine because this point the buffer is allocated but is not use for
  download yet since the connection hasn't completed.
  
  This reduces the connection struct size by 22% on a 64bit arch!
  
  The SOCKS buffer needs to be at least 600 bytes, and the download buffer
  is guaranteed to never be smaller than 1000 bytes.
  
  Closes #6491

- urldata: make magic be the first struct field
  
  By making the `magic` identifier the same size and at the same place
  within the structs (easy, multi, share), libcurl will be able to more
  reliably detect and safely error out if an application passes in the
  wrong handle to APIs. Easier to detect and less likely to cause crashes
  if done.
  
  Such mixups can't be detected at compile-time due to them being
  typedefed void pointers - unless `CURL_STRICTER` is defined.
  
  Closes #6484

- http_chunks: correct and clarify a comment on hexnumber length
  
  ... and also rename the define for max length.
  
  Closes #6489

- curl_path: remove conn->data use
  
  Closes #6487

- transfer: remove conn->data use
  
  Closes #6486

- quic: remove conn->data use
  
  Closes #6485

- [Fabian Keil brought this change]

  Add test1181: Proxy request with --proxy-header "Connection: Keep-Alive"

- [Fabian Keil brought this change]

  Add test1180: Proxy request with -H "Proxy-Connection: Keep-Alive"
  
  At the moment the test fails as curl sends two Proxy-Connection
  headers.

- c-hyper: avoid duplicated Proxy-Connection headers

- http: make providing Proxy-Connection header not cause duplicated headers
  
  Fixes test 1180
  
  Bug: https://curl.se/mail/lib-2021-01/0095.html
  Reported-by: Fabian Keil
  Closes #6472

- runtests: preprocess DISABLED to allow conditionals
  
  ... with this function provided, we can disable tests for specific
  environments and setups directly within this file.
  
  Closes #6477

- runtests: turn preprocessing into a separate function
  
  ... and remove all other variable substitutions as they're now done once
  and for all in the preprocessor.

- lib/Makefile.inc: convert to listing each file on its own line
  
  ... to make it diff friendlier and easier to read.
  
  Closes #6448

- ftplistparser: remove use of conn->data
  
  Closes #6482

- lib: more conn->data cleanups
  
  Closes #6479

- [Patrick Monnerat brought this change]

  vtls: reduce conn->data use
  
  Closes #6474

- hyper: deliver data to application with Curl_client_write
  
  ... just as the native code path does. Avoids sending too large data
  chunks in the callback and more.
  
  Reported-by: Gisle Vanem
  Fixes #6462
  Closes #6473

- gopher: remove accidental conn->data leftover

- libssh: avoid plain free() of libssh-memory
  
  Since curl's own memory debugging system redefines free() calls to track
  and fiddle with memory, it cannot be used on memory allocated by 3rd
  party libraries.
  
  Third party libraries SHOULD NOT require free() to release allocated
  resources for this reason - and libs can use separate healp allocators
  on some systems (like Windows) so free() doesn't necessarily work
  anyway.
  
  Filed as an issue with libssh: https://bugs.libssh.org/T268
  
  Closes #6481

- send: assert that Curl_write_plain() has a ->conn when called
  
  To help catch bad invokes.
  
  Closes #6476

- test410: verify HTTPS GET with a 49K request header
  
  skip test 410 for mesalink in the CI as it otherwise hangs "forever"

- lib: pass in 'struct Curl_easy *' to most functions
  
  ... in most cases instead of 'struct connectdata *' but in some cases in
  addition to.
  
  - We mostly operate on transfers and not connections.
  
  - We need the transfer handle to log, store data and more. Everything in
    libcurl is driven by a transfer (the CURL * in the public API).
  
  - This work clarifies and separates the transfers from the connections
    better.
  
  - We should avoid "conn->data". Since individual connections can be used
    by many transfers when multiplexing, making sure that conn->data
    points to the current and correct transfer at all times is difficult
    and has been notoriously error-prone over the years. The goal is to
    ultimately remove the conn->data pointer for this reason.
  
  Closes #6425

Emil Engler (17 Jan 2021)
- docs: fix typos in NEW-PROTOCOL.md
  
  This fixes a misspelled "it" and a grammatically wrong "-ing" suffix.
  
  Closes #6471

Daniel Stenberg (16 Jan 2021)
- RELEASE-NOTES: synced

Jay Satiro (16 Jan 2021)
- [Razvan Cojocaru brought this change]

  cmake: expose CURL_DISABLE_OPENSSL_AUTO_LOAD_CONFIG
  
  This does for cmake builds what --disable-openssl-auto-load-config
  does for autoconf builds.
  
  Closes https://github.com/curl/curl/pull/6435

Daniel Stenberg (15 Jan 2021)
- test1918: verify curl_easy_option_by_name() and curl_easy_option_by_id()
  
  ... and as a practical side-effect, make sure that the
  Curl_easyopts_check() function is asserted in debug builds, which we
  want to detect mismatches between the options list in easyoptions.c and
  the options in curl.h
  
  Found-by: Gisle Vanem
  Bug: https://github.com/curl/curl/commit/08e8455dddc5e48e58a12ade3815c01ae3da3b64#commitcomment-45991815
  
  Closes #6461

- [Gisle Vanem brought this change]

  easyoptions: add the missing AWS_SIGV4
  
  Follow-up from AWS_SIGV4

- schannel_verify: fix safefree call typo
  
  Follow-up from e87ad71d1ba00519
  
  Closes #6459

- mime: make sure setting MIMEPOST to NULL resets properly
  
  ... so that a function can first use MIMEPOST and then set it to NULL to
  reset it back to a blank POST.
  
  Added test 584 to verify the fix.
  
  Reported-by: Christoph M. Becker
  
  Fixes #6455
  Closes #6456

- multi: set the PRETRANSFER time-stamp when we switch to PERFORM
  
  ... instead of at end of the DO state. This makes the timer more
  accurate for the protocols that use the DOING state (such as FTP), and
  simplifies how the function (now called init_perform) is called.
  
  The timer will then include the entire procedure up to PERFORM -
  including all instructions for getting the transfer started.
  
  Closes #6454

- CURLINFO_PRETRANSFER_TIME.3: clarify
  
  ... the timer *does* include the instructions for getting the remote
  file.
  
  Ref: #6452
  Closes #6453

- [Gisle Vanem brought this change]

  schannel: plug a memory-leak
  
  ... when built without -DUNICODE.
  
  Closes #6457

Jay Satiro (14 Jan 2021)
- gitattributes: Set batch files to CRLF line endings on checkout
  
  If a batch file is run without CRLF line endings (ie LF-only) then
  arbitrary behavior may occur. I consider that a bug in Windows, however
  the effects can be serious enough (eg unintended code executed) that
  we're fixing it in the repo by requiring CRLF line endings for batch
  files on checkout.
  
  Prior to this change the checked-out line endings of batch files were
  dependent on a user's git preferences. On Windows it is common for git
  users to have automatic CRLF conversion enabled (core.autocrlf true),
  but those users that don't would run into this behavior.
  
  For example a user has reported running the Visual Studio project
  generator batch file (projects/generate.bat) and it looped forever.
  Output showed that the Windows OS interpreter was occasionally jumping
  to arbitrary points in the batch file and executing commands. This
  resulted in unintended files being removed (a removal sequence called)
  and looping forever.
  
  Ref: https://serverfault.com/q/429594
  Ref: https://stackoverflow.com/q/232651
  Ref: https://www.dostips.com/forum/viewtopic.php?t=8988
  Ref: https://git-scm.com/docs/gitattributes#_checking_out_and_checking_in
  Ref: https://git-scm.com/book/en/v2/Customizing-Git-Git-Configuration#_core_autocrlf
  
  Bug: https://github.com/curl/curl/discussions/6427
  Reported-by: Ganesh Kamath
  
  Closes https://github.com/curl/curl/pull/6442

Daniel Stenberg (14 Jan 2021)
- tool_operate: spellfix a comment

- ROADMAP: refreshed
  
  o removed HSTS - already implemented
  o added HTTPS RR records
  o mention HTTP/3 completion

- http_chunks: remove Curl_ prefix from static functions

- transfer: remove Curl_ prefix from static functions

- tftp: remove Curl_ prefix from static functions

- multi: remove Curl_ prefix from static functions

- ldap: remove Curl_ prefix from static functions

- doh: remove Curl_ prefix from static functions

- asyn-ares: remove Curl_ prefix from static functions

- vtls: remove Curl_ prefix from static functions

- bearssl: remove Curl_ prefix from static functions

- mbedtls: remove Curl_ prefix from static functions

- wolfssl: remove Curl_ prefix from static functions

- nss: remove Curl_ prefix from static functions

- gnutls: remove Curl_ prefix from static functions

- openssl: remove Curl_ prefix from static functions
  
  ... as we reserve this prefix to library-wide functions.
  
  Closes #6443

- nss: get the run-time version instead of build-time
  
  Closes #6445

Jay Satiro (12 Jan 2021)
- tool_doswin: Restore original console settings on CTRL signal
  
  - Move Windows terminal init code from tool_main to tool_doswin.
  
  - Restore the original console settings on CTRL+C and CTRL+BREAK.
  
  Background: On Windows the curl tool changes the console settings to
  enable virtual terminal processing (eg color output) if supported
  (ie Win 10). The original settings are restored on exit but prior to
  this change were not restored in the case of the CTRL signals.
  
  Windows VT behavior varies depending on console/powershell/terminal;
  refer to the discussion in #6226.
  
  Assisted-by: Rich Turner
  
  Closes https://github.com/curl/curl/pull/6226

Daniel Stenberg (12 Jan 2021)
- gen.pl: fix perl syntax
  
  Follow-up to 324cf1d2e

- [Emil Engler brought this change]

  help: update to current codebase
  
  This commit bumps the help to the current state of the project.
  
  Closes #6437

- [Emil Engler brought this change]

  docs: fix line length bug in gen.pl
  
  The script warns if the length of $opt and $desc is > 78. However, these
  two variables are on totally separate lines so the check makes no sense.
  Also the $bitmask field is totally forgotten. Currently this leads to
  two warnings within `--resolve` and `--aws-sigv4`.
  
  Closes #6438

- [Emil Engler brought this change]

  docs: fix wrong documentation in help.d
  
  curl does not list all categories when you invoke "--help" without any
  parameters.
  
  Closes #6436

- aws-sigv4.d: polish the wording
  
  Make it shorter and imperative form
  
  Closes #6439

- [Fabian Keil brought this change]

  misc: fix typos
  
  Bug: https://curl.se/mail/lib-2021-01/0063.html
  Closes #6434

- multi_runsingle: bail out early on data->conn == NULL
  
  As that's a significant error condition and scan-build warns for NULL
  pointer dereferences if we don't.
  
  Closes #6433

- multi: skip DONE state if there's no connection left for ftp wildcard
  
  ... to avoid running in that state with data->conn being NULL.

- libssh2: fix "Value stored to 'readdir_len' is never read"
  
  Detected by scan-build

- connect: mark intentional ignores of setsockopt return values
  
  Pointed out by Coverity
  
  Closes #6431

Jay Satiro (11 Jan 2021)
- http_proxy: Fix CONNECT chunked encoding race condition
  
  - During the end-of-headers response phase do not mark the tunnel
    complete unless the response body was completely parsed/ignored.
  
  Prior to this change if the entirety of a CONNECT response with chunked
  encoding was not received by the time the final header was parsed then
  the connection would be marked done prematurely, before all the chunked
  data could be read in and ignored (since this is what we do with any
  CONNECT response body) and the connection could not be used.
  
  Bug: https://curl.se/mail/lib-2021-01/0033.html
  Reported-by: Fabian Keil
  
  Closes https://github.com/curl/curl/pull/6432

Daniel Stenberg (11 Jan 2021)
- RELEASE-NOTES: synced

- url: if IDNA conversion fails, fallback to Transitional
  
  This improves IDNA2003 compatiblity.
  
  Reported-by: Bubu on github
  Fixes #6423
  Closes #6428

- travis: make the Hyper build from its master branch
  
  Closes #6430

- http: make 'authneg' also work for Hyper
  
  When doing a request with a request body expecting a 401/407 back, that
  initial request is sent with a zero content-length. Test 177 and more.
  
  Closes #6424

Jay Satiro (8 Jan 2021)
- cmake: Add an option to disable libidn2
  
  New option USE_LIBIDN2 defaults to ON for libidn2 detection. Prior to
  this change libidn2 detection could not be turned off in cmake builds.
  
  Reported-by: William A Rowe Jr
  
  Fixes https://github.com/curl/curl/issues/6361
  Closes https://github.com/curl/curl/pull/6362

Daniel Stenberg (8 Jan 2021)
- HYPER: no longer needs the special branch

- test179: use consistent header line endings
  
  ... to make "Hyper mode" work better.

- file: don't provide content-length for directories
  
  ... as it is misleading.
  
  Ref #6379
  Closes #6421

- TODO: Directory listing for FILE:
  
  Ref #6379

- curl.h: add CURLPROTO_GOPHERS as own protocol identifier
  
  Follow-up to a1f06f32b860, to make sure it can be handled separately
  from plain gopher.
  
  Closes #6418

- http: have CURLOPT_FAILONERROR fail after all headers
  
  ... so that Retry-After and other meta-content can still be used.
  
  Added 1634 to verify. Adjusted test 194 and 281 since --fail now also
  includes the header-terminating CRLF in the output before it exits.
  
  Fixes #6408
  Closes #6409

- global_init: debug builds allocates a byte in init
  
  ... to make build tools/valgrind warn if no curl_global_cleanup is
  called.
  
  This is conditionally only done for debug builds with the env variable
  CURL_GLOBAL_INIT set.
  
  Closes #6410

- lib/unit tests: add missing curl_global_cleanup() calls

- travis: adapt to Hyper build change
  
  Closes #6419

- pretransfer: setup the User-Agent header here
  
  ... and not in the connection setup, as for multiplexed transfers the
  connection setup might be skipped and then the transfer would end up
  without the set user-agent!
  
  Reported-by: Flameborn on github
  Assisted-by: Andrey Gursky
  Assisted-by: Jay Satiro
  Assisted-by: Mike Gelfand
  Fixes #6312
  Closes #6417

- test66: disable with Hyper
  
  ...as Hyper doesn't support HTTP/0.9

- c-hyper: poll the tasks until end correctly
  
  ... makes test 36 work.
  
  Closes #6412

- [Gergely Nagy brought this change]

  mk-ca-bundle.pl: deterministic output when using -t
  
  Printing trust purposes are now sorted, making the output deterministic
  when running on the same input certdata.txt.
  
  Closes #6413

- KNOWN_BUGS: fixed "wolfSSL lacks support for renegotiation"
  
  Fixed by #6411

- [Himanshu Gupta brought this change]

  wolfssl: add SECURE_RENEGOTIATION support
  
  Closes #6411

- RELEASE-NOTES: synced

- wolfssl: update copyright year range
  
  Follow-up to 7de2e96535e9

- c-hyper: make CURLE_GOT_NOTHING work
  
  Test 30
  
  Closes #6407

- http_proxy: make CONNECT work with the Hyper backend
  
  Makes test 80 run
  
  Closes #6406

- TODO: --fail-with-body perchance?

Jay Satiro (4 Jan 2021)
- tool_operate: fix the suppression logic of some error messages
  
  - Fix the failed truncation and failed writing body error messages to
    not be shown unless error messages are shown. (ie the user has
    specified -sS, or has not specified -s).
  
  - Also prefix same error messages with "curl: ", for example:
    curl: (23) Failed to truncate, exiting
  
  Prior to this change the failed truncation error messages would be shown
  if not -s, but did not account for -sS which should show.
  
  Prior to this change the failed writing body error messages would be
  shown always.
  
  Ref: https://curl.se/docs/manpage.html#-S
  
  Bug: https://curl.se/mail/archive-2020-12/0017.html
  Reported-by: Hongyi Zhao
  
  Closes https://github.com/curl/curl/pull/6402

- wolfssl: Support wolfSSL builds missing TLS 1.1
  
  The wolfSSL TLS library defines NO_OLD_TLS in some of their build
  configurations and that causes the library to be built without TLS 1.1.
  For example if MD5 is explicitly disabled when building wolfSSL then
  that defines NO_OLD_TLS and the library is built without TLS 1.1 [1].
  
  Prior to this change attempting to build curl with a wolfSSL that was
  built with NO_OLD_TLS would cause a build link error undefined reference
  to wolfTLSv1_client_method.
  
  [1]: https://github.com/wolfSSL/wolfssl/blob/v4.5.0-stable/configure.ac#L2366
  
  Bug: https://curl.se/mail/lib-2020-12/0121.html
  Reported-by: Julian Montes
  
  Closes https://github.com/curl/curl/pull/6388

Daniel Stenberg (4 Jan 2021)
- test1633: set appropriate name
  
  "--retry with a 429 response and Retry-After:"

- travis: limit the tests with quiche builds to HTTPS and FTPS only
  
  ... since it runs into the 50 minute time limit too often otherwise.
  
  Closes #6403

- HISTORY: added dates to early history
  
  Mostly thanks to this archived web page for urlget:
  
  https://web.archive.org/web/19980216125115/http://www.inf.ufrgs.br/~sagula/urlget.html

- httpauth: make multi-request auth work with custom port
  
  When doing HTTP authentication and a port number set with CURLOPT_PORT,
  the code would previously have the URL's port number override as if it
  had been a redirect to an absolute URL.
  
  Added test 1568 to verify.
  
  Reported-by: UrsusArctos on github
  Fixes #6397
  Closes #6400

- [Emil Engler brought this change]

  language: s/behaviour/behavior/g
  
  We currently use both spellings the british "behaviour" and the american
  "behavior". However "behavior" is more used in the project so I think
  it's worth dropping the british name.
  
  Closes #6395

- cmdline-opts/retry.d: mention response code 429 as well
  
  Reported-by: Cherish98
  Bug: https://curl.se/mail/archive-2020-12/0018.html

- docs/HYPER.md: mention outstanding issues
  
  To make it more obvious to users what doesn't work (yet)
  
  Closes #6389

- COPYING/configure: bump copyright year range

- c-hyper: add timecondition to the request
  
  Test 77-78
  
  Closes #6391

- c-hyper: make Digest and NTLM work
  
  Test 64, 65, 67, 68, 69, 70, 72
  
  Closes #6390

- examples/curlgtk.c: fix the copyright year range
  
  ... and make private functions static.

- [Olaf Hering brought this change]

  docs/examples: adjust prototypes for CURLOPT_READFUNCTION
  
  The type of the buffer in curl_read_callback is 'char *', not 'void *'.
  
  Signed-off-by: Olaf Hering <olaf@aepfle.de>
  Closes #6392

- examples: fix more empty expression statement has no effect
  
  Follow-up to 26e46617b9

- cleanup: fix two empty expression statement has no effect
  
  Follow-up to 26e46617b9

- configure: set -Wextra-semi-stmt for clang with --enable-debug
  
  To have it properly complain on empty statements with no effect.
  
  Ref: #6376
  Closes #6378

- tests/unit: fix empty statements with no effect
  
  ... by making macros use "do {} while(0)"

- [Paul Groke brought this change]

  dns: extend CURLOPT_RESOLVE syntax for adding non-permanent entries
  
  Extend the syntax of CURLOPT_RESOLVE strings: allow using a '+' prefix
  (similar to the existing '-' prefix for removing entries) to add
  DNS cache entries that will time out just like entries that are added
  by libcurl itself.
  
  Append " (non-permanent)" to info log message in case a non-permanent
  entry is added.
  
  Adjust relevant comments to reflect the new behavior.
  
  Adjust documentation.
  
  Extend unit1607 to test the new functionality.
  
  Closes #6294

- schannel: fix "empty expression statement has no effect"
  
  Bug: https://github.com/curl/curl/commit/8ab78f720ae478d533e30b202baec4b451741579#commitcomment-45445950
  Reported-by: Gisle Vanem
  Closes #6381

- [Denis Laxalde brought this change]

  docs: remove redundant "better" in --fail help
  
  Closes #6385

- [Kevin Ushey brought this change]

  curl.1: fix typo microsft -> microsoft
  
  Closes #6380

- [XhmikosR brought this change]

  misc: assorted typo fixes
  
  Closes #6375

- RELEASE-NOTES: synced

- tool_operate: avoid NULL dereference of first_arg
  
  Follow-up to 6a5e020d4d2b04a
  Identified by OSS-Fuzz
  Bug: https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=28999
  Closes #6377

- misc: fix "warning: empty expression statement has no effect"
  
  Turned several macros into do-while(0) style to allow their use to work
  find with semicolon.
  
  Bug: https://github.com/curl/curl/commit/08e8455dddc5e48e58a12ade3815c01ae3da3b64#commitcomment-45433279
  Follow-up to 08e8455dddc5e4
  Reported-by: Gisle Vanem
  Closes #6376

- KNOWN_BUGS: 6.10 curl never completes Negotiate over HTTP
  
  Closes #5235
  Closes #6370

- writeout: fix NULL dereference for "this url"
  
  Detected by torture test 1029
  
  Follow-up to 7a90ddf88f5a
  
  Closes #6374

- failf: remove newline from formatting strings
  
  ... as failf adds one itself.
  
  Also: add an assert() to failf() that triggers on a newline in the
  format string!
  
  Closes #6365

- [XhmikosR brought this change]

  CI: fix warning with the latest versions
  
  `git checkout HEAD^2` is no longer needed
  
  Closes #6369

- INSTALL: update the list known OSes and CPU archs curl has run on
  
  Closes #6366

- [Cherish98 brought this change]

  curl: fix handling of -q option
  
  The match of the "-q" option (short for "--disable") should:
  a) allow concatenation with other single-letters; and
  b) be case-sensitive, lest confusing with "-Q" ("--quote")
  
  Closes #6364

- tests/badsymbols.pl: ignore stand-alone single hash lines
  
  Bug: https://curl.se/mail/lib-2020-12/0084.html
  Reported-by: Dennis Clarke
  Assisted-by: Jay Satiro
  
  Closes #6355

- curl_easy_pause.3: add multiplexed pause effects
  
  and generally refresh and update. Remove details for ancient versions.
  
  Reviewed-by: Jay Satiro
  Closes #6360

Jay Satiro (22 Dec 2020)
- curl_easy_pause.3: fix man page reference
  
  Follow-up to ac9a724 from earlier today.
  
  Ref: https://github.com/curl/curl/pull/6359

Daniel Stenberg (22 Dec 2020)
- EXPERIMENTAL: add the Hyper backend to the list
  
  ... of current experimental features in curl.

- speedcheck: exclude paused transfers
  
  Paused transfers should not be stopped due to slow speed even when
  CURLOPT_LOW_SPEED_LIMIT is set. Additionally, the slow speed timer is
  now reset when the transfer is unpaused - as otherwise it would easily
  just trigger immediately after unpausing.
  
  Reported-by: Harry Sintonen
  Fixes #6358
  Closes #6359

- h2: do not wait for RECV on paused transfers
  
  ... as the socket might be readable all the time when paused and thus
  causing a busy-loop.
  
  Reported-by: Harry Sintonen
  Reviewed-by: Jay Satiro
  Fixes #6356
  Closes #6357

- RELEASE-NOTES: synced

- cmdline-opts/gen.pl: return hard on errors
  
  ... as the warnings tend to go unnoticed otherwise!
  
  Closes #6354

- examples/libtest: add .checksrc to dist
  
  ... so that (auto)builds from tarballs also get the correct instructions.
  
  Fixes #6176
  Closes #6353

- test: verify new --write-out variables
  
  Extended test 1029 and added 1188

- test970: adapted to the new internal order of variables

- curl: add variables to --write-out
  
  In particular, these ones can help a user to create its own error
  message when one or transfers fail.
  
  writeout: add 'onerror', 'url', 'urlnum', 'exitcode', 'errormsg'
  
  onerror - lets a user only show the rest on non-zero exit codes
  
  url - the input URL used for this transfer
  
  urlnum - the numerical URL counter (0 indexed) for this transfer
  
  exitcode - the numerical exit code for the transfer
  
  errormsg - obvious
  
  Reported-by: Earnestly on github
  Fixes #6199
  Closes #6207

- [Matthias Gatto brought this change]

  tests: add very simple AWS HTTP v4 Signature test
  
  Signed-off-by: Matthias Gatto <matthias.gatto@outscale.com>

- [Matthias Gatto brought this change]

  docs: add AWS HTTP v4 Signature

- [Matthias Gatto brought this change]

  tool: add AWS HTTP v4 Signature support
  
  Signed-off-by: Matthias Gatto <matthias.gatto@outscale.com>

- [Matthias Gatto brought this change]

  http: Make the call to v4 signature
  
  This patch allow to call the v4 signature introduce in previous commit
  
  Signed-off-by: Matthias Gatto <matthias.gatto@outscale.com>

- [Matthias Gatto brought this change]

  http: introduce AWS HTTP v4 Signature
  
  It is a security process for HTTP.
  
  It doesn't seems to be standard, but it is used by some cloud providers.
  
  Aws:
  https://docs.aws.amazon.com/general/latest/gr/signature-version-4.html
  Outscale:
  https://wiki.outscale.net/display/EN/Creating+a+Canonical+Request
  GCP (I didn't test that this code work with GCP though):
  https://cloud.google.com/storage/docs/access-control/signing-urls-manually
  
  most of the code is in lib/http_v4_signature.c
  
  Information require by the algorithm:
  - The URL
  - Current time
  -  some prefix that are append to some of the signature parameters.
  
  The data extracted from the URL are: the URI, the region,
  the host and the API type
  
  example:
  https://api.eu-west-2.outscale.com/api/latest/ReadNets
          ~~~ ~~~~~~~~               ~~~~~~~~~~~~~~~~~~~
          ^       ^                          ^
         /         \                        URI
     API type     region
  
  Small description of the algorithm:
  - make canonical header using content type, the host, and the date
  - hash the post data
  - make canonical_request using custom request, the URI,
    the get data, the canonical header, the signed header
    and post data hash
  - hash canonical_request
  - make str_to_sign using one of the prefix pass in parameter,
    the date, the credential scope and the canonical_request hash
  - compute hmac from date, using secret key as key.
  - compute hmac from region, using above hmac as key
  - compute hmac from api_type, using above hmac as key
  - compute hmac from request_type, using above hmac as key
  - compute hmac from str_to_sign using above hmac as key
  - create Authorization header using above hmac, prefix pass in parameter,
    the date, and above hash
  
  Signed-off-by: Matthias Gatto <matthias.gatto@outscale.com>
  
  Closes #5703

- [Matthias Gatto brought this change]

  http: add hmac support for sha256
  
  It seems current hmac implementation use md5 for the hash,
  V4 signature require sha256, so I've added the needed struct in
  this commit.
  
  I've added the functions that do the hmac in v4 signature file
  as a static function ,in the next patch of the serie,
  because it's used only by this file.
  
  Signed-off-by: Matthias Gatto <matthias.gatto@outscale.com>

- [Cristian Rodríguez brought this change]

  connect: on linux, enable reporting of all ICMP errors on UDP sockets
  
  The linux kernel does not report all ICMP errors back to userspace due
  to historical reasons.
  
  IP*_RECVERR sockopt must be turned on to have the correct behaviour
  which is to pass all ICMP errors to userspace.
  
  See https://bugzilla.kernel.org/show_bug.cgi?id=202355
  
  Closes #6341

- curl: add --create-file-mode [mode]
  
  This option sets the (octal) mode to use for the remote file when one is
  created, using the SFTP, SCP or FILE protocols. When not set, the
  default is 0644.
  
  Closes #6244

- c-hyper: fix compiler warnings
  
  Identified by clang on windows.
  
  Reported-by: Gisle Vanem
  Bug: 58974d25d8173aec154e593ed9d866da566c9811
  
  Closes #6351

- KNOWN_BUGS: Remote recursive folder creation with SFTP
  
  Closes #5204

Jay Satiro (20 Dec 2020)
- badsymbols.pl: Add verbose mode -v
  
  Use -v as the first option to enable verbose mode which will show source
  input, extracted symbol and line info. For example:
  
  Source: ./../include/curl/typecheck-gcc.h
  Symbol: curlcheck_socket_info(info)
  Line #423: #define curlcheck_socket_info(info)                     \
  
  Ref: https://curl.se/mail/lib-2020-12/0084.html
  
  Closes https://github.com/curl/curl/pull/6349

- KNOWN_BUGS: Secure Transport disabling hostname validation also disables SNI
  
  That behavior is a limitation of Apple's Secure Transport.
  
  Reported-by: Cory Benfield
  Reported-by: Ian Spence
  Confirmed-by: Nick Zitzmann
  
  Ref: https://github.com/curl/curl/issues/998
  
  Closes https://github.com/curl/curl/issues/6347
  Closes https://github.com/curl/curl/pull/6348

Daniel Stenberg (18 Dec 2020)
- TODO: alt-svc should fallback if alt-svc doesn't work
  
  Closes #4908

- travis: restrict the openssl3 job to only run https and ftps tests
  
  ... as it runs too long otherwise and the other tests are verified in
  other builds anyway.
  
  Closes #6345

- build: repair http disabled but mqtt enabled build
  
  ... as the mqtt code reuses the "method" originally used for HTTP.
  
  Closes #6344

- [Jon Wilkes brought this change]

  cookie: avoid the C1001 internal compiler error with MSVC 14
  
  Fixes #6112
  Closes #6135

- RELEASE-NOTES: synced

- mqtt: handle POST/PUBLISH without a set POSTFIELDSIZE
  
  Detected by OSS-Fuzz
  Bug: https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=28735
  
  Added test 1916 and 1917 to verify.
  
  Closes #6338

- travis: add CI job for Hyper build

- tests: updated tests for Hyper

- lib: introduce c-hyper for using Hyper
  
  ... as an alternative HTTP backend within libcurl.

- tool_setopt: provide helper output in debug builds
  
  ... for when setopt() returns error.

- setopt: adjust to Hyper and disabled HTTP builds

- rtsp: disable if Hyper is used

- getinfo: build with disabled HTTP support

- version: include hyper version

- docs: add HYPER.md

- configure: add --with-hyper
  
  As the first (optional) HTTP backend alternative instead of native
  
  Close #6110

- test1522: add debug tracing
  
  I used this to track down some issues and I figured I could just as well
  keep this extra logging in here for future needs.
  
  Closes #6331

- http: show the request as headers even when split-sending
  
  When the initial request isn't possible to send in its entirety, the
  remainder of request would be delivered to the debug callback as data
  and would wrongly be counted internally as body-bytes sent.
  
  Extended test 1295 to verify.
  
  Closes #6328

- multi: when erroring in TOOFAST state, act as for PERFORM
  
  When failing in TOOFAST, the multi_done() wasn't called so the same
  cleanup and handling wasn't done like when it fails in PERFORM, which in
  the case of FTP could mean that the control connection wouldn't be
  marked as "dead" for the CURLE_ABORTED_BY_CALLBACK case. Which caused
  ftp_disconnect() to use it to send "QUIT", which could end up waiting
  for a response a long time before giving up!
  
  Reported-by: Tomas Berger
  Fixes #6333
  Closes #6337

- cmake: enable gophers correctly in curl-config
  
  Closes #6336

- test1198/9: add two mqtt publish tests without payload lengths
  
  Closes #6335

- tests/mqttd: extract the client id from the correct offset
  
  Closes #6334

- TODO: Prevent terminal injection when writing to terminal
  
  Closes #6150

- Revert "CI/github: work-around for brew breakage on macOS"
  
  This reverts commit 4cbb17a2cbbbe6337142d39479e21c3990b9c22f.
  
  ... as the work-around now causes failures.
  
  Closes #6332

- examples: remove superfluous asterisk uses
  
  ... for function pointers. Breaks in ancient compilers.

- RELEASE-NOTES: synced

- test1272: fix line ending
  
  Follow-up to f24784f9143

- URL-SYNTAX: add gophers details

- test1272: test gophers

- runtests: add support for gophers, gopher over TLS

- [parazyd brought this change]

  gopher: Implement secure gopher protocol.
  
  This commit introduces a "gophers" handler inside the gopher protocol if
  USE_SSL is defined. This protocol is no different than the usual gopher
  prococol, with the added TLS encapsulation upon connecting. The protocol
  has been adopted in the gopher community, and many people have enabled
  TLS in their gopher daemons like geomyidae(8), and clients, like clic(1)
  and hurl(1).
  
  I have not implemented test units for this protocol because my knowledge
  of Perl is sub-par. However, for someone more knowledgeable it might be
  fairly trivial, because the same test that tests the plain gopher
  protocol can be used for "gophers" just by adding a TLS listener.
  
  Signed-off-by: parazyd <parazyd@dyne.org>
  
  Closes #6208

- TODO: Package curl for Windows in a signed installer
  
  Closes #5424

- mqtt: deal with 0 byte reads correctly
  
  OSS-Fuzz found it
  Bug: https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=28676
  
  Closes #6327

- BUG-BOUNTY: minor language update
  
  ... and remove the wording about entries from before 2019 as the "within
  12 months" is still there and covers that.
  
  Closes #6318

- tooĺ_writeout: fix the -w time output units
  
  Fix regression from commit fc813f80e1bcac (#6248) that changed the unit
  to microseconds instead of seconds with fractions
  
  Reported-by: 不确定
  Fixes #6321
  Closes #6322

- quiche: remove fprintf() leftover

Jay Satiro (14 Dec 2020)
- KNOWN_BUGS: SHA-256 digest not supported in Windows SSPI builds
  
  Closes https://github.com/curl/curl/issues/6302

- digest_sspi: Show InitializeSecurityContext errors in verbose mode
  
  The error is shown with infof rather than failf so that the user will
  see the extended error message information only in verbose mode, and
  will still see the standard CURLE_AUTH_ERROR message. For example:
  
  ---
  
  * schannel: InitializeSecurityContext failed: SEC_E_QOP_NOT_SUPPORTED
  (0x8009030A) - The per-message Quality of Protection is not supported by
  the security package
  * multi_done
  * Connection #1 to host 127.0.0.1 left intact
  curl: (94) An authentication function returned an error
  
  ---
  
  Ref: https://github.com/curl/curl/issues/6302
  
  Closes https://github.com/curl/curl/pull/6315

Daniel Stenberg (13 Dec 2020)
- URL-SYNTAX: add default port numbers and IDNA details
  
  Closes #6316

- URL-SYNTAX: mention how FILE:// access can access network on windows
  
  Closes #6314

Jay Satiro (12 Dec 2020)
- URL-SYNTAX: Document default SMTP port 25
  
  Note that ports 25 and 587 are common ports for smtp, the former being
  the default.
  
  Closes https://github.com/curl/curl/pull/6310

Daniel Stenberg (12 Dec 2020)
- CURLOPT_URL.3: remove scheme specific details
  
  ... that are now found in URL-SYNTAX.md
  
  Closes #6307

Dan Fandrich (12 Dec 2020)
- docs: Fix some typos
  
  [skip ci]

Daniel Stenberg (12 Dec 2020)
- URL-SYNTAX: mention all supported schemes
  
  Closes #6311

- [Douglas R. Reno brought this change]

  URL-SYNTAX.md: minor language improvements
  
  Closes #6308

- docs/URL-SYNTAX: the URL syntax curl accepts and works with
  
  Closes #6285

- [0xflotus brought this change]

  docs: enable syntax highlighting in several docs files
  
  ... for better readability
  
  Closes #6286

- test1564/1565: require the 'wakeup' feature to run
  
  Fixes #6299
  Fixes #6300
  Closes #6301

- runtests: add 'wakeup' as a feature

- tests/server/disabled: add "wakeup"
  
  To allow the test suite to know if wakeup support is disabled in the
  build.

- lib1564/5: verify that curl_multi_wakeup returns OK

- tests: make --libcurl tests only test FTP options if ftp enabled
  
  Adjust six --libcurl tests to only check the FTP option if FTP is
  actually present in the build.
  
  Fixes #6303
  Closes #6305

- runtests.pl: fix "uninitialized value" warning
  
  follow-up to e12825c642a88774

- runtests: add support for %if [feature] conditions
  
  ... to make tests run differently or expect different results depending
  on what features that are present or not in curl.
  
  Bonus: initial minor 'Hyper' awareness but nothing is using that yet
  
  Closes #6304

- [Jon Rumsey brought this change]

  OS400: update ccsidcurl.c
  
  Add 'struct' to cast and declaration of cfcdata to fix compilation
  error.
  
  Fixes #6292
  Closes #6297

- ngtcp2: make it build it current master again
  
  Closes #6296

- [Cristian Rodríguez brought this change]

  connect: defer port selection until connect() time
  
  If supported, defer port selection until connect() time
  if --interface is given and source port is 0.
  
  Reproducer:
  
  * start fast webserver on port 80
  * starve system of ephemeral ports
  $  sysctl net.ipv4.ip_local_port_range="60990 60999"
  
  * start a curl/libcurl "crawler"
  $curl --keepalive --parallel --parallel-immediate --head --interface
  127.0.0.2 "http://127.0.0.[1-254]/file[001-002].txt"
  
  current result:
  (possible some successful data)
  curl: (45) bind failed with errno 98: Address already in use
  
  result after patch:
  (complete success or few connections failing, higlhy depending on load)
  
  Fail only when all the possible 4-tuple combinations are exhausted,
  which is impossible to do when port is selected at bind() time becuse
  the kernel does not know if socket will be listen()'ed on or connect'ed
  yet.
  
  Closes #6295

- [Hans-Christian Noren Egtvedt brought this change]

  connect: zero variable on stack to silence valgrind complaint
  
  Valgrind will complain that ssrem buffer usage if not explicit
  initialized, hence initialize it to zero.
  
  This completes the change intially started in commit 2c0d7212151 ('ftp:
  retry getpeername for FTP with TCP_FASTOPEN') where the ssloc buffer has
  a similar memset to zero.
  
  Signed-off-by: Hans-Christian Noren Egtvedt <hegtvedt@cisco.com>
  Closes #6289

- RELEASE-NOTES: synced
  
  start over on the next release cycle

Version 7.74.0 (9 Dec 2020)

Daniel Stenberg (9 Dec 2020)
- RELEASE-NOTES: synced
  
  for 7.74.0

5585
5586
5587
5588
5589
5590
5591
5592
5593
5594
5595
5596
5597
5598
5599
5600
5601
5602
5603
5604
5605
5606
5607
5608
5609
5610
5611
5612
5613
5614
5615
5616
5617
5618
5619
5620
5621
5622
5623
5624
5625
5626
5627
5628
5629
5630
5631
5632
5633
5634
5635
5636
5637
5638
5639
5640
5641
5642
5643
5644
5645
5646
5647
5648
5649
5650
5651
5652
5653
5654
5655
5656
5657
5658
5659
5660
5661
5662
5663
5664
5665
5666
5667
5668
5669
5670
5671
5672
5673
5674
5675
5676
5677
5678
5679
5680
5681
5682
5683
5684
5685
5686
5687
5688
5689
5690
5691
5692
5693
5694
5695
5696
5697
5698
5699
5700
5701
5702
5703
5704
5705
5706
5707
5708
5709
5710
5711
5712
5713
5714
5715
5716
5717
5718
5719
5720
5721
5722
5723
5724
5725
5726
5727
5728
5729
5730
5731
5732
5733
5734
5735
5736
5737
5738
5739
5740
5741
5742
5743
5744
5745
5746
5747
5748
5749
5750
5751
5752
5753
5754
5755
5756
5757
5758
5759
5760
5761
5762
5763
5764
5765
5766
5767
5768
5769
5770
5771
5772
5773
5774
5775
5776
5777
5778
5779
5780
5781
5782
5783
5784
5785
5786
5787
5788
5789
5790
5791
5792
5793
5794
5795
5796
5797
5798
5799
5800
5801
5802
5803
5804
5805
5806
5807
5808
5809
5810
5811
5812
5813
5814
5815
5816
5817
5818
5819
5820
5821
5822
5823
5824
5825
5826
5827
5828
5829
5830
5831
5832
5833
5834
5835
5836
5837
5838
5839
5840
5841
5842
5843
5844
5845
5846
5847
5848
5849
5850
5851
5852
5853
5854
5855
5856
5857
5858
5859
5860
5861
5862
5863
5864
5865
5866
5867
5868
5869
5870
5871
5872
5873
5874
5875
5876
5877
5878
5879
5880
5881
5882
5883
5884
5885
5886
5887
5888
5889
5890
5891
5892
5893
5894
5895
5896
5897
5898
5899
5900
5901
5902
5903
5904
5905
5906
5907
5908
5909
5910
5911
5912
5913
5914
5915
5916
5917
5918
5919
5920
5921
5922
5923
5924
5925
5926
5927
5928
5929
5930
5931
5932
5933
5934
5935
5936
5937
5938
5939
5940
5941
5942
5943
5944
5945
5946
5947
5948
5949
5950
5951
5952
5953
5954
5955
5956
5957
5958
5959
5960
5961
5962
5963
5964
5965
5966
5967
5968
5969
5970
5971
5972
5973
5974
5975
5976
5977
5978
5979
5980
5981
5982
5983
5984
5985
5986
5987
5988
5989
5990
5991
5992
5993
5994
5995
5996
5997
5998
5999
6000
6001
6002
6003
6004
6005
6006
6007
6008
6009
6010
6011
6012
6013
6014
6015
6016
6017
6018
6019
6020
6021
6022
6023
6024
6025
6026
6027
6028
6029
6030
6031
6032
6033
6034
6035
6036
6037
6038
6039
6040
6041
6042
6043
6044
6045
6046
6047
6048
6049
6050
6051
6052
6053
6054
6055
6056
6057
6058
6059
6060
6061
6062
6063
6064
6065
6066
6067
6068
6069
6070
6071
6072
6073
6074
6075
6076
6077
6078
6079
6080
6081
6082
6083
6084
6085
6086
6087
6088
6089
6090
6091
6092
6093
6094
6095
6096
6097
6098
6099
6100
6101
6102
6103
6104
6105
6106
6107
6108
6109
6110
6111
6112
6113
6114
6115
6116
6117
6118
6119
6120
6121
6122
6123
6124
6125
6126
6127
6128
6129
6130
6131
6132
6133
6134
6135
6136
6137
6138
6139
6140
6141
6142
6143
6144
6145
6146
6147
6148
6149
6150
6151
6152
6153
6154
6155
6156
6157
6158
6159
6160
6161
6162
6163
6164
6165
6166
6167
6168
6169
6170
6171
6172
6173
6174
6175
6176
6177
6178
6179
6180
6181
6182
6183
6184
6185
6186
6187
6188
6189
6190
6191
6192
6193
6194
6195
6196
6197
6198
6199
6200
6201
6202
6203
6204
6205
6206
6207
6208
6209
6210
6211
6212
6213
6214
6215
6216
6217
6218
6219
6220
6221
6222
6223
6224
6225
6226
6227
6228
6229
6230
6231
6232
6233
6234
6235
6236
6237
6238
6239
6240
6241
6242
6243
6244
6245
6246
6247
6248
6249
6250
6251
6252
6253
6254
6255
6256
6257
6258
6259
6260
6261
6262
6263
6264
6265
6266
6267
6268
6269
6270
6271
6272
6273
6274
6275
6276
6277
6278
6279
6280
6281
6282
6283
6284
6285
6286
6287
6288
6289
6290
6291
6292
6293
6294
6295
6296
6297
6298
6299
6300
6301
6302
6303
6304
6305
6306
6307
6308
6309
6310
6311
6312
6313
6314
6315
6316
6317
6318
6319
6320
6321
6322
6323
6324
6325
6326
6327
6328
6329
6330
6331
6332
6333
6334
6335
6336
6337
6338
6339
6340
6341
6342
6343
6344
6345
6346
6347
6348
6349
6350
6351
6352
6353
6354
6355
6356
6357
6358
6359
6360
6361
6362
6363
6364
6365
6366
6367
6368
6369
6370
6371
6372
6373
6374
6375
6376
6377
6378
6379
6380
6381
6382
6383
6384
6385
6386
6387
6388
6389
6390
6391
6392
6393
6394
6395
6396
6397
6398
6399
6400
6401
6402
6403
6404
6405
6406
6407
6408
6409
6410
6411
6412
6413
6414
6415
6416
6417
6418
6419
6420
6421
6422
6423
6424
6425
6426
6427
6428
6429
6430
6431
6432
6433
6434
6435
6436
6437
6438
6439
6440
6441
6442
6443
6444
6445
6446
6447
6448
6449
6450
6451
6452
6453
6454
6455
6456
6457
6458
6459
6460
6461
6462
6463
6464
6465
6466
6467
6468
6469
6470
6471
6472
6473
6474
6475
6476
6477
6478
6479
6480
6481
6482
6483
6484
6485
6486
6487
6488
6489
6490
6491
6492
6493
6494
6495
6496
6497
6498
6499
6500
6501
6502
6503
6504
6505
6506
6507
6508
6509
6510
6511
6512
6513
6514
6515
6516
6517
6518
6519
6520
6521
6522
6523
6524
6525
6526
6527
6528
6529
6530
6531
6532
6533
6534
6535
6536
6537
6538
6539
6540
6541
6542
6543
6544
6545
6546
6547
6548
6549
6550
6551
6552
6553
6554
6555
6556
6557
6558
6559
6560
6561
6562
6563
6564
6565
6566
6567
6568
6569
6570
6571
6572
6573
6574
6575
6576
6577
6578
6579
6580
6581
6582
6583
6584
6585
6586
6587
6588
6589
6590
6591
6592
6593
6594
6595
6596
6597
6598
6599
6600
6601
6602
6603
6604
6605
6606
6607
6608
6609
6610
6611
6612
6613
6614
6615
6616
6617
6618
6619
6620
6621
6622
6623
6624
6625
6626
6627
6628
6629
6630
6631
6632
6633
6634
6635
6636
6637
6638
6639
6640
6641
6642
6643
6644
6645
6646
6647
6648
6649
6650
6651
6652
6653
6654
6655
6656
6657
6658
6659
6660
6661
6662
6663
6664
6665
6666
6667
6668
6669
6670
6671
6672
6673
6674
6675
6676
6677
6678
6679
6680
6681
6682
6683
6684
6685
6686
6687
6688
6689
6690
6691
6692
6693
6694
6695
6696
6697
6698
6699
6700
6701
6702
6703
6704
6705
6706
6707
6708
6709
6710
6711
6712
6713
6714
6715
6716
6717
6718
6719
6720
6721
6722
6723
6724
6725
6726
6727
6728
6729
6730
6731
6732
6733
6734
6735
6736
6737
6738
6739
6740
6741
6742
6743
6744
6745
6746
6747
6748
6749
6750
6751
6752
6753
6754
6755
6756
6757
6758
6759
6760
6761
6762
6763
6764
6765
6766
6767
6768
6769
6770
6771
6772
6773
6774
6775
6776
6777
6778
6779
6780
6781
6782
6783
6784
6785
6786
6787
6788
6789
6790
6791
6792
6793
6794
6795
6796
6797
6798
6799
6800
6801
6802
6803
6804
6805
6806
6807
6808
6809
6810
6811
6812
6813
6814
6815
6816
6817
6818
6819
6820
6821
6822
6823
6824
6825
6826
6827
6828
6829
6830
6831
6832
6833
6834
6835
6836
6837
6838
6839
6840
6841
6842
6843
6844
6845
6846
6847
6848
6849
6850
6851
6852
6853
6854
6855
6856
6857
6858
6859
6860
6861
6862
6863
6864
6865
6866
6867
6868
6869
6870
6871
6872
6873
6874
6875
6876
6877
6878
6879
6880
6881
6882
6883
6884
6885
6886
6887
6888
6889
6890
6891
6892
6893
6894
6895
6896
6897
6898
6899
6900
6901
6902
6903
6904
6905
6906
6907
6908
6909
6910
6911
6912
6913
6914
6915
6916
6917
6918
6919
6920
6921
6922
6923
6924
6925
6926
6927
6928
6929
6930
6931
6932
6933
6934
6935
6936
6937
6938
6939
6940
6941
6942
6943
6944
6945
6946
6947
6948
6949
6950
6951
6952
6953
6954
6955
6956
6957
6958
6959
6960
6961
6962
6963
6964
6965
6966
6967
6968
6969
6970
6971
6972
6973
6974
6975
6976
6977
6978
6979
6980
6981
6982
6983
6984
6985
6986
6987
6988
6989
6990
6991
6992
6993
6994
6995
6996
6997
6998
6999
7000
7001
7002
7003
7004
7005
7006
7007
7008
7009
7010
7011
7012
7013
7014
7015
7016
7017
7018
7019
7020
7021
7022
7023
7024
7025
7026
7027
7028
7029
7030
7031
7032
7033
7034
7035
7036
7037
7038
7039
7040
7041
7042
7043
7044
7045
7046
7047
7048
7049
7050
7051
7052
7053
7054
7055
7056
7057
7058
7059
7060
7061
7062
7063
7064
7065
7066
7067
7068
7069
7070
7071
7072
7073
7074
7075
7076
7077
7078
7079
7080
7081
7082
7083
7084
7085
7086
7087
7088
7089
7090
7091
7092
7093
7094
7095
7096
7097
7098
7099
7100
7101
7102
7103
7104
7105
7106
7107
7108
7109
7110
7111
7112
7113
7114
7115
7116
7117
7118
7119
7120
7121
7122
7123
7124
7125
7126
7127
7128
7129
7130
7131
7132
7133
7134
7135
7136
7137
7138
7139
7140
7141
7142
7143
7144
7145
7146
7147
7148
7149
7150
7151
7152
7153
7154
7155
7156
7157
7158
7159
7160
7161
7162
7163
7164
7165
7166
7167
7168
7169
7170
7171
7172
7173
7174
7175
7176
7177
7178
7179
7180
7181
7182
7183
7184
7185
7186
7187
7188
7189
7190
7191
7192
7193
7194
7195
7196
7197
7198
7199
7200
7201
7202
7203
7204
7205
7206
7207
7208
7209
7210
7211
7212
7213
7214
7215
7216
7217
7218
7219
7220
7221
7222
7223
7224
7225
7226
7227
7228
7229
7230
7231
7232
7233
7234
7235
7236
7237
7238
7239
7240
7241
7242
7243
7244
7245
7246
7247
7248
7249
7250
7251
7252
7253
7254
7255
7256
7257
7258
7259
7260
7261
7262
7263
7264
7265
7266
7267
7268
7269
7270
7271
7272
7273
7274
7275
7276
7277
7278
7279
7280
7281
7282
7283
7284
7285
7286
7287
7288
7289
7290
7291
7292
7293
7294
7295
7296
7297
7298
7299
7300
7301
7302
7303
7304
7305
7306
7307
7308
7309
7310
7311
7312
7313
7314
7315
7316
7317
7318
7319
7320
7321
7322
7323
7324
7325
7326
7327
7328
7329
7330
7331
7332
7333
7334
7335
7336
7337
7338
7339
7340
7341
7342
7343
7344
7345
7346
7347
7348
7349
7350
7351
7352
7353
7354
7355
7356
7357
7358
7359
7360
7361
7362
7363
7364
7365
7366
7367
7368
7369
7370
7371
7372
7373
7374
7375
7376
7377
7378
7379
7380
7381
7382
7383
7384
7385
7386
7387
7388
7389
7390
7391
7392
7393
7394
7395
7396
7397
7398
7399
7400
7401
7402
7403
7404
7405
7406
7407
7408
7409
7410
7411
7412
7413
7414
7415
7416
7417
7418
7419
7420
7421
7422
7423
7424
7425
7426
7427
7428
7429
7430
7431
7432
7433
7434
7435
7436
7437
7438
7439
7440

- docs: unify protocol lists
  
  We boast support for 25 transfer protocols. Make sure the lists are
  consistent
  
  Closes #5384

- OpenSSL: have CURLOPT_CRLFILE imply CURLSSLOPT_NO_PARTIALCHAIN
  
  ... to avoid an OpenSSL bug that otherwise makes the CRL check to fail.
  
  Reported-by: Michael Kaufmann
  Fixes #5374
  Closes #5376

- tls13-ciphers.d: shorten the Arg

- sasl-authzid.d: add Arg: and shorten the desc

- cert-type.d: mention the available types in the desc

- tool: shorten 3 --help descriptions
  
  --happy-eyeballs-timeout-ms, --resolve and --ssl-revoke-best-effort
  
  gen.pl already warned about these lines but we didn't listen
  
  Closes #5379

- configure: the wolfssh backend does not provide SCP
  
  Closes #5387

- RELEASE-NOTES: synced

- url: reject too long input when parsing credentials
  
  Since input passed to libcurl with CURLOPT_USERPWD and
  CURLOPT_PROXYUSERPWD circumvents the regular string length check we have
  in Curl_setstropt(), the input length limit is enforced in
  Curl_parse_login_details too, separately.
  
  Reported-by: Thomas Bouzerar
  Closes #5383

- list-only.d: this option existed already in 4.0

Jay Satiro (12 May 2020)
- retry-all-errors.d: Shorten the summary line
  
  Follow-up to b995bb5 from a few moments ago.
  
  Reported-by: Daniel Stenberg
  
  Ref: https://github.com/curl/curl/commit/b995bb5#r39108929

- [denzor brought this change]

  easy: fix dangling pointer on easy_perform fail
  
  Closes https://github.com/curl/curl/pull/5363

- tool: Add option --retry-all-errors to retry on any error
  
  The "sledgehammer" of retrying.
  
  Closes https://github.com/curl/curl/pull/5185

Daniel Stenberg (12 May 2020)
- [James Le Cuirot brought this change]

  libcurl.pc: Merge Libs.private into Libs for static-only builds
  
  A project being built entirely statically will call pkg-config with
  --static, which utilises the Libs.private field. Conversely it will
  not use --static when not being built entirely statically, even if
  there is only a static build of libcurl available. This will most
  likely cause the build to fail due to underlinking unless we merge the
  Libs fields.
  
  Consider that this is what the Meson build system does when it
  generates pkg-config files.
  
  I have also reflected this in the --libs argument of curl-config even
  though REQUIRE_LIB_DEPS always seems to be "yes" anyway.
  
  Closes #5373

- [Peter Wu brought this change]

  CMake: fix runtests.pl with CMake, add new test targets
  
    * runtests.pl:
      - Fix out-of-tree build under CMake when srcdir is not set. Default
        srcdir to the location of runtests.pl.
      - Add a hack to allow CMake to use the TFLAGS option as documented
        in tests/README and used in scripts/travis/script.sh.
    * Bump CMake version to 3.2 for USES_TERMINAL, dropping Debian Jessie
      support (no one should care, it is already EOL.).
    * Remove CTest since it defines its own 'test' target with no tests
      since all unittests are already broken and not built by default.
    * Add new test targets based on the options from Makefile.am. Since
      new test targets are rarely added, I opted for duplicating the
      runtests.pl options as opposed to creating a new Makefile.inc file.
      Use top-level target names (test-x) instead of x-test since that is
      used by CI and others.
  
  Closes #5358

- [Peter Wu brought this change]

  CMake: do not build test programs by default
  
  The default target should only build libcurl and curl. Add a dedicated
  'testdeps' target which will be used later when running tests. Note that
  unittests are currently broken in CMake and already excluded.
  
  Closes #5368

- FILEFORMAT: moved up the variables section and further polished

- runtests: remove ftp2 support, not used
  
  We once supported two separate ftp instances in the test suite. Has not
  been used the last decade.
  
  Closes #5375

- url: sort the protocol schemes in rough popularity order
  
  When looking for a protocol match among supported schemes, check the
  most "popular" schemes first. It has zero functionality difference and
  for all practical purposes a speed difference will not be measureable
  but it still think it makes sense to put the least likely matches last.
  
  "Popularity" based on the 2019 user survey.
  
  Closes #5377

Marc Hoersken (11 May 2020)
- test1238: avoid tftpd being busy for tests shortly following
  
  The tftpd server may still be busy if the total timeout of
  25 seconds has not been reached or no sread error was received
  during or after the execution of the timeout test 1238.
  
  Once the next TFTP test comes around (eg. 1242 or 1243),
  those will fail because the tftpd server is still waiting
  on data from curl due to the UDP protocol being stateless
  and having no connection close. On Linux this error may not
  happen, because ICMP errors generated due to a swrite error
  can also be returned async on the next sread call instead.
  
  Therefore we will now just kill the tftpd server after test
  1238 to make sure that the following tests are not affected.
  
  This enables us to no longer ignore tests 1242, 1243, 2002
  and 2003 on the CI platforms CirrusCI and AppVeyor.
  
  Assisted-by: Peter Wu
  Closes #5364

Daniel Stenberg (11 May 2020)
- write-out.d: added "response_code"

- KNOWN_BUGS: Build with staticly built dependency
  
  I rewrote the item 5.4 to be more generic about static dependencies.

- ROADMAP: remove old entries
  
  MQTT - the start has already landed
  
  tiny-curl - also mostly landed and is a continuous work
  
  make menuconfig - basically no interest from users, not pushing there

- [Peter Wu brought this change]

  travis: Add ngtcp2 and quiche tests for CMake
  
  To avoid an explosion of jobs, extend the existing CMake tests with
  ngtcp2 and quiche support. macOS was previously moved to GitHub actions,
  so the non-Linux case can be dropped.

- [Peter Wu brought this change]

  CMake: add ENABLE_ALT_SVC option
  
  Tested alt-svc with quiche. While at it, add missing MultiSSL reporting
  (not tested).

- [Peter Wu brought this change]

  CMake: add HTTP/3 support (ngtcp2+nghttp3, quiche)
  
  Add three new CMake Find modules (using the curl license, but I grant
  others the right to apply the CMake BSD license instead).
  
  This CMake config is simpler than the autotools one because it assumes
  ngtcp2 and nghttp3 to be used together. Another difference is that this
  CMake config checks whether QUIC is actually supported by the TLS
  library (patched OpenSSL or boringssl) since this can be a common
  configuration mistake that could result in build errors later.
  
  Unlike autotools, CMake does not warn you that the features are
  experimental. The user is supposed to already know that and read the
  documentation. It requires a very special build environment anyway.
  
  Tested with ngtcp2+OpenSSL+nghttp3 and quiche+boringssl, both built from
  current git master. Use `LD_DEBUG=files src/curl |& grep need` to figure
  out which features (libldap-2.4, libssh2) to disable due to conflicts
  with boringssl.
  
  Closes #5359

Marc Hoersken (10 May 2020)
- tests/server/tftpd.c: fix include and enhance debug logging
  
  setjmp.h should only be included if HAVE_SETJMP_H is defined.
  
  Add additional log statements to see wether reads and writes
  are blocking or finishing before an alarm signal is received.
  
  Assisted-by: Peter Wu
  Part of #5364

Daniel Stenberg (10 May 2020)
- tool_operate: only set CURLOPT_SSL_OPTIONS if SSL support is present
  
  Reported-by: Marcel Raad
  Follow-up to 148534db5
  Fixes #5367
  Closes #5369

Marc Hoersken (9 May 2020)
- appveyor: update comments to be clear about toolchain
  
  - CMake-based MSYS builds use mingw-w64 to cross-compile.
  - autotools-based builds are compiled using msys2-devel.
  
  The difference is that the later ones are not cross-compiled
  to Windows and instead require the msys2 runtime to be present.
  
  At the moment only the Azure Pipelines CI builds actually
  run autotools-based cross-compilation builds for Windows.

- TODO: update regarding missing Schannel features
  
  Some aspects have already been implemented over the years.
  
  15.1 Client certificates are now supported:
  
  - System stores via e35b0256eb34f1fe562e3e2a2615beb50a391c52
  - PKCS#12 files via 0fdf96512613574591f501d63fe49495ba40e1d5
  
  15.2 Ciphers can now be specified through:
  
  - Algorithms via 9aefbff30d280c60fc9d8cc3e0b2f19fc70a2f28
  
  Reviewed-by: Daniel Stenberg and Marcel Raad
  Closes #5358

Daniel Stenberg (8 May 2020)
- checksrc: close the .checksrc file handle when done reading

- RELEASE-NOTES: synced
  
  And bumped next version to 7.71.0

- [Gilles Vollant brought this change]

  CURLOPT_SSL_OPTIONS: add *_NATIVE_CA to use Windows CA store (with openssl)
  
  Closes #4346

- TODO: native IDN support on macOS

- urlapi: accept :: as a valid IPv6 address
  
  Text 1560 is extended to verify.
  
  Reported-by: Pavel Volgarev
  Fixes #5344
  Closes #5351

- THANKS-filter: Peter Wang

- [Peter Wang brought this change]

  *_sspi: fix bad uses of CURLE_NOT_BUILT_IN
  
  Return CURLE_AUTH_ERROR instead of CURLE_NOT_BUILT_IN for other
  instances of QuerySecurityPackageInfo failing, as in
  commit 2a81439553286f12cd04a4bdcdf66d8e026d8201.
  
  Closes #5355

- docs/HTTP3: add qlog to the quiche build instruction

- ngtcp2: introduce qlog support
  
  If the QLOGDIR environment variable is set, enable qlogging.
  
  ... and create Curl_qlogdir() in the new generic vquic/vquic.c file for
  QUIC functions that are backend independent.
  
  Closes #5353

- ntlm_sspi: fix bad use of CURLE_NOT_BUILT_IN
  
  That return code is reserved for build-time conditional code not being
  present while this was a regular run-time error from a Windows API.
  
  Reported-by: wangp on github
  Fixes #5349
  Closes #5350

- runtests: show elapsed test time with higher precision (ms)

- RELEASE-NOTES: synced

- http2: simplify and clean up trailer handling
  
  Triggered by a crash detected by OSS-Fuzz after the dynbuf introduction in
  ed35d6590e72. This should make the trailer handling more straight forward and
  hopefully less error-prone.
  
  Deliver the trailer header to the callback already at receive-time. No
  longer caches the trailers to get delivered at end of stream.
  
  Bug: https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=22030
  Closes #5348

Marc Hoersken (7 May 2020)
- appveyor: disable test 1139 instead of ignoring it
  
  Spending time on manpage checking makes no sense
  for these builds due to lacking manpage support.

- appveyor: disable flaky test 1501 and ignore broken 1056
  
  Test 1501 is flaky on Windows CI due to being time sensitive
  and the testsuite relying on taskkill.exe to check for the
  existance of processes which can take to much time itself.
  
  Test 1056 is broken in autotools-based Windows builds due
  to scope ID support missing in these builds at the moment.

- test613.pl: make tests 613 and 614 work with OpenSSH for Windows
  
  OpenSSH for Windows shows group and other/world permissions as *,
  because those concepts do not exist on Windows. It also does not
  show the current or parent directory, so we just ignore those.
  
  Reviewed-by: Daniel Stenberg
  Closes #5328

Daniel Stenberg (6 May 2020)
- runtests: set +x mode again

- libssh2: convert over to use dynbuf
  
  In my very basic test that lists sftp://127.0.0.1/tmp/, this patched
  code makes 161 allocations compared to 194 in git master. A 17%
  reduction.
  
  Closes #5336

- travis: add "qlog" as feature in the quiche build

- quiche: enable qlog output
  
  quiche has the potential to log qlog files. To enable this, you must
  build quiche with the qlog feature enabled `cargo build --features
  qlog`. curl then passes a file descriptor to quiche, which takes
  ownership of the file. The FD transfer only works on UNIX.
  
  The convention is to enable logging when the QLOGDIR environment is
  set. This should be a path to a folder where files are written with the
  naming template <SCID>.qlog.
  
  Co-authored-by: Lucas Pardue
  Replaces #5337
  Closes #5341

- urldata.h: remove #define HEADERSIZE, not used anymore
  
  Follow-up to ed35d6590e72c

- ngtcp2: convert to dynbuf
  
  Closes #5335

- connect: make happy eyeballs work for QUIC (again)
  
  Follow-up from dbd16c3e256c6c (regression in 7.70.0)
  
  Closes #5334

- connect: add two asserts to clue code analyzers in a little

- http_proxy: ported to use dynbuf instead of a static size buffer
  
  Removes a 16K static buffer from the easy handle. Simplifies the code.

- dynbuf: introduce internal generic dynamic buffer functions
  
  A common set of functions instead of many separate implementations for
  creating buffers that can grow when appending data to them. Existing
  functionality has been ported over.
  
  In my early basic testing, the total number of allocations seem at
  roughly the same amount as before, possibly a few less.
  
  See docs/DYNBUF.md for a description of the API.
  
  Closes #5300

- runtests: remove sleep calls
  
  Remove many one second sleeps that were done *after* each newly started
  test server already has been verified. They should not have any purpose
  there.
  
  Closes #5323

- asyn-*: remove support for never-used NULL entry pointers
  
  ... and instead convert those to asserts to make sure they are truly
  never NULL.
  
  Closes #5324

- [Emil Engler brought this change]

  doc: Rename VERSIONS to VERSIONS.md as it already has Markdown syntax
  
  Closes #5325

Jay Satiro (2 May 2020)
- asyn-thread: fix cppcheck warning
  
  - Check for NULL entry parameter before attempting to deref entry in
    Curl_resolver_is_resolved, like is already done in asyn-ares.
  
  This is to silence cppcheck which does not seem to understand that
  asyn-ares and asyn-thread have separate Curl_resolver_is_resolved
  and those units are mutually exclusive. Prior to this change it warned
  of a scenario where asyn-thread's Curl_resolver_is_resolved is called
  with a NULL entry from asyn-ares, but that couldn't happen.
  
  Reported-by: rl1987@users.noreply.github.com
  
  Fixes https://github.com/curl/curl/issues/5326

- select: fix overflow protection in Curl_socket_check
  
  Follow-up to a96c752 which changed the timeout_ms type from time_t to
  timediff_t.
  
  Ref: https://github.com/curl/curl/pull/5240
  
  Closes https://github.com/curl/curl/pull/5286

Marc Hoersken (2 May 2020)
- sockfilt: make select_ws stop waiting on exit signal event
  
  This makes sure that select_ws behaves similar to real select
  which stops waiting on a signal handler being triggered.
  
  This makes it possible to gracefully stop sockfilt.exe on
  Windows with taskkill /IM sockfilt.exe (without /F force flag).
  
  Reviewed-by: Jay Satiro
  Part of #5260

- tests/server/util.[ch]: add exit event to stop waiting on Windows
  
  This commit adds a global exit event to the test servers that
  Windows-specific wait routines can use to get triggered if the
  program was signaled to be terminated, eg. select_ws in sockfilt.c
  
  The exit event will be managed by the signal handling code and is
  set to not reset automatically to support multiple wait routines.
  
  Reviewed-by: Jay Satiro
  Closes #5260

- tests/server/util.c: fix thread handle not being closed
  
  Reviewed-by: Jay Satiro
  Part of #5260

- tests/server/util.c: use raise instead of calling signal handler
  
  Use raise to trigger signal handler instead of calling it
  directly and causing potential unexpected control flow.
  
  Reviewed-by: Jay Satiro
  Part of #5260

- tests: add support for SSH server variant specific transfer paths
  
  OpenSSH for Windows requires paths in the format of /C:/
  instead of the pseudo-POSIX paths /cygdrive/c/ or just /c/
  
  Reviewed-by: Daniel Stenberg
  Closes #5298

Daniel Stenberg (2 May 2020)
- RELEASE-NOTES: synced

- libssh2: set the expected total size in SCP upload init
  
  ... as otherwise the progress callback gets called without that
  information, making the progress meter have less info.
  
  Reported-by: Murugan Balraj
  Bug: https://curl.haxx.se/mail/archive-2020-05/0000.html
  Closes #5317

- runtests: make the logmsg from the ssh server only show in verbose

- tests: make test 1248 + 1249 use %NOLISTENPORT
  
  ... instead of a port of a non-running server so that it works
  stand-alone.
  
  Closes #5318

- examples: remove asiohiper.cpp
  
  This example has repeatedly been reported to contain bugs, and as users
  copy and paste code from this into production, I now deem it better to
  not provide the example at all.
  
  Closes #5090
  Closes #5322

- [Emil Engler brought this change]

  doc: add missing closing parenthesis in CURLINFO_SSL_VERIFYRESULT.3
  
  Closes #5320

- [Emil Engler brought this change]

  KNOWN_BUGS: Remove "curl --upload-file . hang if delay in STDIN"
  
  It was fixed in 9a2cbf3
  
  Closes #5319

- cirrus: disable SFTP and SCP tests
  
  ... as we can't seem to start the sshd server on it. Those problems
  existed before d1239b50bececd (running the SSH server on a random port),
  but they're more noticable now since there are more failed attempts in
  the logs.
  
  Closes #5315

- [Emil Engler brought this change]

  runtests: fix typo in the existence of disabled tests checker
  
  Closes #5316

Dan Fandrich (30 Apr 2020)
- test75: Remove precheck test
  
  This has not been needed since commit 9fa42bed and often prevents it
  from running at all with dynamic test ports.

- tests: Stop referring to server ports when they're not used
  
  Several tests referred to specific server ports even when the test
  didn't actually use that server or specify that it's needed. In such
  cases, the test harness substitutes the text "[not running]" as the port
  number which causes many such tests to fail due to the inability to
  parse the URL.  These tests are changed to use %NOLISTENPORT which will
  always be substituted correctly.

Daniel Stenberg (30 Apr 2020)
- [Emil Engler brought this change]

  GnuTLS: Backend support for CURLINFO_SSL_VERIFYRESULT
  
  Closes #5287

- conncache: various concept cleanups
  
  More connection cache accesses are protected by locks.
  
  CONNCACHE_* is a beter prefix for the connection cache lock macros.
  
  Curl_attach_connnection: now called as soon as there's a connection
  struct available and before the connection is added to the connection
  cache.
  
  Curl_disconnect: now assumes that the connection is already removed from
  the connection cache.
  
  Ref: #4915
  Closes #5009

- tests: tests: run stunnel for HTTPS and FTPS on dynamic ports
  
  As stunnel is an external tool and it has no specific option to export
  the actually used port number when asked to listen to 0, runtests
  instead iterates over ten randomly picked high number ports and sticks
  to the first one stunnel can listen to.
  
  Closes #5267

- tests: pick a random port number for SSH
  
  Since sshd doesn't have such an option by itself, we iterate over a
  series of random ports until one works.
  
  Closes #5273

- [Rikard Falkeborn brought this change]

  libtest/cmake: Remove commented code
  
  These were commented out in e9dd0998706a when Makefile.inc was included
  instead. 11 years have passed since then and the commented code is of
  course very outdated. Remove it to avoid confusion.
  
  Closes #5311

- schannel: source code reindent
  
  White space edits only. Conform better to standard curl source code
  indenting style.
  
  Closes #5305

Kamil Dudka (29 Apr 2020)
- test1177: look for curl.h in source directory
  
  If we use a separate build directory, there is no copy of the header.
  
  Closes #5310

- tests: look for preprocessed tests in build directory
  
  ... which is not always the same directory as source directory
  
  Closes #5310

Daniel Stenberg (29 Apr 2020)
- RELEASE-NOTES: synced
  
  ... and bumped curlver.h to 7.70.1

Version 7.70.0 (29 Apr 2020)

Daniel Stenberg (29 Apr 2020)
- RELEASE-NOTES: 7.70.0

- THANKS: synced with the 7.70.0 release

- headers: copyright range fix

- [Rikard Falkeborn brought this change]

  doh: Constify some input pointers
  
  Closes #5306

- nss: check for PK11_CreateDigestContext() returning NULL
  
  ... to avoid crashes!
  
  Reported-by: Hao Wu
  Fixes #5302
  Closes #5303

- travis: bump the wolfssl CI build to use 4.4.0
  
  Closes #5301

- copyright updates: adjust year ranges

Marc Hoersken (26 Apr 2020)
- CI: do not include */ci branches in PR builds
  
  Align Azure Pipelines with GitHub Actions.

Daniel Stenberg (25 Apr 2020)
- runtests: check for the disabled tests relative srcdir
  
  To make it work correctly for out-of-tree builds.
  
  Follow-up to 75e8feb6fb08b
  
  Bug: https://github.com/curl/curl/pull/5288#issuecomment-619346389
  Reported-by: Marcel Raad
  Closes #5297

- runtests: revert commenting out a line I did for debugging
  
  Follow-up to 11091cd4d. It was not meant to be pushed!

- smtp: set auth correctly
  
  Regression since 7.69.0 and 68fb25fa3fcff.
  
  The code wrongly assigned 'from' instead of 'auth' which probably was a
  copy and paste mistake from other code, leading to that auth could
  remain NULL and later cause an error to be returned.
  
  Assisted-by: Eric Sauvageau
  Fixes #5294
  Closes #5295

Marcel Raad (25 Apr 2020)
- lib: clean up whitespace
  
  This fixes CodeFactor warnings.

Daniel Stenberg (25 Apr 2020)
- [Anderson Toshiyuki Sasaki brought this change]

  libssh: avoid options override by configuration files
  
  Previously, options set explicitly through command line options could be
  overridden by the configuration files parsed automatically when
  ssh_connect() was called.
  
  By calling ssh_options_parse_config() explicitly, the configuration
  files are parsed before setting the options, avoiding the options
  override.  Once the configuration files are parsed, the automatic
  configuration parsing is not executed.
  
  Fixes #4972
  Closes #5283
  Signed-off-by: Anderson Toshiyuki Sasaki <ansasaki@redhat.com>

- runtests: when <killserver> mentions http, kill http/2 too
  
  Since the http2 test server is a mere proxy that needs to know about the
  dynamic port the HTTP server is using, it too needs to get restarted
  when the http server is killed.
  
  A regression caused by 80d6515.
  
  Fixes #5289
  Closes #5291

- [Yuri Slobodyanyuk brought this change]

  docs: fix two typos
  
  Closes #5292

- [Emil Engler brought this change]

  tests/git: ignore mqttd and port files
  
  Closes #5290

- tests: make runtests check that disabled tests exists
  
  ... and error out if so. Removed '536' from DISABLED as there is no such
  test file.
  
  Closes #5288

- test1154: set a proper name

- select: make Curl_socket_check take timediff_t timeout
  
  Coverity found CID 1461718:
  
  Integer handling issues (CONSTANT_EXPRESSION_RESULT) "timeout_ms >
  9223372036854775807L" is always false regardless of the values of its
  operands. This occurs as the logical second operand of "||".
  
  Closes #5240

- [i-ky brought this change]

  libcurl-multi.3: added missing full stop
  
  Closes #5285

Jay Satiro (22 Apr 2020)
- transfer: Switch PUT to GET/HEAD on 303 redirect
  
  Prior to this change if there was a 303 reply to a PUT request then
  the subsequent request to respond to that redirect would also be a PUT.
  It was determined that was most likely incorrect based on the language
  of the RFCs. Basically 303 means "see other" resource, which implies it
  is most likely not the same resource, therefore we should not try to PUT
  to that different resource.
  
  Refer to the discussions in #5237 and #5248 for more information.
  
  Fixes https://github.com/curl/curl/issues/5237
  Closes https://github.com/curl/curl/pull/5248

Daniel Stenberg (22 Apr 2020)
- lib/mk-ca-bundle: skip empty certs
  
  Reviewed-by: Emil Engler
  Reported-by: Ashwin Metpalli
  Fixes #5278
  Closes #5280

- version: skip idn2_check_version() check and add precaution
  
  A gcc-10's -fanalyze complaint made me spot and do these improvements.
  
  Closes #5281

- RELEASE-NOTES: synced

- [Brian Bergeron brought this change]

  curl.h: update comment typo
  
  "routines with be invoked" -> "routines will be invoked"
  
  Closes #5279

- [Emil Engler brought this change]

  GnuTLS: Don't skip really long certificate fields
  
  Closes #5271

- gnutls: bump lowest supported version to 3.1.10
  
  GnuTLS 3.1.10 added new functions we want to use. That version was
  released on Mar 22, 2013. Removing support for older versions also
  greatly simplifies the code.
  
  Ref: #5271
  Closes #5276

- mqtt: make NOSTATE get within the debug name array

- tests: run the RTSP test server on a dynamic port number
  
  To avoid port collisions.
  
  Closes #5272

- tests: add %NOLISTENPORT and use it
  
  The purpose with this variable is to provide a port number that is
  reasonably likely to not have a listener on the local host so that tests
  can try connect failures against it. It uses port 47 - "reserved"
  according to IANA.
  
  Updated six tests to use it instead of the previous different ports.
  
  Assisted-by: Emil Engler
  Closes #5270

- mqtt: remove code with no purpose
  
  Detected by Coverity. CID 1462319.
  
  "The same code is executed when the condition result is true or false,
  because the code in the if-then branch and after the if statement is
  identical."
  
  Closes #5275

- mqtt: fix Curl_read()  error handling while reading remaining length
  
  Detected by Coverity. CID 1462320.
  
  Closes #5274

- server/tftpd: fix compiler warning
  
  Follow-up from 369ce38ac1d
  Reported-by: Marc Hörsken

- http: free memory when Alt-Used header creation fails due to OOM
  
  Reported-by: James Fuller
  Fixes #5268
  Closes #5269

Daniel Gustafsson (20 Apr 2020)
- lib: fix typos in comments and errormessages
  
  This fixes a few randomly spotted typos in recently merged code, most
  notably one in a userfacing errormessage the schannel code.

Daniel Stenberg (20 Apr 2020)
- tests: run the SOCKS test server on a dynamic port number
  
  Closes #5266

- [Johannes Schindelin brought this change]

  multi-ssl: reset the SSL backend on `Curl_global_cleanup()`
  
  When cURL is compiled with support for multiple SSL backends, it is
  possible to configure an SSL backend via `curl_global_sslset()`, but
  only *before* `curl_global_init()` was called.
  
  If another SSL backend should be used after that, a user might be
  tempted to call `curl_global_cleanup()` to start over. However, we did
  not foresee that use case and forgot to reset the SSL backend in that
  cleanup.
  
  Let's allow that use case.
  
  Fixes #5255
  Closes #5257
  Reported-by: davidedec on github
  Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>

- tests: run the TFTP test server on a dynamic port number
  
  Picking a dynamic unused port is better than a fixed to avoid the
  collision risk.
  
  Closes #5265

- mqtt: improve the state machine
  
  To handle PUBLISH before SUBACK and more.
  
  Updated the existing tests and added three new ones.
  
  Reported-by: Christoph Krey
  Bug: https://curl.haxx.se/mail/lib-2020-04/0021.html
  Closes #5246

- runtests: always put test number in servercmd file

- RELEASE-NOTES: synced

- release-notes.pl: fix parsing typo

James Fuller (20 Apr 2020)
- ensure all references to ports are replaced by vars

- add more alt-svc test coverage

Daniel Stenberg (20 Apr 2020)
- test1247: use http server to get the port number set
  
  Follow-up to 0f5db7b263f

- runtests: use a unix domain socket path with the pid in the name
  
  To make it impossible for test cases to access the file name without
  using the proper variable for the purpose.
  
  Closes #5264

Daniel Gustafsson (19 Apr 2020)
- [Mipsters on github brought this change]

  src: Remove C99 constructs to ensure C89 compliance
  
  This fixes the error: 'for' loop initial declaration used outside C99
  mode by declaring the loop increment variable in the beginning of the
  block instead of inside the for loop.
  
  Fixes #5254
  Reviewed-by: Daniel Gustafsson <daniel@yesql.se>

Daniel Stenberg (19 Apr 2020)
- runtests: dummy init the ports variables to avoid warnings
  
  ... and generate something that can help debug test cases.

- [Patrick Monnerat brought this change]

  mime: properly check Content-Type even if it has parameters
  
  New test 669 checks this fix is effective.
  
  Fixes #5256
  Closes #5258
  Reported-by: thanhchungbtc on github

- tests/FILEFORMAT: converted to markdown and extended
  
  Closes #5261

- test1245: make it work with dynamic FTP server port

- test1055: make it work with dynamic FTP port

- test1028: make it run on dynamic FTP server port

- tests: move pingpong server to dynamic listening port
  
  FTP, IMAP, POP3, SMTP and their IPv6 versions are now all on dynamic
  ports
  
  Test 842-845 are unfortunately a bit hard to move over to this concept
  right now and require "default port" still...

- test1056: work with dynamic HTTP ipv6 port

- test1448: work with dynamic HTTP server port

- tests: introduce preprocessed test cases
  
  The runtests script now always performs variable replacement on the
  entire test source file before the test gets executed, and saves the
  updated version in a temporary file (log/test[num]) so that all test
  case readers/servers can use that version (if present) and thus enjoy
  the powers of test case variable substitution.
  
  This is necessary to allow complete port number freedom.
  
  Test 309 is updated to work with a non-fixed port number thanks to this.

- tests: make 2006-2010 handle different port number lengths

- tests: run the sws server on "any port"
  
  Makes the test servers for HTTP and Gopher pop up on a currently unused
  port and runtests adapts to that!
  
  Closes #5247

Marc Hoersken (18 Apr 2020)
- sockfilt: tidy variable naming and data structure in select_ws
  
  This commit does not introduce any logical changes to the code.
  
  Reviewed-by: Jay Satiro and Marcel Raad
  Closes #5238

Daniel Stenberg (17 Apr 2020)
- [Anderson Toshiyuki Sasaki brought this change]

  libssh: Use new ECDSA key types to check known hosts
  
  From libssh 0.9.0, ssh_key_type() returns different key types for ECDSA
  keys depending on the curve.
  
  Signed-off-by: Anderson Toshiyuki Sasaki <ansasaki@redhat.com>
  Fixes #5252
  Closes #5253

Marcel Raad (17 Apr 2020)
- appveyor: add Unicode winbuild jobs
  
  These are cheap as they don't build tests.
  
  Closes https://github.com/curl/curl/pull/5063

Daniel Stenberg (16 Apr 2020)
- mqttd: s/errno/SOCKERRNO
  
  To behave proper on Windows
  Reported-by: Gisle Vanem
  Bug: https://github.com/curl/curl/commit/5e855bbd18f84a02c951be7cac6188276818cdac#r38507132
  Closes #5241

- buildconf: use find -execdir instead, remove -print and the ares files
  
  Follow-up to 1e41bec96a6e
  
  Suggested-by: Marc Hörsken

- [Alexander V. Tikhonov brought this change]

  buildconf: avoid using tempfile when removing files
  
  Closes #5213

- copyright: bump the copyright year range

- scripts/release-notes.pl: accept colon after the Fixes/Closes keywords

- [JP Mens brought this change]

  docs/MQTT: replace confusing 80 by 75
  
  I was a bit surprised by the `80`: first thought: what's HTTP doing
  here? ;)
  
  Closes #5236

- [Brad King brought this change]

  cmake: Avoid MSVC C4273 warnings in send/recv checks
  
  We use `check_c_source_compiles` to check possible send/recv signatures
  by reproducing the forward declarations from system headers.  On Windows
  the `winsock2.h` header adds dll linkage settings to its forward
  declaration.  If ours does not match the compiler warns:
  
      warning C4273: 'recv': inconsistent dll linkage
  
  Add `WINSOCK_API_LINKAGE` to our test signatures when it is defined so
  that our linkage is consistent with that from `winsock2.h`.
  
  Fixes #4764
  Closes #5232

Jay Satiro (14 Apr 2020)
- KNOWN_BUGS: Add entry 'Blocking socket operations'
  
  - Add threaded resolver cleanup and GSSAPI for FTP to the TODO list of
    known blocking operations.
  
  - New known bugs entry 'Blocking socket operations in non-blocking API'
    that directs to the TODO's list of known blocking operations.
  
  Ref: https://github.com/curl/curl/pull/5214#issuecomment-612488021
  
  Reported-by: Marc Hoersken
  
  Closes https://github.com/curl/curl/pull/5216

Marc Hoersken (14 Apr 2020)
- test2043: use revoked.badssl.com instead of revoked.grc.com
  
  The certificate of revoked.grc.com has expired on 2020-04-13.
  
  Reviewed-by: Jay Satiro
  
  Closes #5233

- sockfilt: fix broken pipe on Windows to be ready in select_ws
  
  Closes #5228

Daniel Stenberg (14 Apr 2020)
- RELEASE-NOTES: synced

- scripts/release-notes: fix duplicate output header

- github/workflow: enable MQTT in the macOS debug build

- azure: add mqtt support to one of the Windows builds

- travis: add mqtt job on Linux

- tests: add four MQTT tests 1190 - 1193

- tests: add the mqtt test server mqttd

- tests: support hex encoded data and mqtt server
  
  The mqtt server is started using a "random" port.

- [Björn Stenberg brought this change]

  mqtt: add new experimental protocol
  
  Closes #5173

- TODO: Consider convenience options for JSON and XML?
  
  Closes #5203

- tool: do not declare functions with Curl_ prefix
  
  To avoid collision risks with private libcurl symbols when linked with
  static versions (or just versions not hiding internal symbols).
  
  Reported-by: hydra3333 on github
  Fixes #5219
  Closes #5234

- [Nathaniel R. Lewis brought this change]

  cmake: add aliases so exported target names are available in tree
  
  Reviewed-by: Brad King
  Closes #5206

- version: increase buffer space for ssl version output
  
  To avoid it getting truncated, especially when several SSL backends are
  built-in.
  
  Reported-by: Gisle Vanem
  Fixes #5222
  Closes #5226

Marc Hoersken (13 Apr 2020)
- cirrus: no longer ignore test 504 which is working again
  
  The test is working again, because TCP blackholing is disabled.

- appveyor: completely disable tests that fail to timeout early
  
  The tests changed from ignored to disabled are tests that are
  about connecting to non-listening socket. On AppVeyor these
  tests are not reliable, because for some unknown reason the
  connect is not timing out before the test time limit is reached.

Daniel Stenberg (13 Apr 2020)
- test1908: avoid using fixed port number in test data
  
  Closes #5225

Jay Satiro (12 Apr 2020)
- [Andrew Kurushin brought this change]

  schannel: Fix blocking timeout logic
  
  - Fix schannel_send for the case when no timeout was set.
  
  Prior to this change schannel would error if the socket was not ready
  to send data and no timeout was set.
  
  This commit is similar to parent commit 89dc6e0 which recently made the
  same change for SOCKS, for the same reason. Basically it was not well
  understood that when Curl_timeleft returns 0 it is not a timeout of 0 ms
  but actually means no timeout.
  
  Fixes https://github.com/curl/curl/issues/5177
  Closes https://github.com/curl/curl/pull/5221

- socks: Fix blocking timeout logic
  
  - Document in Curl_timeleft's comment block that returning 0 signals no
    timeout (ie there's infinite time left).
  
  - Fix SOCKS' Curl_blockread_all for the case when no timeout was set.
  
  Prior to this change if the timeout had a value of 0 and that was passed
  to SOCKET_READABLE it would return right away instead of blocking. That
  was likely because it was not well understood that when Curl_timeleft
  returns 0 it is not a timeout of 0 ms but actually means no timeout.
  
  Ref: https://github.com/curl/curl/pull/5214#issuecomment-612512360
  
  Closes https://github.com/curl/curl/pull/5220

- [Marc Hoersken brought this change]

  gopher: check remaining time left during write busy loop
  
  Prior to this change gopher's blocking code would block forever,
  ignoring any set timeout value.
  
  Assisted-by: Jay Satiro
  Reviewed-by: Daniel Stenberg
  
  Similar to #5220 and #5221
  Closes #5214

Daniel Stenberg (13 Apr 2020)
- [Dirkjan Bussink brought this change]

  gnutls: ensure TLS 1.3 when SRP isn't requested
  
  When SRP is requested in the priority string, GnuTLS will disable
  support for TLS 1.3. Before this change, curl would always add +SRP to
  the priority list, effectively always disabling TLS 1.3 support.
  
  With this change, +SRP is only added to the priority list when SRP
  authentication is also requested. This also allows updating the error
  handling here to not have to retry without SRP. This is because SRP is
  only added when requested and in that case a retry is not needed.
  
  Closes #5223

Marc Hoersken (12 Apr 2020)
- tests/server: add hidden window to gracefully handle WM_CLOSE
  
  Forward Window events as signals to existing signal event handler.

- tests/server: add CTRL event handler for Win32 consoles
  
  Forward CTRL events as signals to existing signal event handler.

- tests/server: move all signal handling routines to util.[ch]
  
  Avoid code duplication to prepare for portability enhancements.

Daniel Stenberg (12 Apr 2020)
- compressed.d: stress that the headers are not modified
  
  Suggested-by: Michael Osipov
  Assisted-by: Jay Satiro
  Bug: https://github.com/curl/curl/issues/5182#issuecomment-611638008
  Closes #5217

Marc Hoersken (11 Apr 2020)
- tests/server/util.c: use curl_off_t instead of long for pid
  
  Avoid potential overflow of huge PIDs on Windows.
  
  Related to #5188
  Assisted-by: Marcel Raad

- tests: use Cygwin/msys PIDs for stunnel and sshd on Windows
  
  Since the Windows versions of both programs would write Windows
  PIDs to their pidfiles which we cannot handle, we need to use
  our known perl.exe Cygwin/msys PID together with exec() in order
  to tie the spawned processes to the existance of our perl.exe
  
  The perl.exe that is executing secureserver.pl and sshserver.pl
  has a Cygwin/msys PID, because it is started inside Cygwin/msys.
  
  Related to #5188

- tests: add Windows compatible pidwait like pidkill and pidterm
  
  Related to #5188

- tests: fix conflict between Cygwin/msys and Windows PIDs
  
  Add 65536 to Windows PIDs to allow Windows specific treatment
  by having disjunct ranges for Cygwin/msys and Windows PIDs.
  
  See also:
  - https://cygwin.com/git/?p=newlib-cygwin.git;a=commit; ↵
    h=b5e1003722cb14235c4f166be72c09acdffc62ea
  - https://cygwin.com/git/?p=newlib-cygwin.git;a=commit; ↵
    h=448cf5aa4b429d5a9cebf92a0da4ab4b5b6d23fe
  
  Replaces #5178
  Closes #5188

Daniel Stenberg (11 Apr 2020)
- RELEASE-NOTES: synced

- release-notes.pl: detect the start of the references in cleanup mode

- Revert "file: on Windows, refuse paths that start with \\"
  
  This reverts commit 1b71bc532bde8621fd3260843f8197182a467ff2.
  
  Reminded-by: Chris Roberts
  Bug: https://curl.haxx.se/mail/archive-2020-04/0013.html
  
  Closes #5215

Jay Satiro (11 Apr 2020)
- lib: fix conversion warnings for SOCKET_WRITABLE/READABLE
  
  - If loss of data may occur converting a timediff_t to time_t and
    the time value is > TIME_T_MAX then treat it as TIME_T_MAX.
  
  This is a follow-up to 8843678 which removed the (time_t) typecast
  from the macros so that conversion warnings could be identified.
  
  Closes https://github.com/curl/curl/pull/5199

- test1148: tolerate progress updates better (again)
  
  - Ignore intermediate progress updates.
  
  - Support locales that use a character other than period as decimal
    separator (eg 100,0%).
  
  test1148 checks that the progress finishes at 100% and has the right
  bar width. Prior to this change the test assumed that the only progress
  reported for such a quick transfer was 100%, however in rare instances
  (like in the CI where transfer time can slow considerably) there may be
  intermediate updates. For example, below is stderrlog1148 from a failed
  CI run with explicit \r and \n added (it is one line; broken up so that
  it's easier to understand).
  
  \r
  \r##################################                                        48.3%
  \r######################################################################## 100.0%
  \n
  
  Closes https://github.com/curl/curl/pull/5194

Marc Hoersken (10 Apr 2020)
- sshserver.pl: use cached Win32 environment check variable

- appveyor: partially revert 3413a110 to keep build without proxy
  
  Ref: #5211 and #4526
  Reported-by: Marcel Raad

- appveyor: ignore failing 'connect to non-listening proxy' tests
  
  Closes #5211

- CI/macos: convert CRLF to LF and align indentation

Daniel Stenberg (9 Apr 2020)
- url: allow non-HTTPS altsvc-matching for debug builds
  
  This is already partly supported but this part was missing.
  Reported-by: James Fuller
  
  Closes #5205

- server/resolve: remove AI_CANONNAME to make macos tell the truth
  
  With this bit set, my mac successfully resolves "ip6-localhost" when in
  fact there is no such host known to my machine! That in turn made test
  241 wrongly execute and fail.
  
  Closes #5202

- runtests: fix warning about using an undefined variable
  
  Follow-up from 4d939ef6ceb2db1

- release-notes: fix the initial reference list output

- github actions: run when pushed to master or */ci + PRs
  
  Avoid double-builds when using "local" branches for PRs. For both macos
  and fuzz jobs.
  
  Closes #5201

- runtests: provide nicer errormsg when protocol "dump" file is empty

- [Gilles Vollant brought this change]

  schannel: support .P12 or .PFX client certificates
  
  Used with curl command line option like this: --cert
  <filename>:<password> --cert-type p12
  
  Closes #5193

- tests: verify split initial HTTP requests with CURL_SMALLREQSEND
  
  test1294: "split request" being when the entire request isn't sent in
  the first go, and the remainder is sent in the PERFORM state. A GET
  request is otherwise not sending anything during PERFORM.
  
  test1295: same kind of split but with POST
  
  Closes #5197

- http: don't consider upload done if the request isn't completely sent off
  
  Fixes #4919
  Closes #5197

- http: allow Curl_add_buffer_send() to do a short first send by force
  
  In a debug build, settting the environment variable "CURL_SMALLREQSEND"
  will make the first HTTP request send not send more bytes than the set
  amount, thus ending up verifying that the logic for handling a split
  HTTP request send works correctly.

- connect: store connection info for QUIC connections
  
  Restores the --head functionality to the curl utility which extracts
  'protocol' that is stored that way.
  
  Reported-by: James Fuller
  Fixes #5196
  Closes #5198

- tests/README: update the port numbers list
  
  Since the pipelining server is long gone.
  Reported-by: James Fuller

- select: remove typecast from SOCKET_WRITABLE/READABLE macros
  
  So that they don't hide conversions-by-mistake
  
  Reviewed-by: Jay Satiro
  Closes #5190

- CURLOPT_WRITEFUNCTION.3: add inline example and new see-also
  
  Closes #5192

- release-notes: output trailing references sorted numerically

- cleanup: correct copyright year range on a few files

- configure: remove use of -vec-report0 from CFLAGS with icc
  
  ... as it apparently isn't (always) supported.
  Reported-by: Alain Miniussi
  Fixes #5096
  Closes #5191

- warnless: remove code block for icc that didn't work
  
  Reported-by: Alain Miniussi
  Fixes #5096

Marc Hoersken (6 Apr 2020)
- dist: add missing setup-win32.h
  
  Follow up to d820224b8b

Daniel Stenberg (6 Apr 2020)
- RELEASE-NOTES: synced

- scripts/release-notes.pl: add helper script for RELEASE-NOTES maintenance
  
  This script helps putting entries in the RELEASE-NOTES using a coherent
  style and sorting with a minimal human editing effort - as long as the
  first line in the commit message is good enough! There's a short howto
  at the top of the file.

- [Dennis Felsing brought this change]

  configure: don't check for Security.framework when cross-compiling
  
  Since it checks for the local file, not the cross-compiled one.
  
  Closes #5189

- TODO: Option to make -Z merge lined based outputs on stdout
  
  Closes #5175

- lib: never define CURL_CA_BUNDLE with a getenv
  
  - it breaks the build (since 6de756c9b1de34b7a1)
  - it's not documented and not consistent across platforms
  - the curl tool does that getenv magic
  
  Bug: https://github.com/curl/curl/commit/6de756c#r38127030
  Reported-by: Gisle Vanem
  
  Closes #5187

Marc Hoersken (5 Apr 2020)
- lib670: use the same Win32 API check as all other lib tests

- appveyor: use random test server ports based upon APPVEYOR_API_URL
  
  Avoid conflicts of test server ports with AppVeyor API on localhost.
  
  Closes #5034

- appveyor: sort builds by type and add two new variants
  
  Related to #5034 and #5063

- appveyor: show failed tests in log even if test is ignored
  
  And print API response with newline only if there is one

- appveyor: turn disabled tests into ignored result tests

Daniel Stenberg (5 Apr 2020)
- KNOWN_BUGS: fixed "USE_UNIX_SOCKETS on Windows"
  
  Fixed with #5170 (commit 23a870f2fd041278)

- test1566: verify --etag-compare that gets a 304 back
  
  Verifies the fix in #5183
  
  Closes #5186

- [Kwon-Young Choi brought this change]

  CURLINFO_CONDITION_UNMET: return true for 304 http status code
  
  In libcurl, CURLINFO_CONDITION_UNMET is used to avoid writing to the
  output file if the server did not transfered a file based on time
  condition. In the same manner, getting a 304 HTTP response back from the
  server, for example after passing a custom If-Match-* header, also
  fulfill this condition.
  
  Fixes #5181
  Closes #5183

- [Kwon-Young Choi brought this change]

  curl: allow both --etag-compare and --etag-save with same file name
  
  This change inverse the order of processing for the --etag-compare and
  --etag-save option to process first --etag-compare. This in turn allows
  to use the same file name to compare and save an etag.
  
  The original behavior of not failing if the etag file does not exists is
  conserved.
  
  Fixes #5179
  Closes #5180

Viktor Szakats (4 Apr 2020)
- windows: enable UnixSockets with all build toolchains
  
  Extend existing unix socket support in Windows builds to be
  enabled for all toolchain vendors or versions. (Previously
  it was only supported with certain MSVC versions + more recent
  Windows 10 SDKs)
  
  Ref: https://devblogs.microsoft.com/commandline/af_unix-comes-to-windows/
  Ref: https://github.com/curl/curl/issues/5162
  Closes: https://github.com/curl/curl/pull/5170

Daniel Stenberg (4 Apr 2020)
- KNOWN_BUGS: Store TLS context per transfer instead of per connection
  
  Closes #5102

Marc Hoersken (3 Apr 2020)
- sockfilt: remove redundancy in timeout handling
  
  And update other logmsg output in select_ws on Windows.

- sockfilt: fix handling of ready closed sockets on Windows
  
  Replace the incomplete workaround regarding FD_CLOSE
  only signalling once by instead doing a pre-check with
  standard select and storing the result for later use.
  
  select keeps triggering on closed sockets on Windows while
  WSAEventSelect fires only once with data still available.
  By doing the pre-check we do not run in a deadlock
  due to waiting forever for another FD_CLOSE event.

- sockfilt: fix race-condition of waiting threads and event handling
  
  Fix race-condition of waiting threads finishing while events are
  already being processed which lead to invalid or skipped events.
  
  Use mutex to check for one event at a time or do post-processing.
  In addition to mutex-based locking use specific event as signal.
  
  Closes #5156

Daniel Stenberg (2 Apr 2020)
- [Leo Neat brought this change]

  CI-fuzz: increase fuzz time to 40 minutes
  
  Closes #5174

Marc Hoersken (2 Apr 2020)
- CI: increase Azure Pipelines timeouts due to performance issues
  
  The current demand on Azure negatively impacts the CI performance.

- runtests.pl: log host OS as detected by Perl environment

- ftpserver.pl: log before and after data connection is closed

Daniel Stenberg (1 Apr 2020)
- RELEASE-NOTES: synced

- RELEASE-PROCEDURE.md: run the copyright.pl script!

- vquic/ngtcp2.h: update copyright year range
  
  Follow-up to 0736ee73d346a52

- [Daiki Ueno brought this change]

  CI: add build with ngtcp2 + gnutls on Travis CI

- [Daiki Ueno brought this change]

  vquic: add support for GnuTLS backend of ngtcp2
  
  Currently, the TLS backend used by vquic/ngtcp2.c is selected at compile
  time. Therefore OpenSSL support needs to be explicitly disabled.
  
  Signed-off-by: Daiki Ueno <dueno@redhat.com>
  Closes #5148

- [Gisle Vanem brought this change]

  examples/sessioninfo.c: add include to fix compiler warning
  
  Fixes #5171

- misc: copyright year updates
  
  Follow-up to 7a71965e9

- [Harry Sintonen brought this change]

  build: fixed build for systems with select() in unistd.h
  
  Closes #5169

- memdebug: don't log free(NULL)
  
  ... it serves no purpose and fills up the log.

- cleanup: insert newline after if() conditions
  
  Our code style mandates we put the conditional block on a separate
  line. These mistakes are now detected by the updated checksrc.

- checksrc: warn on obvious conditional blocks on the same line as if()
  
  Closes #5164

- [Roger Orr brought this change]

  cmake: add CMAKE_MSVC_RUNTIME_LIBRARY
  
  Fixes #5165
  Closes #5167

- [Daiki Ueno brought this change]

  ngtcp2: update to git master for the key installation API change
  
  This updates the ngtcp2 OpenSSL backend to follow the API change in
  commit 32e703164 of ngtcp2.
  
  Notable changes are:
  - ngtcp2_crypto_derive_and_install_{rx,tx}_key have been added to replace
    ngtcp2_crypto_derive_and_install_key
  - the 'side' argument of ngtcp2_crypto_derive_and_install_initial_key
    has been removed
  
  Fixes #5166
  Closes #5168

- [Cyrus brought this change]

  SECURITY.md: minor rephrase
  
  Closes #5158

- output.d: quote the URL when globbing
  
  Some shells do globbing of their own unless the URL is quoted, so maybe
  encourage this.
  
  Co-authored-by: Jay Satiro
  Closes #5160

- dist: add tests/version-scan.pl to tarball
  
  ... used in test 1177.
  
  Follow-up to a97d826f6de3

- test1177: verify that all the CURL_VERSION_ bits are documented

- curl.h: remnove CURL_VERSION_ESNI. Never supported nor documented
  
  Considered experimental and therefore we can do this.
  
  Closes #5157

- KNOWN_BUGS: DoH doesn't inherit all transfer options
  
  Closes #4578
  Closes #4579

- KNOWN_BUGS: DoH leaks memory after followlocation
  
  Closes #4592

- KNOWN_BUGS: "FTPS needs session reuse"
  
  Closes #4654

- KNOWN_BUGS: "stick to same family over SOCKS pro" is presumed fixed

- TODO: Set custom client ip when using haproxy protocol
  
  Closes #5125

Michael Kaufmann (27 Mar 2020)
- writeout_json: Fix data type issues
  
  Load long values correctly (e.g. for http_code).
  
  Use curl_off_t (not long) for:
  - size_download (CURLINFO_SIZE_DOWNLOAD_T)
  - size_upload (CURLINFO_SIZE_UPLOAD_T)
  
  The unit for these values is bytes/second, not microseconds:
  - speed_download (CURLINFO_SPEED_DOWNLOAD_T)
  - speed_upload (CURLINFO_SPEED_UPLOAD_T)
  
  Fixes #5131
  Closes #5152

Daniel Stenberg (27 Mar 2020)
- mailmap: fixup a few author names/fields
  
  Douglas Steinwand, Gökhan Şengün, Jessa Chandler, Julian Z and
  Svyatoslav Mishyn

- version: add 'cainfo' and 'capath' to version info struct
  
  Suggested-by: Timothe Litt
  URL: https://curl.haxx.se/mail/lib-2020-03/0090.html
  Reviewed-by: Jay Satiro
  
  Closes #5150

- RELEASE-NOTES: synced

Jay Satiro (26 Mar 2020)
- SSLCERTS.md: Fix example code for setting CA cert file
  
  Prior to this change the documentation erroneously said use
  CURLOPT_CAPATH to set a CA cert file.
  
  Bug: https://curl.haxx.se/mail/lib-2020-03/0121.html
  Reported-by: Timothe Litt
  
  Closes https://github.com/curl/curl/pull/5151

Marc Hoersken (26 Mar 2020)
- sockfilt: add logmsg output to select_ws_wait_thread on Windows
  
  Assisted-by: Jay Satiro
  Reviewed-by: Daniel Stenberg
  
  Closes #5086

Daniel Stenberg (26 Mar 2020)
- docs/make: generate curl.1 from listed files only
  
  Previously it rendered the page from files matching "*.d" in the correct
  directory, which worked fine in git builds when the files were added but
  made it easy to forget adding the files to the dist.
  
  Now, only man page sections listed in DPAGES in Makefile.inc will be
  used, thus "forcing" us to update this to get the man page right and get
  it included in the dist at the same time.
  
  Ref: #5146
  Closes #5149

- openssl: adapt to functions marked as deprecated since version 3
  
  OpenSSL 3 deprecates SSL_CTX_load_verify_locations and the MD4, DES
  functions we use.
  
  Fix the MD4 and SSL_CTX_load_verify_locations warnings.
  
  In configure, detect OpenSSL v3 and if so, inhibit the deprecation
  warnings. OpenSSL v3 deprecates the DES functions we use for NTLM and
  until we rewrite the code to use non-deprecated functions we better
  ignore these warnings as they don't help us.
  
  Closes #5139

- dist: add mail-rcpt-allowfails.d to the tarball
  
  Reported-by: Maksim Stsepanenka
  Reviewed-by: Jat Satiro
  
  Closes #5146







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
7441
7442
7443
7444
7445
7446
7447


























































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































- docs: unify protocol lists
  
  We boast support for 25 transfer protocols. Make sure the lists are
  consistent
  
  Closes #5384

























































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































Changes to jni/curl/CMakeLists.txt.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#***************************************************************************
#                                  _   _ ____  _
#  Project                     ___| | | |  _ \| |
#                             / __| | | | |_) | |
#                            | (__| |_| |  _ <| |___
#                             \___|\___/|_| \_\_____|
#
# Copyright (C) 1998 - 2020, 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 https://curl.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







|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#***************************************************************************
#                                  _   _ ____  _
#  Project                     ___| | | |  _ \| |
#                             / __| | | | |_) | |
#                            | (__| |_| |  _ <| |___
#                             \___|\___/|_| \_\_____|
#
# Copyright (C) 1998 - 2021, 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 https://curl.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
333
334
335
336
337
338
339

340
341
342
343
344
345
346
option(CMAKE_USE_WOLFSSL "enable wolfSSL for SSL/TLS" OFF)

set(openssl_default ON)
if(WIN32 OR CMAKE_USE_SECTRANSP OR CMAKE_USE_SCHANNEL OR CMAKE_USE_MBEDTLS OR CMAKE_USE_NSS OR CMAKE_USE_WOLFSSL)
  set(openssl_default OFF)
endif()
option(CMAKE_USE_OPENSSL "Use OpenSSL code. Experimental" ${openssl_default})


count_true(enabled_ssl_options_count
  CMAKE_USE_SCHANNEL
  CMAKE_USE_SECTRANSP
  CMAKE_USE_OPENSSL
  CMAKE_USE_MBEDTLS
  CMAKE_USE_BEARSSL







>







333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
option(CMAKE_USE_WOLFSSL "enable wolfSSL for SSL/TLS" OFF)

set(openssl_default ON)
if(WIN32 OR CMAKE_USE_SECTRANSP OR CMAKE_USE_SCHANNEL OR CMAKE_USE_MBEDTLS OR CMAKE_USE_NSS OR CMAKE_USE_WOLFSSL)
  set(openssl_default OFF)
endif()
option(CMAKE_USE_OPENSSL "Use OpenSSL code. Experimental" ${openssl_default})
option(CURL_DISABLE_OPENSSL_AUTO_LOAD_CONFIG "Disable automatic loading of OpenSSL configuration" OFF)

count_true(enabled_ssl_options_count
  CMAKE_USE_SCHANNEL
  CMAKE_USE_SECTRANSP
  CMAKE_USE_OPENSSL
  CMAKE_USE_MBEDTLS
  CMAKE_USE_BEARSSL
614
615
616
617
618
619
620



621

622
623
624
625
626
627
628

if(NOT CURL_DISABLE_LDAPS)
  check_include_file_concat("ldap_ssl.h" HAVE_LDAP_SSL_H)
  check_include_file_concat("ldapssl.h"  HAVE_LDAPSSL_H)
endif()

# Check for idn



check_library_exists_concat("idn2" idn2_lookup_ul HAVE_LIBIDN2)


# Check for symbol dlopen (same as HAVE_LIBDL)
check_library_exists("${CURL_LIBS}" dlopen "" HAVE_DLOPEN)

set(HAVE_LIBZ OFF)
set(HAVE_ZLIB_H OFF)
set(USE_ZLIB OFF)







>
>
>
|
>







615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633

if(NOT CURL_DISABLE_LDAPS)
  check_include_file_concat("ldap_ssl.h" HAVE_LDAP_SSL_H)
  check_include_file_concat("ldapssl.h"  HAVE_LDAPSSL_H)
endif()

# Check for idn
option(USE_LIBIDN2 "Use libidn2 for IDN support" ON)
set(HAVE_LIBIDN2 OFF)
if(USE_LIBIDN2)
  check_library_exists_concat("idn2" idn2_lookup_ul HAVE_LIBIDN2)
endif()

# Check for symbol dlopen (same as HAVE_LIBDL)
check_library_exists("${CURL_LIBS}" dlopen "" HAVE_DLOPEN)

set(HAVE_LIBZ OFF)
set(HAVE_ZLIB_H OFF)
set(USE_ZLIB OFF)
1397
1398
1399
1400
1401
1402
1403

1404
1405
1406
1407
1408
1409
1410
# TODO check HAVE_LDAP_SSL (in autoconf this is enabled with --enable-ldaps)
_add_if("LDAPS"         NOT CURL_DISABLE_LDAPS AND
                        ((USE_OPENLDAP AND SSL_ENABLED) OR
                        (NOT USE_OPENLDAP AND HAVE_LDAP_SSL)))
_add_if("DICT"          NOT CURL_DISABLE_DICT)
_add_if("TFTP"          NOT CURL_DISABLE_TFTP)
_add_if("GOPHER"        NOT CURL_DISABLE_GOPHER)

_add_if("POP3"          NOT CURL_DISABLE_POP3)
_add_if("POP3S"         NOT CURL_DISABLE_POP3 AND SSL_ENABLED)
_add_if("IMAP"          NOT CURL_DISABLE_IMAP)
_add_if("IMAPS"         NOT CURL_DISABLE_IMAP AND SSL_ENABLED)
_add_if("SMB"           NOT CURL_DISABLE_SMB AND use_ntlm)
_add_if("SMBS"          NOT CURL_DISABLE_SMB AND SSL_ENABLED AND use_ntlm)
_add_if("SMTP"          NOT CURL_DISABLE_SMTP)







>







1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
# TODO check HAVE_LDAP_SSL (in autoconf this is enabled with --enable-ldaps)
_add_if("LDAPS"         NOT CURL_DISABLE_LDAPS AND
                        ((USE_OPENLDAP AND SSL_ENABLED) OR
                        (NOT USE_OPENLDAP AND HAVE_LDAP_SSL)))
_add_if("DICT"          NOT CURL_DISABLE_DICT)
_add_if("TFTP"          NOT CURL_DISABLE_TFTP)
_add_if("GOPHER"        NOT CURL_DISABLE_GOPHER)
_add_if("GOPHERS"       NOT CURL_DISABLE_GOPHER AND SSL_ENABLED)
_add_if("POP3"          NOT CURL_DISABLE_POP3)
_add_if("POP3S"         NOT CURL_DISABLE_POP3 AND SSL_ENABLED)
_add_if("IMAP"          NOT CURL_DISABLE_IMAP)
_add_if("IMAPS"         NOT CURL_DISABLE_IMAP AND SSL_ENABLED)
_add_if("SMB"           NOT CURL_DISABLE_SMB AND use_ntlm)
_add_if("SMBS"          NOT CURL_DISABLE_SMB AND SSL_ENABLED AND use_ntlm)
_add_if("SMTP"          NOT CURL_DISABLE_SMTP)
Changes to jni/curl/COPYING.
1
2
3
4
5
6
7
8
9
10
COPYRIGHT AND PERMISSION NOTICE

Copyright (c) 1996 - 2020, Daniel Stenberg, <daniel@haxx.se>, and many
contributors, see the THANKS file.

All rights reserved.

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.


|







1
2
3
4
5
6
7
8
9
10
COPYRIGHT AND PERMISSION NOTICE

Copyright (c) 1996 - 2021, Daniel Stenberg, <daniel@haxx.se>, and many
contributors, see the THANKS file.

All rights reserved.

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.
Changes to jni/curl/Makefile.in.
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
#***************************************************************************
#                                  _   _ ____  _
#  Project                     ___| | | |  _ \| |
#                             / __| | | | |_) | |
#                            | (__| |_| |  _ <| |___
#                             \___|\___/|_| \_\_____|
#
# Copyright (C) 1998 - 2020, 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 https://curl.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







|







39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
#***************************************************************************
#                                  _   _ ____  _
#  Project                     ___| | | |  _ \| |
#                             / __| | | | |_) | |
#                            | (__| |_| |  _ <| |___
#                             \___|\___/|_| \_\_____|
#
# Copyright (C) 1998 - 2021, 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 https://curl.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
453
454
455
456
457
458
459

460
461
462
463
464
465
466
STRIP = @STRIP@
SUPPORT_FEATURES = @SUPPORT_FEATURES@
SUPPORT_PROTOCOLS = @SUPPORT_PROTOCOLS@
USE_ARES = @USE_ARES@
USE_BEARSSL = @USE_BEARSSL@
USE_GNUTLS = @USE_GNUTLS@
USE_GNUTLS_NETTLE = @USE_GNUTLS_NETTLE@

USE_LIBRTMP = @USE_LIBRTMP@
USE_LIBSSH = @USE_LIBSSH@
USE_LIBSSH2 = @USE_LIBSSH2@
USE_MBEDTLS = @USE_MBEDTLS@
USE_MESALINK = @USE_MESALINK@
USE_NGHTTP2 = @USE_NGHTTP2@
USE_NGHTTP3 = @USE_NGHTTP3@







>







453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
STRIP = @STRIP@
SUPPORT_FEATURES = @SUPPORT_FEATURES@
SUPPORT_PROTOCOLS = @SUPPORT_PROTOCOLS@
USE_ARES = @USE_ARES@
USE_BEARSSL = @USE_BEARSSL@
USE_GNUTLS = @USE_GNUTLS@
USE_GNUTLS_NETTLE = @USE_GNUTLS_NETTLE@
USE_HYPER = @USE_HYPER@
USE_LIBRTMP = @USE_LIBRTMP@
USE_LIBSSH = @USE_LIBSSH@
USE_LIBSSH2 = @USE_LIBSSH2@
USE_MBEDTLS = @USE_MBEDTLS@
USE_MESALINK = @USE_MESALINK@
USE_NGHTTP2 = @USE_NGHTTP2@
USE_NGHTTP3 = @USE_NGHTTP3@
696
697
698
699
700
701
702
703



704



705



706
707
708




709





710




711


712
713
714





715


716










































717
718
719
720
721





722

723
724
725
726

727




728






729









730
731















732






733












734

735

736





737






738





















































739
740
741
742
743
744
745
746









747



















748
749
750
751
752
753






754



755








756









757
758
759
760
761
762
763
764
765
 $(VC14_LIBVCXPROJ) $(VC14_SRCVCXPROJ) $(VC15_LIBVCXPROJ) $(VC15_SRCVCXPROJ)

bin_SCRIPTS = curl-config
SUBDIRS = lib src
DIST_SUBDIRS = $(SUBDIRS) tests packages scripts include docs
pkgconfigdir = $(libdir)/pkgconfig
pkgconfig_DATA = libcurl.pc
LIB_VAUTH_CFILES = vauth/cleartext.c vauth/cram.c vauth/digest.c             \



  vauth/digest_sspi.c vauth/krb5_gssapi.c vauth/krb5_sspi.c vauth/ntlm.c     \



  vauth/ntlm_sspi.c vauth/oauth2.c vauth/spnego_gssapi.c vauth/spnego_sspi.c \



  vauth/vauth.c

LIB_VAUTH_HFILES = vauth/digest.h vauth/ntlm.h vauth/vauth.h




LIB_VTLS_CFILES = vtls/bearssl.c vtls/gskit.c vtls/gtls.c vtls/keylog.c  \





  vtls/mbedtls.c vtls/mbedtls_threadlock.c vtls/mesalink.c vtls/nss.c    \




  vtls/openssl.c vtls/schannel.c vtls/schannel_verify.c vtls/sectransp.c \


  vtls/vtls.c vtls/wolfssl.c

LIB_VTLS_HFILES = vtls/bearssl.h vtls/gskit.h vtls/gtls.h vtls/keylog.h      \





  vtls/mbedtls.h vtls/mbedtls_threadlock.h vtls/mesalink.h vtls/nssg.h       \


  vtls/openssl.h vtls/schannel.h vtls/sectransp.h vtls/vtls.h vtls/wolfssl.h











































LIB_VQUIC_CFILES = vquic/ngtcp2.c vquic/quiche.c vquic/vquic.c
LIB_VQUIC_HFILES = vquic/ngtcp2.h vquic/quiche.h vquic/vquic.h
LIB_VSSH_CFILES = vssh/libssh.c vssh/libssh2.c vssh/wolfssh.c
LIB_VSSH_HFILES = vssh/ssh.h





LIB_CFILES = altsvc.c amigaos.c asyn-ares.c asyn-thread.c base64.c            \

  conncache.c connect.c content_encoding.c cookie.c curl_addrinfo.c           \
  curl_ctype.c curl_des.c curl_endian.c curl_fnmatch.c curl_get_line.c        \
  curl_gethostname.c curl_gssapi.c curl_memrchr.c curl_multibyte.c            \
  curl_ntlm_core.c curl_ntlm_wb.c curl_path.c curl_range.c curl_rtmp.c        \

  curl_sasl.c curl_sspi.c curl_threads.c dict.c dotdot.c easy.c escape.c      \




  file.c fileinfo.c formdata.c ftp.c url.c ftplistparser.c getenv.c getinfo.c \






  gopher.c hash.c hmac.c hostasyn.c hostcheck.c hostip.c hostip4.c hostip6.c  \









  hostsyn.c http.c http2.c http_chunks.c http_digest.c http_negotiate.c       \
  http_ntlm.c http_proxy.c idn_win32.c if2ip.c imap.c inet_ntop.c inet_pton.c \















  krb5.c ldap.c llist.c md4.c md5.c memdebug.c mime.c mprintf.c mqtt.c        \






  multi.c netrc.c non-ascii.c nonblock.c openldap.c parsedate.c pingpong.c    \












  pop3.c progress.c psl.c doh.c rand.c rename.c rtsp.c select.c               \

  sendf.c setopt.c sha256.c share.c slist.c smb.c smtp.c socketpair.c socks.c \

  socks_gssapi.c socks_sspi.c speedcheck.c splay.c strcase.c strdup.c         \





  strerror.c strtok.c strtoofft.c system_win32.c telnet.c tftp.c timeval.c    \






  transfer.c urlapi.c version.c warnless.c wildcard.c x509asn1.c dynbuf.c     \





















































  version_win32.c easyoptions.c easygetopt.c hsts.c

LIB_HFILES = altsvc.h amigaos.h arpa_telnet.h asyn.h conncache.h connect.h    \
  content_encoding.h cookie.h curl_addrinfo.h curl_base64.h curl_ctype.h      \
  curl_des.h curl_endian.h curl_fnmatch.h curl_get_line.h curl_gethostname.h  \
  curl_gssapi.h curl_hmac.h curl_ldap.h curl_md4.h curl_md5.h curl_memory.h   \
  curl_memrchr.h curl_multibyte.h curl_ntlm_core.h curl_ntlm_wb.h curl_path.h \
  curl_printf.h curl_range.h curl_rtmp.h curl_sasl.h curl_krb5.h curl_setup.h \









  curl_setup_once.h curl_sha256.h curl_sspi.h curl_threads.h curlx.h dict.h   \



















  dotdot.h easyif.h escape.h file.h fileinfo.h formdata.h ftp.h url.h         \
  ftplistparser.h getinfo.h gopher.h hash.h hostcheck.h hostip.h http.h       \
  http2.h http_chunks.h http_digest.h http_negotiate.h http_ntlm.h            \
  http_proxy.h if2ip.h imap.h inet_ntop.h inet_pton.h llist.h memdebug.h      \
  mime.h mqtt.h multihandle.h multiif.h netrc.h non-ascii.h nonblock.h        \
  parsedate.h pingpong.h pop3.h progress.h psl.h doh.h quic.h rand.h rename.h \






  rtsp.h select.h sendf.h setopt.h setup-vms.h share.h sigpipe.h slist.h      \



  smb.h smtp.h sockaddr.h socketpair.h socks.h speedcheck.h splay.h strcase.h \








  strdup.h strerror.h strtok.h strtoofft.h system_win32.h telnet.h tftp.h     \









  timeval.h transfer.h urlapi-int.h urldata.h warnless.h wildcard.h           \
  x509asn1.h dynbuf.h version_win32.h easyoptions.h hsts.h

LIB_RCFILES = libcurl.rc
CSOURCES = $(LIB_CFILES) $(LIB_VAUTH_CFILES) $(LIB_VTLS_CFILES) \
  $(LIB_VQUIC_CFILES) $(LIB_VSSH_CFILES)

HHEADERS = $(LIB_HFILES) $(LIB_VAUTH_HFILES) $(LIB_VTLS_HFILES) \
  $(LIB_VQUIC_HFILES) $(LIB_VSSH_HFILES)







|
>
>
>
|
>
>
>
|
>
>
>


|
>
>
>
>
|
>
>
>
>
>
|
>
>
>
>
|
>
>
|

|
>
>
>
>
>
|
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
|
|
|
|
>
>
>
>
>
|
>
|
|
|
|
>
|
>
>
>
>
|
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
|
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
|
>
|
>
|
>
>
>
>
>
|
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
|
|
|
|
|
|
|
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
|
|
|
|
|
>
>
>
>
>
>
|
>
>
>
|
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
|
|







697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
 $(VC14_LIBVCXPROJ) $(VC14_SRCVCXPROJ) $(VC15_LIBVCXPROJ) $(VC15_SRCVCXPROJ)

bin_SCRIPTS = curl-config
SUBDIRS = lib src
DIST_SUBDIRS = $(SUBDIRS) tests packages scripts include docs
pkgconfigdir = $(libdir)/pkgconfig
pkgconfig_DATA = libcurl.pc
LIB_VAUTH_CFILES = \
  vauth/cleartext.c     \
  vauth/cram.c          \
  vauth/digest.c        \
  vauth/digest_sspi.c   \
  vauth/krb5_gssapi.c   \
  vauth/krb5_sspi.c     \
  vauth/ntlm.c          \
  vauth/ntlm_sspi.c     \
  vauth/oauth2.c        \
  vauth/spnego_gssapi.c \
  vauth/spnego_sspi.c   \
  vauth/vauth.c

LIB_VAUTH_HFILES = \
  vauth/digest.h        \
  vauth/ntlm.h          \
  vauth/vauth.h

LIB_VTLS_CFILES = \
  vtls/bearssl.c            \
  vtls/gskit.c              \
  vtls/gtls.c               \
  vtls/keylog.c             \
  vtls/mbedtls.c            \
  vtls/mbedtls_threadlock.c \
  vtls/mesalink.c           \
  vtls/nss.c                \
  vtls/openssl.c            \
  vtls/schannel.c           \
  vtls/schannel_verify.c    \
  vtls/sectransp.c          \
  vtls/vtls.c               \
  vtls/wolfssl.c

LIB_VTLS_HFILES = \
  vtls/bearssl.h            \
  vtls/gskit.h              \
  vtls/gtls.h               \
  vtls/keylog.h             \
  vtls/mbedtls.h            \
  vtls/mbedtls_threadlock.h \
  vtls/mesalink.h           \
  vtls/nssg.h               \
  vtls/openssl.h            \
  vtls/schannel.h           \
  vtls/sectransp.h          \
  vtls/vtls.h               \
  vtls/wolfssl.h

LIB_VQUIC_CFILES = \
  vquic/ngtcp2.c   \
  vquic/quiche.c   \
  vquic/vquic.c

LIB_VQUIC_HFILES = \
  vquic/ngtcp2.h   \
  vquic/quiche.h   \
  vquic/vquic.h

LIB_VSSH_CFILES = \
  vssh/libssh.c    \
  vssh/libssh2.c   \
  vssh/wolfssh.c

LIB_VSSH_HFILES = \
  vssh/ssh.h

LIB_CFILES = \
  altsvc.c           \
  amigaos.c          \
  asyn-ares.c        \
  asyn-thread.c      \
  base64.c           \
  c-hyper.c          \
  conncache.c        \
  connect.c          \
  content_encoding.c \
  cookie.c           \
  curl_addrinfo.c    \
  curl_ctype.c       \
  curl_des.c         \
  curl_endian.c      \
  curl_fnmatch.c     \
  curl_get_line.c    \
  curl_gethostname.c \
  curl_gssapi.c      \
  curl_memrchr.c     \
  curl_multibyte.c   \
  curl_ntlm_core.c   \
  curl_ntlm_wb.c     \
  curl_path.c        \
  curl_range.c       \
  curl_rtmp.c        \
  curl_sasl.c        \
  curl_sspi.c        \
  curl_threads.c     \
  dict.c             \
  doh.c              \
  dotdot.c           \
  dynbuf.c           \
  easy.c             \
  easygetopt.c       \
  easyoptions.c      \
  escape.c           \
  file.c             \
  fileinfo.c         \
  formdata.c         \
  ftp.c              \
  ftplistparser.c    \
  getenv.c           \
  getinfo.c          \
  gopher.c           \
  hash.c             \
  hmac.c             \
  hostasyn.c         \
  hostcheck.c        \
  hostip.c           \
  hostip4.c          \
  hostip6.c          \
  hostsyn.c          \
  hsts.c             \
  http.c             \
  http2.c            \
  http_chunks.c      \
  http_digest.c      \
  http_negotiate.c   \
  http_ntlm.c        \
  http_proxy.c       \
  http_aws_sigv4.c   \
  idn_win32.c        \
  if2ip.c            \
  imap.c             \
  inet_ntop.c        \
  inet_pton.c        \
  krb5.c             \
  ldap.c             \
  llist.c            \
  md4.c              \
  md5.c              \
  memdebug.c         \
  mime.c             \
  mprintf.c          \
  mqtt.c             \
  multi.c            \
  netrc.c            \
  non-ascii.c        \
  nonblock.c         \
  openldap.c         \
  parsedate.c        \
  pingpong.c         \
  pop3.c             \
  progress.c         \
  psl.c              \
  rand.c             \
  rename.c           \
  rtsp.c             \
  select.c           \
  sendf.c            \
  setopt.c           \
  sha256.c           \
  share.c            \
  slist.c            \
  smb.c              \
  smtp.c             \
  socketpair.c       \
  socks.c            \
  socks_gssapi.c     \
  socks_sspi.c       \
  speedcheck.c       \
  splay.c            \
  strcase.c          \
  strdup.c           \
  strerror.c         \
  strtok.c           \
  strtoofft.c        \
  system_win32.c     \
  telnet.c           \
  tftp.c             \
  timeval.c          \
  transfer.c         \
  url.c              \
  urlapi.c           \
  version.c          \
  version_win32.c    \
  warnless.c         \
  wildcard.c         \
  x509asn1.c

LIB_HFILES = \
  altsvc.h           \
  amigaos.h          \
  arpa_telnet.h      \
  asyn.h             \
  c-hyper.h          \
  conncache.h        \
  connect.h          \
  content_encoding.h \
  cookie.h           \
  curl_addrinfo.h    \
  curl_base64.h      \
  curl_ctype.h       \
  curl_des.h         \
  curl_endian.h      \
  curl_fnmatch.h     \
  curl_get_line.h    \
  curl_gethostname.h \
  curl_gssapi.h      \
  curl_hmac.h        \
  curl_krb5.h        \
  curl_ldap.h        \
  curl_md4.h         \
  curl_md5.h         \
  curl_memory.h      \
  curl_memrchr.h     \
  curl_multibyte.h   \
  curl_ntlm_core.h   \
  curl_ntlm_wb.h     \
  curl_path.h        \
  curl_printf.h      \
  curl_range.h       \
  curl_rtmp.h        \
  curl_sasl.h        \
  curl_setup.h       \
  curl_setup_once.h  \
  curl_sha256.h      \
  curl_sspi.h        \
  curl_threads.h     \
  curlx.h            \
  dict.h             \
  doh.h              \
  dotdot.h           \
  dynbuf.h           \
  easyif.h           \
  easyoptions.h      \
  escape.h           \
  file.h             \
  fileinfo.h         \
  formdata.h         \
  ftp.h              \
  ftplistparser.h    \
  getinfo.h          \
  gopher.h           \
  hash.h             \
  hostcheck.h        \
  hostip.h           \
  hsts.h             \
  http.h             \
  http2.h            \
  http_chunks.h      \
  http_digest.h      \
  http_negotiate.h   \
  http_ntlm.h        \
  http_proxy.h       \
  http_aws_sigv4.h   \
  if2ip.h            \
  imap.h             \
  inet_ntop.h        \
  inet_pton.h        \
  llist.h            \
  memdebug.h         \
  mime.h             \
  mqtt.h             \
  multihandle.h      \
  multiif.h          \
  netrc.h            \
  non-ascii.h        \
  nonblock.h         \
  parsedate.h        \
  pingpong.h         \
  pop3.h             \
  progress.h         \
  psl.h              \
  quic.h             \
  rand.h             \
  rename.h           \
  rtsp.h             \
  select.h           \
  sendf.h            \
  setopt.h           \
  setup-vms.h        \
  share.h            \
  sigpipe.h          \
  slist.h            \
  smb.h              \
  smtp.h             \
  sockaddr.h         \
  socketpair.h       \
  socks.h            \
  speedcheck.h       \
  splay.h            \
  strcase.h          \
  strdup.h           \
  strerror.h         \
  strtok.h           \
  strtoofft.h        \
  system_win32.h     \
  telnet.h           \
  tftp.h             \
  timeval.h          \
  transfer.h         \
  url.h              \
  urlapi-int.h       \
  urldata.h          \
  version_win32.h    \
  warnless.h         \
  wildcard.h         \
  x509asn1.h

LIB_RCFILES = libcurl.rc
CSOURCES = $(LIB_CFILES) $(LIB_VAUTH_CFILES) $(LIB_VTLS_CFILES) \
  $(LIB_VQUIC_CFILES) $(LIB_VSSH_CFILES)

HHEADERS = $(LIB_HFILES) $(LIB_VAUTH_HFILES) $(LIB_VTLS_HFILES) \
  $(LIB_VQUIC_HFILES) $(LIB_VSSH_HFILES)
Changes to jni/curl/RELEASE-NOTES.
1
2
3
4
5
6
7
8
9
10





11
12
13
14
15
16
17
18
19

20
21
22
23
24
25
26
27
28
29
30
31
32
33

34
35
36
37
38
39
40
41

42
43
44
45
46
47
48
49
50
51
52
53
54
55
56

57
58

59
60
61
62


63
64
65
66



67
68






69

70
71
72
73
74



75
76





77
78
79
80
81
82
83
84
85
86
87
88

89
90
91
92
93
94
95
96


97
98
99
100
101

102
103
104
105
106
107
108
109
110
111
112
113
114
115

116
117
118


119
120

121






122
123
124
125
126
127
128
129
130
131
132
133



134
135

136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226

227
228
229
230
231
232
233

234
235
236
237
238
239
240
241
242
243
244
245
246
247
248

curl and libcurl 7.74.0

 Public curl releases:         196
 Command line options:         235
 curl_easy_setopt() options:   284
 Public functions in libcurl:  85
 Contributors:                 2287

This release includes the following changes:






 o hsts: add experimental support for Strict-Transport-Security [37]

This release includes the following bugfixes:

 o CVE-2020-8286: Inferior OCSP verification [93]
 o CVE-2020-8285: FTP wildcard stack overflow [95]
 o CVE-2020-8284: trusting FTP PASV responses [97]
 o acinclude: detect manually set minimum macos/ipod version [46]
 o alt-svc: enable (in the build) by default [20]

 o alt-svc: minimize variable scope and avoid "DEAD_STORE" [51]
 o asyn: use 'struct thread_data *' instead of 'void *' [84]
 o checksrc: warn on empty line before open brace [13]
 o CI/appveyor: disable test 571 in two cmake builds [22]
 o CI/azure: improve on flakiness by avoiding libtool wrappers [7]
 o CI/tests: enable test target on TravisCI for CMake builds [38]
 o CI/travis: add brotli and zstd to the libssh2 build [27]
 o cirrus: build with FreeBSD 12.2 in CirrusCI [80]
 o cmake: call the feature unixsockets without dash [26]
 o cmake: check for linux/tcp.h [91]
 o cmake: correctly handle linker flags for static libs [52]
 o cmake: don't pass -fvisibility=hidden to clang-cl on Windows [53]
 o cmake: don't use reserved target name 'test' [79]
 o cmake: make BUILD_TESTING dependent option [30]

 o cmake: make CURL_ZLIB a tri-state variable [70]
 o cmake: set the unicode feature in curl-config on Windows [23]
 o cmake: store IDN2 information in curl_config.h [25]
 o cmake: use libcurl.rc in all Windows builds [69]
 o configure: pass -pthread to Libs.private for pkg-config [50]
 o configure: use pkgconfig to find openSSL when cross-compiling [28]
 o connect: repair build without ipv6 availability [19]
 o curl.1: add an "OUTPUT" section at the top of the manpage [32]

 o curl.se: new home [59]
 o curl: add compatibility for Amiga and GCC 6.5 [61]
 o curl: only warn not fail, if not finding the home dir [15]
 o curl_easy_escape: limit output string length to 3 * max input [55]
 o Curl_pgrsStartNow: init speed limit time stamps at start [48]
 o curl_setup: USE_RESOLVE_ON_IPS is for Apple native resolver use
 o curl_url_set.3: fix typo in the RETURN VALUE section [3]
 o CURLOPT_DNS_USE_GLOBAL_CACHE.3: fix typo [34]
 o CURLOPT_HSTS.3: document the file format [82]
 o CURLOPT_NOBODY.3: fix typo [6]
 o CURLOPT_TCP_NODELAY.3: fix comment in example code [8]
 o CURLOPT_URL.3: clarify SCP/SFTP URLs are for uploads as well
 o docs: document the 8MB input string limit [57]
 o docs: fix typos and markup in ETag manpage sections [87]
 o docs: Fix various typos in documentation [58]

 o examples/httpput: remove use of CURLOPT_PUT [39]
 o FAQ: refreshed [56]

 o file: avoid duplicated code sequence [77]
 o ftp: retry getpeername for FTP with TCP_FASTOPEN [100]
 o gnutls: fix memory leaks (certfields memory wasn't released) [41]
 o header.d: mention the "Transfer-Encoding: chunked" handling [45]


 o HISTORY: the new domain
 o http3: fix two build errors, silence warnings [10]
 o http3: use the master branch of GnuTLS for testing [88]
 o http: pass correct header size to debug callback for chunked post [44]



 o http_proxy: use enum with state names for 'keepon' [54]
 o httpput-postfields.c: new example doing PUT with POSTFIELDS [35]






 o infof/failf calls: fix format specifiers [78]

 o libssh2: fix build with disabled proxy support [17]
 o libssh2: fix transport over HTTPS proxy [31]
 o libssh2: require version 1.0 or later [24]
 o Makefile.m32: add support for HTTP/3 via ngtcp2+nghttp3 [11]
 o Makefile.m32: add support for UNICODE builds [85]



 o mqttd: fclose test file when done [60]
 o NEW-PROTOCOL: document what needs to be done to add one [92]





 o ngtcp2: adapt to recent nghttp3 updates [49]
 o ngtcp2: advertise h3 ALPN unconditionally [72]
 o ngtcp2: Fix build error due to symbol name change [90]
 o ngtcp2: use the minimal version of QUIC supported by ngtcp2 [67]
 o ntlm: avoid malloc(0) on zero length user and domain [96]
 o openssl: acknowledge SRP disabling in configure properly [9]
 o openssl: free mem_buf in error path [94]
 o openssl: guard against OOM on context creation [68]
 o openssl: use OPENSSL_init_ssl() with >= 1.1.0 [66]
 o os400: Sync libcurl API options [5]
 o packages/OS400: make the source code-style compliant [4]
 o quiche: close the connection [89]

 o quiche: remove 'static' from local buffer [71]
 o range.d: clarify that curl will not parse multipart responses [36]
 o range.d: fix typo
 o Revert "multi: implement wait using winsock events" [99]
 o rtsp: error out on empty Session ID, unified the code
 o rtsp: fixed Session ID comparison to refuse prefix [65]
 o rtsp: fixed the RTST Session ID mismatch in test 570 [64]
 o runtests: return error if no tests ran [16]


 o runtests: revert the mistaken edit of $CURL
 o runtests: show keywords when no tests ran [33]
 o scripts/completion.pl: parse all opts [101]
 o socks: check for DNS entries with the right port number [74]
 o src/tool_filetime: disable -Wformat on mingw for this file [2]

 o strerror: use 'const' as the string should never be modified [18]
 o test122[12]: remove these two tests [1]
 o test506: make it not run in c-ares builds [75]
 o tests/*server.py: close log file after each log line [81]
 o tests/server/tftpd.c: close upload file right after transfer [62]
 o tests/util.py: fix compatibility with Python 2 [83]
 o tests: add missing global_init/cleanup calls [42]
 o tests: fix some http/2 tests for older versions of nghttpx [47]
 o tool_debug_cb: do not assume zero-terminated data
 o tool_help: make "output" description less confusing [21]
 o tool_operate: --retry for HTTP 408 responses too [43]
 o tool_operate: bail out proper on errors during parallel transfers [29]
 o tool_operate: fix compiler warning when --libcurl is disabled [12]
 o tool_writeout: use off_t getinfo-types instead of doubles [76]

 o travis: use ninja-build for CMake builds [63]
 o travis: use valgrind when running tests for debug builds [40]
 o urlapi: don't accept blank port number field without scheme [98]


 o urlapi: URL encode a '+' in the query part [14]
 o urldata: remove 'void *protop' and create the union 'p' [86]

 o vquic/ngtcp2.h: define local_addr as sockaddr_storage [73]







This release includes the following known bugs:

 o see docs/KNOWN_BUGS (https://curl.se/docs/knownbugs.html)

This release would not have looked like this without help, code, reports and
advice from friends like these:

  Andreas Fischer, asavah on github, b9a1 on github, Baruch Siach,
  Basuke Suzuki, bobmitchell1956 on github, BrumBrum on hackerone,
  Cristian Morales Vega, d4d on hackerone, Daiki Ueno, Daniel Gustafsson,
  Daniel Stenberg, Dietmar Hauser, Dirk Wetter, emanruse on github,



  Emil Engler, hamstergene on github, Harry Sintonen, Jacob Hoffman-Andrews,
  Jakub Zakrzewski, Jeroen Ooms, Jon Rumsey, José Joaquín Atria, Junho Choi,

  Kael1117 on github, Klaus Crusius, Kovalkov Dmitrii, Marcel Raad,
  Marc Hörsken, Marc Schlatter, Niranjan Hasabnis, nosajsnikta on github,
  Oliver Urbann, Per Nilsson, Philipp Klaus Krause, Ray Satiro,
  Rikard Falkeborn, Rui LIU, Sergei Nikulov, Thomas Danielsson, Tobias Hieta,
  Tom G. Christensen, Varnavas Papaioannou, Viktor Szakats, Vincent Torri,
  xnynx on github,
  (46 contributors)

        Thanks! (and sorry if I forgot to mention someone)

References to bug reports and discussions on issues:

 [1] = https://curl.se/bug/?i=6080
 [2] = https://curl.se/bug/?i=6079
 [3] = https://curl.se/bug/?i=6102
 [4] = https://curl.se/bug/?i=6085
 [5] = https://curl.se/bug/?i=6083
 [6] = https://curl.se/bug/?i=6097
 [7] = https://curl.se/bug/?i=6049
 [8] = https://curl.se/bug/?i=6096
 [9] = https://curl.se/mail/lib-2020-10/0037.html
 [10] = https://curl.se/bug/?i=6093
 [11] = https://curl.se/bug/?i=6092
 [12] = https://curl.se/bug/?i=6095
 [13] = https://curl.se/bug/?i=6088
 [14] = https://curl.se/bug/?i=6086
 [15] = https://curl.se/bug/?i=6200
 [16] = https://curl.se/bug/?i=6053
 [17] = https://curl.se/bug/?i=6125
 [18] = https://curl.se/bug/?i=6068
 [19] = https://curl.se/bug/?i=6069
 [20] = https://curl.se/bug/?i=5868
 [21] = https://curl.se/bug/?i=6118
 [22] = https://curl.se/bug/?i=6119
 [23] = https://curl.se/bug/?i=6117
 [24] = https://curl.se/bug/?i=6116
 [25] = https://curl.se/bug/?i=6108
 [26] = https://curl.se/bug/?i=6108
 [27] = https://curl.se/bug/?i=6105
 [28] = https://curl.se/bug/?i=6145
 [29] = https://curl.se/bug/?i=6141
 [30] = https://curl.se/bug/?i=6072
 [31] = https://curl.se/bug/?i=6113
 [32] = https://curl.se/bug/?i=6134
 [33] = https://curl.se/bug/?i=6126
 [34] = https://curl.se/bug/?i=6131
 [35] = https://curl.se/bug/?i=6188
 [36] = https://curl.se/bug/?i=6124
 [37] = https://curl.se/bug/?i=5896
 [38] = https://curl.se/bug/?i=6074
 [39] = https://curl.se/bug/?i=6186
 [40] = https://curl.se/bug/?i=6154
 [41] = https://curl.se/bug/?i=6153
 [42] = https://curl.se/bug/?i=6156
 [43] = https://curl.se/bug/?i=6155
 [44] = https://curl.se/bug/?i=6147
 [45] = https://curl.se/bug/?i=6148
 [46] = https://curl.se/bug/?i=6138
 [47] = https://curl.se/bug/?i=6139
 [48] = https://curl.se/bug/?i=6162
 [49] = https://curl.se/bug/?i=6185
 [50] = https://curl.se/bug/?i=6168
 [51] = https://curl.se/bug/?i=6182
 [52] = https://curl.se/bug/?i=6195
 [53] = https://curl.se/bug/?i=6194
 [54] = https://curl.se/mail/lib-2020-11/0026.html
 [55] = https://curl.se/bug/?i=6192
 [56] = https://curl.se/bug/?i=6177
 [57] = https://curl.se/bug/?i=6190
 [58] = https://curl.se/bug/?i=6171
 [59] = https://curl.se/bug/?i=6172
 [60] = https://curl.se/bug/?i=6058
 [61] = https://curl.se/bug/?i=6220
 [62] = https://curl.se/bug/?i=6058
 [63] = https://curl.se/bug/?i=6077
 [64] = https://curl.se/bug/?i=6161
 [65] = https://curl.se/bug/?i=6161
 [66] = https://curl.se/bug/?i=6254
 [67] = https://curl.se/bug/?i=6250
 [68] = https://curl.se/bug/?i=6224
 [69] = https://curl.se/bug/?i=6215
 [70] = https://curl.se/bug/?i=6173
 [71] = https://curl.se/bug/?i=6223
 [72] = https://curl.se/bug/?i=6250
 [73] = https://curl.se/bug/?i=6250
 [74] = https://curl.se/bug/?i=6247
 [75] = https://curl.se/bug/?i=6247
 [76] = https://curl.se/bug/?i=6248
 [77] = https://curl.se/bug/?i=6249
 [78] = https://curl.se/bug/?i=6241
 [79] = https://curl.se/bug/?i=6257

 [80] = https://curl.se/bug/?i=6211
 [81] = https://curl.se/bug/?i=6058
 [82] = https://curl.se/bug/?i=6205
 [83] = https://curl.se/bug/?i=6259
 [84] = https://curl.se/bug/?i=6239
 [85] = https://curl.se/bug/?i=6228
 [86] = https://curl.se/bug/?i=6238

 [87] = https://curl.se/bug/?i=6273
 [88] = https://curl.se/bug/?i=6235
 [89] = https://curl.se/bug/?i=6213
 [90] = https://curl.se/bug/?i=6271
 [91] = https://curl.se/bug/?i=6252
 [92] = https://curl.se/bug/?i=6263
 [93] = https://curl.se/docs/CVE-2020-8286.html
 [94] = https://curl.se/bug/?i=6267
 [95] = https://curl.se/docs/CVE-2020-8285.html
 [96] = https://curl.se/bug/?i=6264
 [97] = https://curl.se/docs/CVE-2020-8284.html
 [98] = https://curl.se/bug/?i=6283
 [99] = https://curl.se/bug/?i=6146
 [100] = https://curl.se/bug/?i=6252
 [101] = https://curl.se/bug/?i=6280

|

|
|
|

|



>
>
>
>
>
|



|
|
|
<
|
>
|
|
|
|
|
|
|
|
|
|
|
|
<
|
>
|
|
|
|
|
|
|
|
>
<
<
<
<
<
<
<
|
<
|
<
<
<
|
|
>
|
|
>
|
|
<
<
>
>
|
|
|
|
>
>
>
|
<
>
>
>
>
>
>
|
>
|
|
|
|
|
>
>
>
|
<
>
>
>
>
>
|
|
|
|
<
<
|
<
<
<
|
<
>
|
<
<
|
|
|
<
|
>
>
|
<
<
|
<
>
|
|
|
|
|
|
|
<
|
<
|
<
|
|
>
|
|
<
>
>
|
|
>
|
>
>
>
>
>
>








|
|
<
|
>
>
>
|
|
>
|
<
|
<
|
|
|





|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<
|
|
>
|
|
|
|
|
|
|
>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

23
24
25
26
27
28
29
30
31
32
33
34
35
36

37
38
39
40
41
42
43
44
45
46
47







48

49



50
51
52
53
54
55
56
57


58
59
60
61
62
63
64
65
66
67

68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84

85
86
87
88
89
90
91
92
93


94



95

96
97


98
99
100

101
102
103
104


105

106
107
108
109
110
111
112
113

114

115

116
117
118
119
120

121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142

143
144
145
146
147
148
149
150

151

152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235

236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
curl and libcurl 7.75.0

 Public curl releases:         197
 Command line options:         237
 curl_easy_setopt() options:   285
 Public functions in libcurl:  85
 Contributors:                 2322

This release includes the following changes:

 o curl: add --create-file-mode [mode] [28]
 o curl: add new variables to --write-out [25]
 o dns: extend CURLOPT_RESOLVE syntax for adding non-permanent entries [53]
 o gopher: implement secure gopher protocol [2]
 o http: add Hyper as new optional HTTP backend [24]
 o http: introduce AWS HTTP v4 Signature support [26]

This release includes the following bugfixes:

 o badsymbols.pl: add verbose mode -v [31]
 o badsymbols.pl: ignore stand-alone single hash lines [40]
 o BUG-BOUNTY: minor language updates [5]

 o build: fix djgpp builds [84]
 o cleanup: fix empty expression statement has no effect
 o cmake: Add an option to disable libidn2 [48]
 o cmake: enable gophers correctly in curl-config [10]
 o cmake: expose CURL_DISABLE_OPENSSL_AUTO_LOAD_CONFIG [32]
 o cmdline-opts/gen.pl: return hard on errors [11]
 o cmdline-opts/retry.d: mention response code 429 as well [47]
 o configure: set -Wextra-semi-stmt for clang with --enable-debug [52]
 o connect: defer port selection until connect() time [22]
 o connect: mark intentional ignores of setsockopt return values [75]
 o connect: on linux, enable reporting of all ICMP errors on UDP sockets [27]
 o connect: zero variable on stack to silence valgrind complaint [23]
 o cookie: avoid the C1001 internal compiler error with MSVC 14 [36]
 o curl.1: fix typo microsft -> microsoft [56]

 o curl: fix handling of -q option [39]
 o curl: include the file name in --xattr/--remote-time error msgs
 o curl: move fprintf outputs to warnf [105]
 o Curl_chunker: shrink the struct [104]
 o curl_easy_pause.3: add multiplexed pause effects [41]
 o CURLINFO_PRETRANSFER_TIME.3: clarify [61]
 o CURLOPT_URL.3: remove scheme specific details [12]
 o digest_sspi: Show InitializeSecurityContext errors in verbose mode [8]
 o docs/examples: adjust prototypes for CURLOPT_READFUNCTION [51]
 o docs/URL-SYNTAX: the URL syntax curl accepts and works with [15]
 o docs: enable syntax highlighting in several docs files [16]







 o docs: fix line length bug in gen.pl [70]

 o docs: fix typos in NEW-PROTOCOL.md [102]



 o docs: fix wrong documentation in help.d [71]
 o docs: remove redundant "better" in --fail help [55]
 o doh: allocate state struct on demand [85]
 o examples/libtest: add .checksrc to dist [14]
 o examples: remove superfluous asterisk uses
 o failf: remove newline from formatting strings [35]
 o file: don't provide content-length for directories [49]
 o getinfo: build with disabled HTTP support


 o gitattributes: Set batch files to CRLF line endings on checkout [65]
 o h2: do not wait for RECV on paused transfers [43]
 o HISTORY: added dates to early history
 o http: empty reply connection are not left intact [80]
 o http: get CURLOPT_REQUEST_TARGET working with a HTTP proxy [83]
 o http: have CURLOPT_FAILONERROR fail after all headers [54]
 o http: make providing Proxy-Connection header not cause duplicated headers [92]
 o http: show the request as headers even when split-sending [7]
 o http_chunks: correct and clarify a comment on hexnumber length [88]
 o http_proxy: Fix CONNECT chunked encoding race condition [76]

 o httpauth: make multi-request auth work with custom port [45]
 o INSTALL: now at 85 operating systems
 o INSTALL: update the list known OSes and CPU archs curl has run on [38]
 o lib/unit tests: add missing curl_global_cleanup() calls
 o lib1564/5: verify that curl_multi_wakeup returns OK
 o lib: pass in 'struct Curl_easy *' to most functions [101]
 o lib: remove Curl_ prefix from many static functions [66]
 o lib: save a bit of space with some structure packing [82]
 o libssh2: fix "Value stored to 'readdir_len' is never read"
 o libssh2: move data from connection object to transfer object [114]
 o libssh: avoid plain free() of libssh-memory [99]
 o mime: make sure setting MIMEPOST to NULL resets properly [58]
 o misc: assorted typo fixes [57]
 o misc: fix "warning: empty expression statement has no effect" [30]
 o misc: fix typos [73]
 o mk-ca-bundle.pl: deterministic output when using -t [62]
 o mqtt: deal with 0 byte reads correctly [4]

 o mqtt: handle POST/PUBLISH without a set POSTFIELDSIZE [1]
 o multi: set the PRETRANSFER time-stamp when we switch to PERFORM [59]
 o multi: skip DONE state if there's no connection left for ftp wildcard
 o multi: when erroring in TOOFAST state, act as for PERFORM [9]
 o multi_runsingle: bail out early on data->conn == NULL [74]
 o ngtcp2: Fix http3 upload stall [106]
 o ngtcp2: Fix stack buffer overflow [107]
 o ngtcp2: make it build it current master again [21]
 o nss: get the run-time version instead of build-time [67]


 o openssl: lowercase the hostname before using it for SNI [46]



 o OS400: update ccsidcurl.c [20]

 o pretransfer: setup the User-Agent header here [60]
 o quiche: remove fprintf() leftover


 o Revert "CI/github: work-around for brew breakage on macOS" [17]
 o runtests: add 'wakeup' as a feature
 o runtests: add support for %if [feature] conditions [19]

 o runtests: preprocess DISABLED to allow conditionals [93]
 o schannel: plug a memory-leak [64]
 o schannel_verify: fix safefree call typo [50]
 o select: convert Curl_select() to private static function [103]


 o socks: use the download buffer instead [86]

 o speedcheck: exclude paused transfers [42]
 o strerror: skip errnum >= 0 assertion on windows [78]
 o test1522: add debug tracing [3]
 o test1633: set appropriate name
 o test179: use consistent header line endings
 o test410: verify HTTPS GET with a 49K request header
 o tests/mqttd: extract the client id from the correct offset [13]
 o tests: make --libcurl tests only test FTP options if ftp enabled [18]

 o tool_doswin: Restore original console settings on CTRL signal [68]

 o tool_operate: fix the suppression logic of some error messages [33]

 o tool_operate: spellfix a comment
 o tooĺ_writeout: fix the -w time output units [6]
 o transfer: fix GCC 10 warning with flag '-Wint-in-bool-context' [79]
 o travis: build ngtcp2 --with-gnutls [72]
 o travis: limit the tests with quiche builds to HTTPS and FTPS only [44]

 o travis: restrict the openssl3 job to only run https and ftps tests [34]
 o url: if IDNA conversion fails, fallback to Transitional [29]
 o urldata: make magic be the first struct field [87]
 o urldata: remove 'local_ip' from the connectdata struct [97]
 o urldata: remove duplicate 'upkeep_interval_ms' from connectdata [96]
 o urldata: remove duplicate port number storage [98]
 o urldata: remove the duplicate 'ip_addr_str' field [100]
 o urldata: store ip version in a single byte [95]
 o vtls: remove md5sum [69]
 o warnless: remove curlx_ultosi [108]
 o wolfssl: add SECURE_RENEGOTIATION support [63]
 o wolfssl: Support wolfSSL builds missing TLS 1.1 [37]

This release includes the following known bugs:

 o see docs/KNOWN_BUGS (https://curl.se/docs/knownbugs.html)

This release would not have looked like this without help, code, reports and
advice from friends like these:

  0xflotus on github, Alessandro Ghedini, Andrey Gursky, Bubu on github,
  Cherish98 on github, Christoph M. Becker, Cory Benfield, Cristian Rodríguez,

  Dan Fandrich, Daniel Stenberg, David Earl, Denis Laxalde, Dennis Clarke,
  Dmitry Wagin, Douglas R. Reno, Earnestly on github, Emil Engler, Erik Olsson,
  Fabian Keil, Flameborn on github, Ganesh Kamath, Gergely Nagy, Gisle Vanem,
  Hans-Christian Noren Egtvedt, Harry Sintonen, Himanshu Gupta, Hongyi Zhao,
  Ian Spence, Ikko Ashimine, Jacob Hoffman-Andrews, Jeremy Thibault,
  Jon Rumsey, Jon Wilkes, Julian Montes, Kevin Ushey, Marcel Raad,
  Matthias Gatto, Matt Holt, Michał Antoniak, Mike Gelfand, Mike Tzou,
  Nick Zitzmann, Olaf Hering, parazyd on github, Patrick Monnerat, Paul Groke,

  Ray Satiro, Razvan Cojocaru, Rich Turner, Sai Ram Kunala, Sean McArthur,

  Tatsuhiro Tsujikawa, Tomas Berger, UrsusArctos on github, Viktor Szakats,
  William A. Rowe Jr, XhmikosR on github, 不确定
  (58 contributors)

        Thanks! (and sorry if I forgot to mention someone)

References to bug reports and discussions on issues:

 [1] = https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=28735
 [2] = https://curl.se/bug/?i=6208
 [3] = https://curl.se/bug/?i=6331
 [4] = https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=28676
 [5] = https://curl.se/bug/?i=6318
 [6] = https://curl.se/bug/?i=6321
 [7] = https://curl.se/bug/?i=6328
 [8] = https://curl.se/bug/?i=6315
 [9] = https://curl.se/bug/?i=6333
 [10] = https://curl.se/bug/?i=6336
 [11] = https://curl.se/bug/?i=6354
 [12] = https://curl.se/bug/?i=6307
 [13] = https://curl.se/bug/?i=6334
 [14] = https://curl.se/bug/?i=6176
 [15] = https://curl.se/bug/?i=6285
 [16] = https://curl.se/bug/?i=6286
 [17] = https://curl.se/bug/?i=6332
 [18] = https://curl.se/bug/?i=6303
 [19] = https://curl.se/bug/?i=6304
 [20] = https://curl.se/bug/?i=6292
 [21] = https://curl.se/bug/?i=6296
 [22] = https://curl.se/bug/?i=6295
 [23] = https://curl.se/bug/?i=6289
 [24] = https://curl.se/bug/?i=6110
 [25] = https://curl.se/bug/?i=6199
 [26] = https://curl.se/bug/?i=5703
 [27] = https://curl.se/bug/?i=6341
 [28] = https://curl.se/bug/?i=6244
 [29] = https://curl.se/bug/?i=6423
 [30] = https://github.com/curl/curl/commit/08e8455dddc5e48e58a12ade3815c01ae3da3b64#commitcomment-45433279
 [31] = https://curl.se/bug/?i=6349
 [32] = https://curl.se/bug/?i=6435
 [33] = https://curl.se/mail/archive-2020-12/0017.html
 [34] = https://curl.se/bug/?i=6345
 [35] = https://curl.se/bug/?i=6365
 [36] = https://curl.se/bug/?i=6112
 [37] = https://curl.se/mail/lib-2020-12/0121.html
 [38] = https://curl.se/bug/?i=6366
 [39] = https://curl.se/bug/?i=6364
 [40] = https://curl.se/mail/lib-2020-12/0084.html
 [41] = https://curl.se/bug/?i=6360
 [42] = https://curl.se/bug/?i=6358
 [43] = https://curl.se/bug/?i=6356
 [44] = https://curl.se/bug/?i=6403
 [45] = https://curl.se/bug/?i=6397
 [46] = https://curl.se/bug/?i=6540
 [47] = https://curl.se/mail/archive-2020-12/0018.html
 [48] = https://curl.se/bug/?i=6361
 [49] = https://curl.se/bug/?i=6421
 [50] = https://curl.se/bug/?i=6459
 [51] = https://curl.se/bug/?i=6392
 [52] = https://curl.se/bug/?i=6378
 [53] = https://curl.se/bug/?i=6294
 [54] = https://curl.se/bug/?i=6408
 [55] = https://curl.se/bug/?i=6385
 [56] = https://curl.se/bug/?i=6380
 [57] = https://curl.se/bug/?i=6375
 [58] = https://curl.se/bug/?i=6455
 [59] = https://curl.se/bug/?i=6454
 [60] = https://curl.se/bug/?i=6312
 [61] = https://curl.se/bug/?i=6453
 [62] = https://curl.se/bug/?i=6413
 [63] = https://curl.se/bug/?i=6411
 [64] = https://curl.se/bug/?i=6457
 [65] = https://github.com/curl/curl/discussions/6427
 [66] = https://curl.se/bug/?i=6443
 [67] = https://curl.se/bug/?i=6445
 [68] = https://curl.se/bug/?i=6226
 [69] = https://curl.se/bug/?i=6557
 [70] = https://curl.se/bug/?i=6438
 [71] = https://curl.se/bug/?i=6436
 [72] = https://curl.se/bug/?i=6493
 [73] = https://curl.se/mail/lib-2021-01/0063.html
 [74] = https://curl.se/bug/?i=6433
 [75] = https://curl.se/bug/?i=6431
 [76] = https://curl.se/mail/lib-2021-01/0033.html

 [78] = https://curl.se/bug/?i=6504
 [79] = https://curl.se/bug/?i=6537
 [80] = https://twitter.com/mholt6/status/1352130240265375744
 [82] = https://curl.se/bug/?i=6483
 [83] = https://curl.se/bug/?i=6490
 [84] = https://curl.se/bug/?i=6382
 [85] = https://curl.se/bug/?i=6492
 [86] = https://curl.se/bug/?i=6491
 [87] = https://curl.se/bug/?i=6484
 [88] = https://curl.se/bug/?i=6489
 [92] = https://curl.se/mail/lib-2021-01/0095.html
 [93] = https://curl.se/bug/?i=6477
 [95] = https://curl.se/bug/?i=6534
 [96] = https://curl.se/bug/?i=6534
 [97] = https://curl.se/bug/?i=6534
 [98] = https://curl.se/bug/?i=6534
 [99] = https://curl.se/bug/?i=6481
 [100] = https://curl.se/bug/?i=6534
 [101] = https://curl.se/bug/?i=6425
 [102] = https://curl.se/bug/?i=6471
 [103] = https://curl.se/bug/?i=6531
 [104] = https://curl.se/bug/?i=6527
 [105] = https://curl.se/bug/?i=6533
 [106] = https://curl.se/bug/?i=6521
 [107] = https://curl.se/bug/?i=6521
 [108] = https://curl.se/bug/?i=6530
 [114] = https://curl.se/bug/?i=6519
Changes to jni/curl/acinclude.m4.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#***************************************************************************
#                                  _   _ ____  _
#  Project                     ___| | | |  _ \| |
#                             / __| | | | |_) | |
#                            | (__| |_| |  _ <| |___
#                             \___|\___/|_| \_\_____|
#
# Copyright (C) 1998 - 2020, 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 https://curl.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







|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#***************************************************************************
#                                  _   _ ____  _
#  Project                     ___| | | |  _ \| |
#                             / __| | | | |_) | |
#                            | (__| |_| |  _ <| |___
#                             \___|\___/|_| \_\_____|
#
# Copyright (C) 1998 - 2021, 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 https://curl.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
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
  AC_MSG_RESULT([$tst_lib_xnet_required])
])


dnl CURL_CHECK_AIX_ALL_SOURCE
dnl -------------------------------------------------
dnl Provides a replacement of traditional AC_AIX with
dnl an uniform behaviour across all autoconf versions,
dnl and with our own placement rules.

AC_DEFUN([CURL_CHECK_AIX_ALL_SOURCE], [
  AH_VERBATIM([_ALL_SOURCE],
    [/* Define to 1 if OS is AIX. */
#ifndef _ALL_SOURCE
#  undef _ALL_SOURCE







|







139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
  AC_MSG_RESULT([$tst_lib_xnet_required])
])


dnl CURL_CHECK_AIX_ALL_SOURCE
dnl -------------------------------------------------
dnl Provides a replacement of traditional AC_AIX with
dnl an uniform behavior across all autoconf versions,
dnl and with our own placement rules.

AC_DEFUN([CURL_CHECK_AIX_ALL_SOURCE], [
  AH_VERBATIM([_ALL_SOURCE],
    [/* Define to 1 if OS is AIX. */
#ifndef _ALL_SOURCE
#  undef _ALL_SOURCE
Changes to jni/curl/buildconf.bat.
Changes to jni/curl/configure.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
# Generated by GNU Autoconf 2.69 for curl -.
#
# Report bugs to <a suitable curl mailing list: https://curl.se/mail/>.
#
#
# Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc.
#
#
# This configure script is free software; the Free Software Foundation
# gives unlimited permission to copy, distribute and modify it.
#
# Copyright (c) 1998 - 2020 Daniel Stenberg, <daniel@haxx.se>
# This configure script may be copied, distributed and modified under the
# terms of the curl license; see COPYING for more details

## -------------------------------- ##
##  XC_CONFIGURE_PREAMBLE ver: 1.0  ##
## -------------------------------- ##














|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
# Generated by GNU Autoconf 2.69 for curl -.
#
# Report bugs to <a suitable curl mailing list: https://curl.se/mail/>.
#
#
# Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc.
#
#
# This configure script is free software; the Free Software Foundation
# gives unlimited permission to copy, distribute and modify it.
#
# Copyright (c) 1998 - 2021 Daniel Stenberg, <daniel@haxx.se>
# This configure script may be copied, distributed and modified under the
# terms of the curl license; see COPYING for more details

## -------------------------------- ##
##  XC_CONFIGURE_PREAMBLE ver: 1.0  ##
## -------------------------------- ##

901
902
903
904
905
906
907

908
909
910
911
912
913
914
USE_MANUAL_FALSE
USE_MANUAL_TRUE
MANOPT
NROFF
PERL
FISH_FUNCTIONS_DIR
ZSH_FUNCTIONS_DIR

USE_QUICHE
USE_NGHTTP3
USE_NGTCP2_CRYPTO_GNUTLS
USE_NGTCP2_CRYPTO_OPENSSL
USE_NGTCP2
USE_NGHTTP2
IDN_ENABLED







>







901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
USE_MANUAL_FALSE
USE_MANUAL_TRUE
MANOPT
NROFF
PERL
FISH_FUNCTIONS_DIR
ZSH_FUNCTIONS_DIR
USE_HYPER
USE_QUICHE
USE_NGHTTP3
USE_NGTCP2_CRYPTO_GNUTLS
USE_NGTCP2_CRYPTO_OPENSSL
USE_NGTCP2
USE_NGHTTP2
IDN_ENABLED
1201
1202
1203
1204
1205
1206
1207

1208
1209
1210
1211
1212
1213
1214
enable_versioned_symbols
with_winidn
with_libidn2
with_nghttp2
with_ngtcp2
with_nghttp3
with_quiche

with_zsh_functions_dir
with_fish_functions_dir
enable_threaded_resolver
enable_pthreads
enable_verbose
enable_sspi
enable_crypto_auth







>







1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
enable_versioned_symbols
with_winidn
with_libidn2
with_nghttp2
with_ngtcp2
with_nghttp3
with_quiche
with_hyper
with_zsh_functions_dir
with_fish_functions_dir
enable_threaded_resolver
enable_pthreads
enable_verbose
enable_sspi
enable_crypto_auth
2111
2112
2113
2114
2115
2116
2117


2118
2119
2120
2121
2122
2123
2124
  --without-nghttp2       Disable nghttp2 usage
  --with-ngtcp2=PATH      Enable ngtcp2 usage
  --without-ngtcp2        Disable ngtcp2 usage
  --with-nghttp3=PATH     Enable nghttp3 usage
  --without-nghttp3       Disable nghttp3 usage
  --with-quiche=PATH      Enable quiche usage
  --without-quiche        Disable quiche usage


  --with-zsh-functions-dir=PATH
                          Install zsh completions to PATH
  --without-zsh-functions-dir
                          Do not install zsh completions
  --with-fish-functions-dir=PATH
                          Install fish completions to PATH
  --without-fish-functions-dir







>
>







2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
  --without-nghttp2       Disable nghttp2 usage
  --with-ngtcp2=PATH      Enable ngtcp2 usage
  --without-ngtcp2        Disable ngtcp2 usage
  --with-nghttp3=PATH     Enable nghttp3 usage
  --without-nghttp3       Disable nghttp3 usage
  --with-quiche=PATH      Enable quiche usage
  --without-quiche        Disable quiche usage
  --with-hyper=PATH       Enable hyper usage
  --without-hyper         Disable hyper usage
  --with-zsh-functions-dir=PATH
                          Install zsh completions to PATH
  --without-zsh-functions-dir
                          Do not install zsh completions
  --with-fish-functions-dir=PATH
                          Install fish completions to PATH
  --without-fish-functions-dir
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
curl configure -
generated by GNU Autoconf 2.69

Copyright (C) 2012 Free Software Foundation, Inc.
This configure script is free software; the Free Software Foundation
gives unlimited permission to copy, distribute and modify it.

Copyright (c) 1998 - 2020 Daniel Stenberg, <daniel@haxx.se>
This configure script may be copied, distributed and modified under the
terms of the curl license; see COPYING for more details
_ACEOF
  exit
fi

## ------------------------ ##







|







2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
curl configure -
generated by GNU Autoconf 2.69

Copyright (C) 2012 Free Software Foundation, Inc.
This configure script is free software; the Free Software Foundation
gives unlimited permission to copy, distribute and modify it.

Copyright (c) 1998 - 2021 Daniel Stenberg, <daniel@haxx.se>
This configure script may be copied, distributed and modified under the
terms of the curl license; see COPYING for more details
_ACEOF
  exit
fi

## ------------------------ ##
5896
5897
5898
5899
5900
5901
5902
5903


5904
5905
5906
5907
5908
5909
5910
  curl_ldaps_msg="no      (--enable-ldaps)"
   curl_rtsp_msg="no      (--enable-rtsp)"
   curl_rtmp_msg="no      (--with-librtmp)"
  curl_mtlnk_msg="no      (--with-libmetalink)"
    curl_psl_msg="no      (--with-libpsl)"
 curl_altsvc_msg="enabled";
    ssl_backends=




enable_altsvc="yes"

INITIAL_LDFLAGS=$LDFLAGS
INITIAL_LIBS=$LIBS









|
>
>







5900
5901
5902
5903
5904
5905
5906
5907
5908
5909
5910
5911
5912
5913
5914
5915
5916
  curl_ldaps_msg="no      (--enable-ldaps)"
   curl_rtsp_msg="no      (--enable-rtsp)"
   curl_rtmp_msg="no      (--with-librtmp)"
  curl_mtlnk_msg="no      (--with-libmetalink)"
    curl_psl_msg="no      (--with-libpsl)"
 curl_altsvc_msg="enabled";
    ssl_backends=
     curl_h1_msg="enabled (--with-hyper)"
     curl_h2_msg="no      (--with-nghttp2)"
     curl_h3_msg="no      (--with-ngtcp2, --with-quiche)"

enable_altsvc="yes"

INITIAL_LDFLAGS=$LDFLAGS
INITIAL_LIBS=$LIBS


10535
10536
10537
10538
10539
10540
10541
10542
10543
10544
10545
10546
10547
10548
10549
10550
10551
10552
10553
    darwin1.*)
      _lt_dar_allow_undefined='$wl-flat_namespace $wl-undefined ${wl}suppress' ;;
    darwin*) # darwin 5.x on
      # if running on 10.5 or later, the deployment target defaults
      # to the OS version, if on x86, and 10.4, the deployment
      # target defaults to 10.4. Don't you love it?
      case ${MACOSX_DEPLOYMENT_TARGET-10.0},$host in
	10.0,*86*-darwin8*|10.0,*-darwin[91]*)
	  _lt_dar_allow_undefined='$wl-undefined ${wl}dynamic_lookup' ;;
	10.[012][,.]*)
	  _lt_dar_allow_undefined='$wl-flat_namespace $wl-undefined ${wl}suppress' ;;
	10.*)
	  _lt_dar_allow_undefined='$wl-undefined ${wl}dynamic_lookup' ;;
      esac
    ;;
  esac
    if test yes = "$lt_cv_apple_cc_single_mod"; then
      _lt_dar_single_mod='$single_module'
    fi







|



|







10541
10542
10543
10544
10545
10546
10547
10548
10549
10550
10551
10552
10553
10554
10555
10556
10557
10558
10559
    darwin1.*)
      _lt_dar_allow_undefined='$wl-flat_namespace $wl-undefined ${wl}suppress' ;;
    darwin*) # darwin 5.x on
      # if running on 10.5 or later, the deployment target defaults
      # to the OS version, if on x86, and 10.4, the deployment
      # target defaults to 10.4. Don't you love it?
      case ${MACOSX_DEPLOYMENT_TARGET-10.0},$host in
	10.0,*86*-darwin8*|10.0,*-darwin[912]*)
	  _lt_dar_allow_undefined='$wl-undefined ${wl}dynamic_lookup' ;;
	10.[012][,.]*)
	  _lt_dar_allow_undefined='$wl-flat_namespace $wl-undefined ${wl}suppress' ;;
	10.*|11.*)
	  _lt_dar_allow_undefined='$wl-undefined ${wl}dynamic_lookup' ;;
      esac
    ;;
  esac
    if test yes = "$lt_cv_apple_cc_single_mod"; then
      _lt_dar_single_mod='$single_module'
    fi
18136
18137
18138
18139
18140
18141
18142




















18143
18144
18145
18146
18147
18148
18149
    if test "$ac_var_match_word" = "no"; then
      ac_var_added_warnings="$ac_var_added_warnings -W$warning"
    fi
  done
    tmp_CFLAGS="$tmp_CFLAGS $ac_var_added_warnings"
  squeeze tmp_CFLAGS





















          fi
        fi
        ;;
        #
      DEC_C)
        #
        if test "$want_warnings" = "yes"; then







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







18142
18143
18144
18145
18146
18147
18148
18149
18150
18151
18152
18153
18154
18155
18156
18157
18158
18159
18160
18161
18162
18163
18164
18165
18166
18167
18168
18169
18170
18171
18172
18173
18174
18175
    if test "$ac_var_match_word" = "no"; then
      ac_var_added_warnings="$ac_var_added_warnings -W$warning"
    fi
  done
    tmp_CFLAGS="$tmp_CFLAGS $ac_var_added_warnings"
  squeeze tmp_CFLAGS


    ac_var_added_warnings=""
  for warning in extra-semi-stmt; do

  ac_var_match_word="no"
  for word1 in $CFLAGS; do
    for word2 in -Wno-$warning -W$warning; do
      if test "$word1" = "$word2"; then
        ac_var_match_word="yes"
      fi
    done
  done

    if test "$ac_var_match_word" = "no"; then
      ac_var_added_warnings="$ac_var_added_warnings -W$warning"
    fi
  done
    tmp_CFLAGS="$tmp_CFLAGS $ac_var_added_warnings"
  squeeze tmp_CFLAGS

          fi
        fi
        ;;
        #
      DEC_C)
        #
        if test "$want_warnings" = "yes"; then
20076
20077
20078
20079
20080
20081
20082

20083
20084
20085
20086
20087
20088
20089
$as_echo "#define CURL_DISABLE_RTSP 1" >>confdefs.h

       CURL_DISABLE_RTSP=1


$as_echo "#define CURL_DISABLE_ALTSVC 1" >>confdefs.h


       curl_altsvc_msg="no";
       enable_altsvc="no"
       ;;
  *)   { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
       ;;
  esac







>







20102
20103
20104
20105
20106
20107
20108
20109
20110
20111
20112
20113
20114
20115
20116
$as_echo "#define CURL_DISABLE_RTSP 1" >>confdefs.h

       CURL_DISABLE_RTSP=1


$as_echo "#define CURL_DISABLE_ALTSVC 1" >>confdefs.h

       curl_h1_msg="no      (--enable-http, --with-hyper)"
       curl_altsvc_msg="no";
       enable_altsvc="no"
       ;;
  *)   { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
       ;;
  esac
29050
29051
29052
29053
29054
29055
29056
29057
29058
29059
29060
29061
29062
29063
29064
    ;;
  *)
        want_h2="yes"
    want_h2_path="$withval/lib/pkgconfig"
    ;;
esac

curl_h2_msg="no      (--with-nghttp2)"
if test X"$want_h2" != Xno; then
    CLEANLDFLAGS="$LDFLAGS"
  CLEANCPPFLAGS="$CPPFLAGS"
  CLEANLIBS="$LIBS"


    if test -n "$PKG_CONFIG"; then







<







29077
29078
29079
29080
29081
29082
29083

29084
29085
29086
29087
29088
29089
29090
    ;;
  *)
        want_h2="yes"
    want_h2_path="$withval/lib/pkgconfig"
    ;;
esac


if test X"$want_h2" != Xno; then
    CLEANLDFLAGS="$LDFLAGS"
  CLEANCPPFLAGS="$CPPFLAGS"
  CLEANLIBS="$LIBS"


    if test -n "$PKG_CONFIG"; then
29292
29293
29294
29295
29296
29297
29298
29299
29300
29301
29302
29303
29304
29305
29306
    fi
  fi

fi


OPT_TCP2="yes"
curl_h3_msg="no      (--with-ngtcp2, --with-quiche)"

if test "x$disable_http" = "xyes"; then
  # without HTTP, ngtcp2 is no use
  OPT_TCP2="no"
fi









<







29318
29319
29320
29321
29322
29323
29324

29325
29326
29327
29328
29329
29330
29331
    fi
  fi

fi


OPT_TCP2="yes"


if test "x$disable_http" = "xyes"; then
  # without HTTP, ngtcp2 is no use
  OPT_TCP2="no"
fi


30603
30604
30605
30606
30607
30608
30609





















































































































































































































































































30610
30611
30612
30613
30614
30615
30616

  else
        if test X"$want_quiche" != Xdefault; then
                  as_fn_error $? "--with-quiche was specified but could not find quiche pkg-config file." "$LINENO" 5
    fi
  fi
fi























































































































































































































































































OPT_ZSH_FPATH=default

# Check whether --with-zsh-functions-dir was given.
if test "${with_zsh_functions_dir+set}" = set; then :
  withval=$with_zsh_functions_dir; OPT_ZSH_FPATH=$withval







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







30628
30629
30630
30631
30632
30633
30634
30635
30636
30637
30638
30639
30640
30641
30642
30643
30644
30645
30646
30647
30648
30649
30650
30651
30652
30653
30654
30655
30656
30657
30658
30659
30660
30661
30662
30663
30664
30665
30666
30667
30668
30669
30670
30671
30672
30673
30674
30675
30676
30677
30678
30679
30680
30681
30682
30683
30684
30685
30686
30687
30688
30689
30690
30691
30692
30693
30694
30695
30696
30697
30698
30699
30700
30701
30702
30703
30704
30705
30706
30707
30708
30709
30710
30711
30712
30713
30714
30715
30716
30717
30718
30719
30720
30721
30722
30723
30724
30725
30726
30727
30728
30729
30730
30731
30732
30733
30734
30735
30736
30737
30738
30739
30740
30741
30742
30743
30744
30745
30746
30747
30748
30749
30750
30751
30752
30753
30754
30755
30756
30757
30758
30759
30760
30761
30762
30763
30764
30765
30766
30767
30768
30769
30770
30771
30772
30773
30774
30775
30776
30777
30778
30779
30780
30781
30782
30783
30784
30785
30786
30787
30788
30789
30790
30791
30792
30793
30794
30795
30796
30797
30798
30799
30800
30801
30802
30803
30804
30805
30806
30807
30808
30809
30810
30811
30812
30813
30814
30815
30816
30817
30818
30819
30820
30821
30822
30823
30824
30825
30826
30827
30828
30829
30830
30831
30832
30833
30834
30835
30836
30837
30838
30839
30840
30841
30842
30843
30844
30845
30846
30847
30848
30849
30850
30851
30852
30853
30854
30855
30856
30857
30858
30859
30860
30861
30862
30863
30864
30865
30866
30867
30868
30869
30870
30871
30872
30873
30874
30875
30876
30877
30878
30879
30880
30881
30882
30883
30884
30885
30886
30887
30888
30889
30890
30891
30892
30893
30894
30895
30896
30897
30898
30899
30900
30901
30902
30903
30904
30905
30906
30907
30908
30909
30910
30911
30912
30913
30914
30915
30916
30917
30918

  else
        if test X"$want_quiche" != Xdefault; then
                  as_fn_error $? "--with-quiche was specified but could not find quiche pkg-config file." "$LINENO" 5
    fi
  fi
fi


OPT_HYPER="yes"

if test "x$disable_http" = "xyes"; then
  # without HTTP, hyper is of no use
  OPT_HYPER="no"
fi


# Check whether --with-hyper was given.
if test "${with_hyper+set}" = set; then :
  withval=$with_hyper; OPT_HYPER=$withval
fi

case "$OPT_HYPER" in
  no)
        want_hyper="no"
    ;;
  yes)
        want_hyper="default"
    want_hyper_path=""
    ;;
  *)
        want_hyper="yes"
    want_hyper_path="$withval"
    ;;
esac

if test X"$want_hyper" != Xno; then
    CLEANLDFLAGS="$LDFLAGS"
  CLEANCPPFLAGS="$CPPFLAGS"
  CLEANLIBS="$LIBS"


    if test -n "$PKG_CONFIG"; then
      PKGCONFIG="$PKG_CONFIG"
    else
      if test -n "$ac_tool_prefix"; then
  # Extract the first word of "${ac_tool_prefix}pkg-config", so it can be a program name with args.
set dummy ${ac_tool_prefix}pkg-config; ac_word=$2
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
$as_echo_n "checking for $ac_word... " >&6; }
if ${ac_cv_path_PKGCONFIG+:} false; then :
  $as_echo_n "(cached) " >&6
else
  case $PKGCONFIG in
  [\\/]* | ?:[\\/]*)
  ac_cv_path_PKGCONFIG="$PKGCONFIG" # Let the user override the test with a path.
  ;;
  *)
  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
as_dummy="$PATH:/usr/bin:/usr/local/bin"
for as_dir in $as_dummy
do
  IFS=$as_save_IFS
  test -z "$as_dir" && as_dir=.
    for ac_exec_ext in '' $ac_executable_extensions; do
  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
    ac_cv_path_PKGCONFIG="$as_dir/$ac_word$ac_exec_ext"
    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
    break 2
  fi
done
  done
IFS=$as_save_IFS

  ;;
esac
fi
PKGCONFIG=$ac_cv_path_PKGCONFIG
if test -n "$PKGCONFIG"; then
  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PKGCONFIG" >&5
$as_echo "$PKGCONFIG" >&6; }
else
  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
fi


fi
if test -z "$ac_cv_path_PKGCONFIG"; then
  ac_pt_PKGCONFIG=$PKGCONFIG
  # Extract the first word of "pkg-config", so it can be a program name with args.
set dummy pkg-config; ac_word=$2
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
$as_echo_n "checking for $ac_word... " >&6; }
if ${ac_cv_path_ac_pt_PKGCONFIG+:} false; then :
  $as_echo_n "(cached) " >&6
else
  case $ac_pt_PKGCONFIG in
  [\\/]* | ?:[\\/]*)
  ac_cv_path_ac_pt_PKGCONFIG="$ac_pt_PKGCONFIG" # Let the user override the test with a path.
  ;;
  *)
  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
as_dummy="$PATH:/usr/bin:/usr/local/bin"
for as_dir in $as_dummy
do
  IFS=$as_save_IFS
  test -z "$as_dir" && as_dir=.
    for ac_exec_ext in '' $ac_executable_extensions; do
  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
    ac_cv_path_ac_pt_PKGCONFIG="$as_dir/$ac_word$ac_exec_ext"
    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
    break 2
  fi
done
  done
IFS=$as_save_IFS

  ;;
esac
fi
ac_pt_PKGCONFIG=$ac_cv_path_ac_pt_PKGCONFIG
if test -n "$ac_pt_PKGCONFIG"; then
  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_pt_PKGCONFIG" >&5
$as_echo "$ac_pt_PKGCONFIG" >&6; }
else
  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
fi

  if test "x$ac_pt_PKGCONFIG" = x; then
    PKGCONFIG="no"
  else
    case $cross_compiling:$ac_tool_warned in
yes:)
{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
ac_tool_warned=yes ;;
esac
    PKGCONFIG=$ac_pt_PKGCONFIG
  fi
else
  PKGCONFIG="$ac_cv_path_PKGCONFIG"
fi

    fi

    if test "x$PKGCONFIG" != "xno"; then
      { $as_echo "$as_me:${as_lineno-$LINENO}: checking for hyper options with pkg-config" >&5
$as_echo_n "checking for hyper options with pkg-config... " >&6; }
            itexists=`
    if test -n "$want_hyper_path"; then
      PKG_CONFIG_LIBDIR="$want_hyper_path"
      export PKG_CONFIG_LIBDIR
    fi
         $PKGCONFIG --exists hyper >/dev/null 2>&1 && echo 1`

      if test -z "$itexists"; then
                        PKGCONFIG="no"
        { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
      else
        { $as_echo "$as_me:${as_lineno-$LINENO}: result: found" >&5
$as_echo "found" >&6; }
      fi
    fi


  if test "$PKGCONFIG" != "no" ; then
    LIB_HYPER=`
    if test -n "$want_hyper_path"; then
      PKG_CONFIG_LIBDIR="$want_hyper_path"
      export PKG_CONFIG_LIBDIR
    fi

      $PKGCONFIG --libs-only-l hyper`
    CPP_HYPER=`
    if test -n "$want_hyper_path"; then
      PKG_CONFIG_LIBDIR="$want_hyper_path"
      export PKG_CONFIG_LIBDIR
    fi
       $PKGCONFIG --cflags-only-I hyper`
    LD_HYPER=`
    if test -n "$want_hyper_path"; then
      PKG_CONFIG_LIBDIR="$want_hyper_path"
      export PKG_CONFIG_LIBDIR
    fi

      $PKGCONFIG --libs-only-L hyper`
  else
        LIB_HYPER="-lhyper"
    if test X"$want_hyper" != Xdefault; then
      CPP_HYPER=-I"$want_hyper_path/capi/include"
      LD_HYPER="-L$want_hyper_path/target/debug"
    fi
  fi
  if test -n "$LIB_HYPER"; then
    { $as_echo "$as_me:${as_lineno-$LINENO}: -l is $LIB_HYPER" >&5
$as_echo "$as_me: -l is $LIB_HYPER" >&6;}
    { $as_echo "$as_me:${as_lineno-$LINENO}: -I is $CPP_HYPER" >&5
$as_echo "$as_me: -I is $CPP_HYPER" >&6;}
    { $as_echo "$as_me:${as_lineno-$LINENO}: -L is $LD_HYPER" >&5
$as_echo "$as_me: -L is $LD_HYPER" >&6;}

    LDFLAGS="$LDFLAGS $LD_HYPER"
    CPPFLAGS="$CPPFLAGS $CPP_HYPER"
    LIBS="$LIB_HYPER $LIBS"

    if test "x$cross_compiling" != "xyes"; then
      DIR_HYPER=`echo $LD_HYPER | $SED -e 's/^-L//'`
    fi

    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for hyper_io_new in -lhyper" >&5
$as_echo_n "checking for hyper_io_new in -lhyper... " >&6; }
if ${ac_cv_lib_hyper_hyper_io_new+:} false; then :
  $as_echo_n "(cached) " >&6
else
  ac_check_lib_save_LIBS=$LIBS
LIBS="-lhyper  $LIBS"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */


#ifdef __cplusplus
extern "C"
#endif
char hyper_io_new ();
int main (void)
{
return hyper_io_new ();
 ;
 return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"; then :
  ac_cv_lib_hyper_hyper_io_new=yes
else
  ac_cv_lib_hyper_hyper_io_new=no
fi
rm -f core conftest.err conftest.$ac_objext \
    conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_hyper_hyper_io_new" >&5
$as_echo "$ac_cv_lib_hyper_hyper_io_new" >&6; }
if test "x$ac_cv_lib_hyper_hyper_io_new" = xyes; then :

       for ac_header in hyper.h
do :
  ac_fn_c_check_header_mongrel "$LINENO" "hyper.h" "ac_cv_header_hyper_h" "$ac_includes_default"
if test "x$ac_cv_header_hyper_h" = xyes; then :
  cat >>confdefs.h <<_ACEOF
#define HAVE_HYPER_H 1
_ACEOF
 experimental="$experimental Hyper"
          { $as_echo "$as_me:${as_lineno-$LINENO}: Hyper support is experimental" >&5
$as_echo "$as_me: Hyper support is experimental" >&6;}
          curl_h1_msg="enabled (Hyper)"
          curl_h2_msg=$curl_h1_msg
          HYPER_ENABLED=1

$as_echo "#define USE_HYPER 1" >>confdefs.h

          USE_HYPER=1

          CURL_LIBRARY_PATH="$CURL_LIBRARY_PATH:$DIR_HYPER"
          export CURL_LIBRARY_PATH
          { $as_echo "$as_me:${as_lineno-$LINENO}: Added $DIR_HYPER to CURL_LIBRARY_PATH" >&5
$as_echo "$as_me: Added $DIR_HYPER to CURL_LIBRARY_PATH" >&6;}
fi

done


else
          LDFLAGS=$CLEANLDFLAGS
        CPPFLAGS=$CLEANCPPFLAGS
        LIBS=$CLEANLIBS

fi

  fi
fi



OPT_ZSH_FPATH=default

# Check whether --with-zsh-functions-dir was given.
if test "${with_zsh_functions_dir+set}" = set; then :
  withval=$with_zsh_functions_dir; OPT_ZSH_FPATH=$withval
44819
44820
44821
44822
44823
44824
44825
44826
44827
44828
44829
44830
44831
44832
44833
  fi
fi

if test "x$USE_TLS_SRP" = "x1"; then
  SUPPORT_FEATURES="$SUPPORT_FEATURES TLS-SRP"
fi

if test "x$USE_NGHTTP2" = "x1"; then
  SUPPORT_FEATURES="$SUPPORT_FEATURES HTTP2"
fi

if test "x$USE_NGTCP2" = "x1" -o "x$USE_QUICHE" = "x1"; then
  SUPPORT_FEATURES="$SUPPORT_FEATURES HTTP3"
fi








|







45121
45122
45123
45124
45125
45126
45127
45128
45129
45130
45131
45132
45133
45134
45135
  fi
fi

if test "x$USE_TLS_SRP" = "x1"; then
  SUPPORT_FEATURES="$SUPPORT_FEATURES TLS-SRP"
fi

if test "x$USE_NGHTTP2" = "x1" -o "x$USE_HYPER" = "x1"; then
  SUPPORT_FEATURES="$SUPPORT_FEATURES HTTP2"
fi

if test "x$USE_NGTCP2" = "x1" -o "x$USE_QUICHE" = "x1"; then
  SUPPORT_FEATURES="$SUPPORT_FEATURES HTTP3"
fi

44880
44881
44882
44883
44884
44885
44886



44887
44888
44889
44890
44891
44892
44893
  SUPPORT_PROTOCOLS="$SUPPORT_PROTOCOLS DICT"
fi
if test "x$CURL_DISABLE_TFTP" != "x1"; then
  SUPPORT_PROTOCOLS="$SUPPORT_PROTOCOLS TFTP"
fi
if test "x$CURL_DISABLE_GOPHER" != "x1"; then
  SUPPORT_PROTOCOLS="$SUPPORT_PROTOCOLS GOPHER"



fi
if test "x$CURL_DISABLE_MQTT" != "x1"; then
  SUPPORT_PROTOCOLS="$SUPPORT_PROTOCOLS MQTT"
fi
if test "x$CURL_DISABLE_POP3" != "x1"; then
  SUPPORT_PROTOCOLS="$SUPPORT_PROTOCOLS POP3"
  if test "x$SSL_ENABLED" = "x1"; then







>
>
>







45182
45183
45184
45185
45186
45187
45188
45189
45190
45191
45192
45193
45194
45195
45196
45197
45198
  SUPPORT_PROTOCOLS="$SUPPORT_PROTOCOLS DICT"
fi
if test "x$CURL_DISABLE_TFTP" != "x1"; then
  SUPPORT_PROTOCOLS="$SUPPORT_PROTOCOLS TFTP"
fi
if test "x$CURL_DISABLE_GOPHER" != "x1"; then
  SUPPORT_PROTOCOLS="$SUPPORT_PROTOCOLS GOPHER"
  if test "x$SSL_ENABLED" = "x1"; then
    SUPPORT_PROTOCOLS="$SUPPORT_PROTOCOLS GOPHERS"
  fi
fi
if test "x$CURL_DISABLE_MQTT" != "x1"; then
  SUPPORT_PROTOCOLS="$SUPPORT_PROTOCOLS MQTT"
fi
if test "x$CURL_DISABLE_POP3" != "x1"; then
  SUPPORT_PROTOCOLS="$SUPPORT_PROTOCOLS POP3"
  if test "x$SSL_ENABLED" = "x1"; then
47822
47823
47824
47825
47826
47827
47828

47829
47830
47831
47832
47833
47834
47835
  LDAP:             ${curl_ldap_msg}
  LDAPS:            ${curl_ldaps_msg}
  RTSP:             ${curl_rtsp_msg}
  RTMP:             ${curl_rtmp_msg}
  Metalink:         ${curl_mtlnk_msg}
  PSL:              ${curl_psl_msg}
  Alt-svc:          ${curl_altsvc_msg}

  HTTP2:            ${curl_h2_msg}
  HTTP3:            ${curl_h3_msg}
  ECH:              ${curl_ech_msg}
  Protocols:        ${SUPPORT_PROTOCOLS}
  Features:         ${SUPPORT_FEATURES}
" >&5
$as_echo "$as_me: Configured to build curl/libcurl:







>







48127
48128
48129
48130
48131
48132
48133
48134
48135
48136
48137
48138
48139
48140
48141
  LDAP:             ${curl_ldap_msg}
  LDAPS:            ${curl_ldaps_msg}
  RTSP:             ${curl_rtsp_msg}
  RTMP:             ${curl_rtmp_msg}
  Metalink:         ${curl_mtlnk_msg}
  PSL:              ${curl_psl_msg}
  Alt-svc:          ${curl_altsvc_msg}
  HTTP1:            ${curl_h1_msg}
  HTTP2:            ${curl_h2_msg}
  HTTP3:            ${curl_h3_msg}
  ECH:              ${curl_ech_msg}
  Protocols:        ${SUPPORT_PROTOCOLS}
  Features:         ${SUPPORT_FEATURES}
" >&5
$as_echo "$as_me: Configured to build curl/libcurl:
47866
47867
47868
47869
47870
47871
47872

47873
47874
47875
47876
47877
47878
47879
47880
47881
47882
47883
  LDAP:             ${curl_ldap_msg}
  LDAPS:            ${curl_ldaps_msg}
  RTSP:             ${curl_rtsp_msg}
  RTMP:             ${curl_rtmp_msg}
  Metalink:         ${curl_mtlnk_msg}
  PSL:              ${curl_psl_msg}
  Alt-svc:          ${curl_altsvc_msg}

  HTTP2:            ${curl_h2_msg}
  HTTP3:            ${curl_h3_msg}
  ECH:              ${curl_ech_msg}
  Protocols:        ${SUPPORT_PROTOCOLS}
  Features:         ${SUPPORT_FEATURES}
" >&6;}
if test -n "$experimental"; then
 cat >&2 << _EOF
  WARNING: $experimental enabled but marked EXPERIMENTAL. Use with caution!
_EOF
fi







>











48172
48173
48174
48175
48176
48177
48178
48179
48180
48181
48182
48183
48184
48185
48186
48187
48188
48189
48190
  LDAP:             ${curl_ldap_msg}
  LDAPS:            ${curl_ldaps_msg}
  RTSP:             ${curl_rtsp_msg}
  RTMP:             ${curl_rtmp_msg}
  Metalink:         ${curl_mtlnk_msg}
  PSL:              ${curl_psl_msg}
  Alt-svc:          ${curl_altsvc_msg}
  HTTP1:            ${curl_h1_msg}
  HTTP2:            ${curl_h2_msg}
  HTTP3:            ${curl_h3_msg}
  ECH:              ${curl_ech_msg}
  Protocols:        ${SUPPORT_PROTOCOLS}
  Features:         ${SUPPORT_FEATURES}
" >&6;}
if test -n "$experimental"; then
 cat >&2 << _EOF
  WARNING: $experimental enabled but marked EXPERIMENTAL. Use with caution!
_EOF
fi
Changes to jni/curl/configure.ac.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#***************************************************************************
#                                  _   _ ____  _
#  Project                     ___| | | |  _ \| |
#                             / __| | | | |_) | |
#                            | (__| |_| |  _ <| |___
#                             \___|\___/|_| \_\_____|
#
# Copyright (C) 1998 - 2020, 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 https://curl.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







|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#***************************************************************************
#                                  _   _ ____  _
#  Project                     ___| | | |  _ \| |
#                             / __| | | | |_) | |
#                            | (__| |_| |  _ <| |___
#                             \___|\___/|_| \_\_____|
#
# Copyright (C) 1998 - 2021, 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 https://curl.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
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
AC_INIT([curl], [-], [a suitable curl mailing list: https://curl.se/mail/])

XC_OVR_ZZ50
XC_OVR_ZZ60
CURL_OVERRIDE_AUTOCONF

dnl configure script copyright
AC_COPYRIGHT([Copyright (c) 1998 - 2020 Daniel Stenberg, <daniel@haxx.se>
This configure script may be copied, distributed and modified under the
terms of the curl license; see COPYING for more details])

AC_CONFIG_SRCDIR([lib/urldata.h])
AC_CONFIG_HEADERS(lib/curl_config.h)
AC_CONFIG_MACRO_DIR([m4])
AM_MAINTAINER_MODE







|







27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
AC_INIT([curl], [-], [a suitable curl mailing list: https://curl.se/mail/])

XC_OVR_ZZ50
XC_OVR_ZZ60
CURL_OVERRIDE_AUTOCONF

dnl configure script copyright
AC_COPYRIGHT([Copyright (c) 1998 - 2021 Daniel Stenberg, <daniel@haxx.se>
This configure script may be copied, distributed and modified under the
terms of the curl license; see COPYING for more details])

AC_CONFIG_SRCDIR([lib/urldata.h])
AC_CONFIG_HEADERS(lib/curl_config.h)
AC_CONFIG_MACRO_DIR([m4])
AM_MAINTAINER_MODE
162
163
164
165
166
167
168
169


170
171
172
173
174
175
176
  curl_ldaps_msg="no      (--enable-ldaps)"
   curl_rtsp_msg="no      (--enable-rtsp)"
   curl_rtmp_msg="no      (--with-librtmp)"
  curl_mtlnk_msg="no      (--with-libmetalink)"
    curl_psl_msg="no      (--with-libpsl)"
 curl_altsvc_msg="enabled";
    ssl_backends=




enable_altsvc="yes"

dnl
dnl Save some initial values the user might have provided
dnl
INITIAL_LDFLAGS=$LDFLAGS







|
>
>







162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
  curl_ldaps_msg="no      (--enable-ldaps)"
   curl_rtsp_msg="no      (--enable-rtsp)"
   curl_rtmp_msg="no      (--with-librtmp)"
  curl_mtlnk_msg="no      (--with-libmetalink)"
    curl_psl_msg="no      (--with-libpsl)"
 curl_altsvc_msg="enabled";
    ssl_backends=
     curl_h1_msg="enabled (--with-hyper)"
     curl_h2_msg="no      (--with-nghttp2)"
     curl_h3_msg="no      (--with-ngtcp2, --with-quiche)"

enable_altsvc="yes"

dnl
dnl Save some initial values the user might have provided
dnl
INITIAL_LDFLAGS=$LDFLAGS
385
386
387
388
389
390
391

392
393
394
395
396
397
398
       disable_http="yes"
       AC_MSG_WARN([disable HTTP disables FTP over proxy and RTSP])
       AC_SUBST(CURL_DISABLE_HTTP, [1])
       AC_DEFINE(CURL_DISABLE_RTSP, 1, [to disable RTSP])
       AC_SUBST(CURL_DISABLE_RTSP, [1])
       dnl toggle off alt-svc too when HTTP is disabled
       AC_DEFINE(CURL_DISABLE_ALTSVC, 1, [disable alt-svc])

       curl_altsvc_msg="no";
       enable_altsvc="no"
       ;;
  *)   AC_MSG_RESULT(yes)
       ;;
  esac ],
       AC_MSG_RESULT(yes)







>







387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
       disable_http="yes"
       AC_MSG_WARN([disable HTTP disables FTP over proxy and RTSP])
       AC_SUBST(CURL_DISABLE_HTTP, [1])
       AC_DEFINE(CURL_DISABLE_RTSP, 1, [to disable RTSP])
       AC_SUBST(CURL_DISABLE_RTSP, [1])
       dnl toggle off alt-svc too when HTTP is disabled
       AC_DEFINE(CURL_DISABLE_ALTSVC, 1, [disable alt-svc])
       curl_h1_msg="no      (--enable-http, --with-hyper)"
       curl_altsvc_msg="no";
       enable_altsvc="no"
       ;;
  *)   AC_MSG_RESULT(yes)
       ;;
  esac ],
       AC_MSG_RESULT(yes)
3548
3549
3550
3551
3552
3553
3554
3555
3556
3557
3558
3559
3560
3561
3562
  *)
    dnl --with-nghttp2 option used with path
    want_h2="yes"
    want_h2_path="$withval/lib/pkgconfig"
    ;;
esac

curl_h2_msg="no      (--with-nghttp2)"
if test X"$want_h2" != Xno; then
  dnl backup the pre-nghttp2 variables
  CLEANLDFLAGS="$LDFLAGS"
  CLEANCPPFLAGS="$CPPFLAGS"
  CLEANLIBS="$LIBS"

  CURL_CHECK_PKGCONFIG(libnghttp2, $want_h2_path)







<







3551
3552
3553
3554
3555
3556
3557

3558
3559
3560
3561
3562
3563
3564
  *)
    dnl --with-nghttp2 option used with path
    want_h2="yes"
    want_h2_path="$withval/lib/pkgconfig"
    ;;
esac


if test X"$want_h2" != Xno; then
  dnl backup the pre-nghttp2 variables
  CLEANLDFLAGS="$LDFLAGS"
  CLEANCPPFLAGS="$CPPFLAGS"
  CLEANLIBS="$LIBS"

  CURL_CHECK_PKGCONFIG(libnghttp2, $want_h2_path)
3607
3608
3609
3610
3611
3612
3613
3614
3615
3616
3617
3618
3619
3620
3621
fi

dnl **********************************************************************
dnl Check for ngtcp2 (QUIC)
dnl **********************************************************************

OPT_TCP2="yes"
curl_h3_msg="no      (--with-ngtcp2, --with-quiche)"

if test "x$disable_http" = "xyes"; then
  # without HTTP, ngtcp2 is no use
  OPT_TCP2="no"
fi

AC_ARG_WITH(ngtcp2,







<







3609
3610
3611
3612
3613
3614
3615

3616
3617
3618
3619
3620
3621
3622
fi

dnl **********************************************************************
dnl Check for ngtcp2 (QUIC)
dnl **********************************************************************

OPT_TCP2="yes"


if test "x$disable_http" = "xyes"; then
  # without HTTP, ngtcp2 is no use
  OPT_TCP2="no"
fi

AC_ARG_WITH(ngtcp2,
3982
3983
3984
3985
3986
3987
3988




























































































3989
3990
3991
3992
3993
3994
3995
    if test X"$want_quiche" != Xdefault; then
      dnl To avoid link errors, we do not allow --with-quiche without
      dnl a pkgconfig file
      AC_MSG_ERROR([--with-quiche was specified but could not find quiche pkg-config file.])
    fi
  fi
fi





























































































dnl **********************************************************************
dnl Check for zsh completion path
dnl **********************************************************************

OPT_ZSH_FPATH=default
AC_ARG_WITH(zsh-functions-dir,







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







3983
3984
3985
3986
3987
3988
3989
3990
3991
3992
3993
3994
3995
3996
3997
3998
3999
4000
4001
4002
4003
4004
4005
4006
4007
4008
4009
4010
4011
4012
4013
4014
4015
4016
4017
4018
4019
4020
4021
4022
4023
4024
4025
4026
4027
4028
4029
4030
4031
4032
4033
4034
4035
4036
4037
4038
4039
4040
4041
4042
4043
4044
4045
4046
4047
4048
4049
4050
4051
4052
4053
4054
4055
4056
4057
4058
4059
4060
4061
4062
4063
4064
4065
4066
4067
4068
4069
4070
4071
4072
4073
4074
4075
4076
4077
4078
4079
4080
4081
4082
4083
4084
4085
4086
4087
4088
    if test X"$want_quiche" != Xdefault; then
      dnl To avoid link errors, we do not allow --with-quiche without
      dnl a pkgconfig file
      AC_MSG_ERROR([--with-quiche was specified but could not find quiche pkg-config file.])
    fi
  fi
fi

dnl **********************************************************************
dnl Check for Hyper
dnl **********************************************************************

OPT_HYPER="yes"

if test "x$disable_http" = "xyes"; then
  # without HTTP, hyper is of no use
  OPT_HYPER="no"
fi

AC_ARG_WITH(hyper,
AC_HELP_STRING([--with-hyper=PATH],[Enable hyper usage])
AC_HELP_STRING([--without-hyper],[Disable hyper usage]),
  [OPT_HYPER=$withval])
case "$OPT_HYPER" in
  no)
    dnl --without-hyper option used
    want_hyper="no"
    ;;
  yes)
    dnl --with-hyper option used without path
    want_hyper="default"
    want_hyper_path=""
    ;;
  *)
    dnl --with-hyper option used with path
    want_hyper="yes"
    want_hyper_path="$withval"
    ;;
esac

if test X"$want_hyper" != Xno; then
  dnl backup the pre-hyper variables
  CLEANLDFLAGS="$LDFLAGS"
  CLEANCPPFLAGS="$CPPFLAGS"
  CLEANLIBS="$LIBS"

  CURL_CHECK_PKGCONFIG(hyper, $want_hyper_path)

  if test "$PKGCONFIG" != "no" ; then
    LIB_HYPER=`CURL_EXPORT_PCDIR([$want_hyper_path])
      $PKGCONFIG --libs-only-l hyper`
    CPP_HYPER=`CURL_EXPORT_PCDIR([$want_hyper_path]) dnl
      $PKGCONFIG --cflags-only-I hyper`
    LD_HYPER=`CURL_EXPORT_PCDIR([$want_hyper_path])
      $PKGCONFIG --libs-only-L hyper`
  else
    dnl no hyper pkg-config found
    LIB_HYPER="-lhyper"
    if test X"$want_hyper" != Xdefault; then
      CPP_HYPER=-I"$want_hyper_path/capi/include"
      LD_HYPER="-L$want_hyper_path/target/debug"
    fi
  fi
  if test -n "$LIB_HYPER"; then
    AC_MSG_NOTICE([-l is $LIB_HYPER])
    AC_MSG_NOTICE([-I is $CPP_HYPER])
    AC_MSG_NOTICE([-L is $LD_HYPER])

    LDFLAGS="$LDFLAGS $LD_HYPER"
    CPPFLAGS="$CPPFLAGS $CPP_HYPER"
    LIBS="$LIB_HYPER $LIBS"

    if test "x$cross_compiling" != "xyes"; then
      DIR_HYPER=`echo $LD_HYPER | $SED -e 's/^-L//'`
    fi

    AC_CHECK_LIB(hyper, hyper_io_new,
      [
       AC_CHECK_HEADERS(hyper.h,
          experimental="$experimental Hyper"
          AC_MSG_NOTICE([Hyper support is experimental])
          curl_h1_msg="enabled (Hyper)"
          curl_h2_msg=$curl_h1_msg
          HYPER_ENABLED=1
          AC_DEFINE(USE_HYPER, 1, [if hyper is in use])
          AC_SUBST(USE_HYPER, [1])
          CURL_LIBRARY_PATH="$CURL_LIBRARY_PATH:$DIR_HYPER"
          export CURL_LIBRARY_PATH
          AC_MSG_NOTICE([Added $DIR_HYPER to CURL_LIBRARY_PATH]),
       )
      ],
        dnl not found, revert back to clean variables
        LDFLAGS=$CLEANLDFLAGS
        CPPFLAGS=$CLEANCPPFLAGS
        LIBS=$CLEANLIBS
    )
  fi
fi


dnl **********************************************************************
dnl Check for zsh completion path
dnl **********************************************************************

OPT_ZSH_FPATH=default
AC_ARG_WITH(zsh-functions-dir,
5041
5042
5043
5044
5045
5046
5047
5048
5049
5050
5051
5052
5053
5054
5055
  fi
fi

if test "x$USE_TLS_SRP" = "x1"; then
  SUPPORT_FEATURES="$SUPPORT_FEATURES TLS-SRP"
fi

if test "x$USE_NGHTTP2" = "x1"; then
  SUPPORT_FEATURES="$SUPPORT_FEATURES HTTP2"
fi

if test "x$USE_NGTCP2" = "x1" -o "x$USE_QUICHE" = "x1"; then
  SUPPORT_FEATURES="$SUPPORT_FEATURES HTTP3"
fi








|







5134
5135
5136
5137
5138
5139
5140
5141
5142
5143
5144
5145
5146
5147
5148
  fi
fi

if test "x$USE_TLS_SRP" = "x1"; then
  SUPPORT_FEATURES="$SUPPORT_FEATURES TLS-SRP"
fi

if test "x$USE_NGHTTP2" = "x1" -o "x$USE_HYPER" = "x1"; then
  SUPPORT_FEATURES="$SUPPORT_FEATURES HTTP2"
fi

if test "x$USE_NGTCP2" = "x1" -o "x$USE_QUICHE" = "x1"; then
  SUPPORT_FEATURES="$SUPPORT_FEATURES HTTP3"
fi

5107
5108
5109
5110
5111
5112
5113



5114
5115
5116
5117
5118
5119
5120
  SUPPORT_PROTOCOLS="$SUPPORT_PROTOCOLS DICT"
fi
if test "x$CURL_DISABLE_TFTP" != "x1"; then
  SUPPORT_PROTOCOLS="$SUPPORT_PROTOCOLS TFTP"
fi
if test "x$CURL_DISABLE_GOPHER" != "x1"; then
  SUPPORT_PROTOCOLS="$SUPPORT_PROTOCOLS GOPHER"



fi
if test "x$CURL_DISABLE_MQTT" != "x1"; then
  SUPPORT_PROTOCOLS="$SUPPORT_PROTOCOLS MQTT"
fi
if test "x$CURL_DISABLE_POP3" != "x1"; then
  SUPPORT_PROTOCOLS="$SUPPORT_PROTOCOLS POP3"
  if test "x$SSL_ENABLED" = "x1"; then







>
>
>







5200
5201
5202
5203
5204
5205
5206
5207
5208
5209
5210
5211
5212
5213
5214
5215
5216
  SUPPORT_PROTOCOLS="$SUPPORT_PROTOCOLS DICT"
fi
if test "x$CURL_DISABLE_TFTP" != "x1"; then
  SUPPORT_PROTOCOLS="$SUPPORT_PROTOCOLS TFTP"
fi
if test "x$CURL_DISABLE_GOPHER" != "x1"; then
  SUPPORT_PROTOCOLS="$SUPPORT_PROTOCOLS GOPHER"
  if test "x$SSL_ENABLED" = "x1"; then
    SUPPORT_PROTOCOLS="$SUPPORT_PROTOCOLS GOPHERS"
  fi
fi
if test "x$CURL_DISABLE_MQTT" != "x1"; then
  SUPPORT_PROTOCOLS="$SUPPORT_PROTOCOLS MQTT"
fi
if test "x$CURL_DISABLE_POP3" != "x1"; then
  SUPPORT_PROTOCOLS="$SUPPORT_PROTOCOLS POP3"
  if test "x$SSL_ENABLED" = "x1"; then
5258
5259
5260
5261
5262
5263
5264

5265
5266
5267
5268
5269
5270
5271
5272
5273
5274
5275
  LDAP:             ${curl_ldap_msg}
  LDAPS:            ${curl_ldaps_msg}
  RTSP:             ${curl_rtsp_msg}
  RTMP:             ${curl_rtmp_msg}
  Metalink:         ${curl_mtlnk_msg}
  PSL:              ${curl_psl_msg}
  Alt-svc:          ${curl_altsvc_msg}

  HTTP2:            ${curl_h2_msg}
  HTTP3:            ${curl_h3_msg}
  ECH:              ${curl_ech_msg}
  Protocols:        ${SUPPORT_PROTOCOLS}
  Features:         ${SUPPORT_FEATURES}
])
if test -n "$experimental"; then
 cat >&2 << _EOF
  WARNING: $experimental enabled but marked EXPERIMENTAL. Use with caution!
_EOF
fi







>











5354
5355
5356
5357
5358
5359
5360
5361
5362
5363
5364
5365
5366
5367
5368
5369
5370
5371
5372
  LDAP:             ${curl_ldap_msg}
  LDAPS:            ${curl_ldaps_msg}
  RTSP:             ${curl_rtsp_msg}
  RTMP:             ${curl_rtmp_msg}
  Metalink:         ${curl_mtlnk_msg}
  PSL:              ${curl_psl_msg}
  Alt-svc:          ${curl_altsvc_msg}
  HTTP1:            ${curl_h1_msg}
  HTTP2:            ${curl_h2_msg}
  HTTP3:            ${curl_h3_msg}
  ECH:              ${curl_ech_msg}
  Protocols:        ${SUPPORT_PROTOCOLS}
  Features:         ${SUPPORT_FEATURES}
])
if test -n "$experimental"; then
 cat >&2 << _EOF
  WARNING: $experimental enabled but marked EXPERIMENTAL. Use with caution!
_EOF
fi
Changes to jni/curl/docs/BUG-BOUNTY.md.
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
This bounty is relying on funds from sponsors. If you use curl professionally,
consider help funding this! See
[https://opencollective.com/curl](https://opencollective.com/curl) for
details.

# What are the reward amounts?

The curl projects offer monetary compensation for reported and published
security vulnerabilities. The amount of money that is rewarded depends on how
serious the flaw is determined to be.

We offer reward money *up to* a certain amount per severity. The curl security
team determines the severity of each reported flaw on a case by case basis and
the exact amount rewarded to the reporter is then decided.








|







18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
This bounty is relying on funds from sponsors. If you use curl professionally,
consider help funding this! See
[https://opencollective.com/curl](https://opencollective.com/curl) for
details.

# What are the reward amounts?

The curl project offers monetary compensation for reported and published
security vulnerabilities. The amount of money that is rewarded depends on how
serious the flaw is determined to be.

We offer reward money *up to* a certain amount per severity. The curl security
team determines the severity of each reported flaw on a case by case basis and
the exact amount rewarded to the reporter is then decided.

42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67

The vulnerability has to be fixed and publicly announced (by the curl project)
before a bug bounty will be considered.

Bounties need to be requested within twelve months from the publication of the
vulnerability.

The vulnerabilities must not have been made public before February 1st, 2019.
We do not retroactively pay for old, already known, or published security
problems.

# Product vulnerabilities only

This bug bounty only concerns the curl and libcurl products and thus their
respective source codes - when running on existing hardware. It does not
include documentation, websites, or other infrastructure.

The curl security team will be the sole arbiter if a reported flaw can be
subject to a bounty or not.

# How are vulnerabilities graded?

The grading of each reported vulnerability that makes a reward claim will be
performed by the curl security team. The grading will be based on the CVSS
(Common Vulnerability Scoring System) 3.0.








<
<
<
<






|
|







42
43
44
45
46
47
48




49
50
51
52
53
54
55
56
57
58
59
60
61
62
63

The vulnerability has to be fixed and publicly announced (by the curl project)
before a bug bounty will be considered.

Bounties need to be requested within twelve months from the publication of the
vulnerability.





# Product vulnerabilities only

This bug bounty only concerns the curl and libcurl products and thus their
respective source codes - when running on existing hardware. It does not
include documentation, websites, or other infrastructure.

The curl security team is the sole arbiter if a reported flaw is subject to a
bounty or not.

# How are vulnerabilities graded?

The grading of each reported vulnerability that makes a reward claim will be
performed by the curl security team. The grading will be based on the CVSS
(Common Vulnerability Scoring System) 3.0.

Changes to jni/curl/docs/CODE_REVIEW.md.
158
159
160
161
162
163
164
165
166
167
168
Make extra precautions and verify that memory buffers that need a terminating
zero always have exactly that. Buffers *without* a zero terminator must not be
used as input to string functions.

# Commit messages

Tightly coupled with a code review is making sure that the commit message is
good. It is the responsibilitiy of the person who merges the code to make sure
that the commit message follows our standard (detailed in the
[CONTRIBUTE.md](CONTRIBUTE.md) document). This includes making sure the PR
identifies related issues and giving credit to reporters and helpers.







|



158
159
160
161
162
163
164
165
166
167
168
Make extra precautions and verify that memory buffers that need a terminating
zero always have exactly that. Buffers *without* a zero terminator must not be
used as input to string functions.

# Commit messages

Tightly coupled with a code review is making sure that the commit message is
good. It is the responsibility of the person who merges the code to make sure
that the commit message follows our standard (detailed in the
[CONTRIBUTE.md](CONTRIBUTE.md) document). This includes making sure the PR
identifies related issues and giving credit to reporters and helpers.
Changes to jni/curl/docs/CODE_STYLE.md.
32
33
34
35
36
37
38

39
40
41
42
43

44
45
46
47
48
49

50

51
52
53
54
55
56
57
library-global symbols.

## Indenting

We use only spaces for indentation, never TABs. We use two spaces for each new
open brace.


    if(something_is_true) {
      while(second_statement == fine) {
        moo();
      }
    }


## Comments

Since we write C89 code, **//** comments are not allowed. They weren't
introduced in the C standard until C99. We use only **/* comments */**.


    /* this is a comment */


## Long lines

Source code in curl may never be wider than 79 columns and there are two
reasons for maintaining this even in the modern era of very large and high
resolution screens:








>
|
|
|
|
|
>






>
|
>







32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
library-global symbols.

## Indenting

We use only spaces for indentation, never TABs. We use two spaces for each new
open brace.

```c
if(something_is_true) {
  while(second_statement == fine) {
    moo();
  }
}
```

## Comments

Since we write C89 code, **//** comments are not allowed. They weren't
introduced in the C standard until C99. We use only **/* comments */**.

```c
/* this is a comment */
```

## Long lines

Source code in curl may never be wider than 79 columns and there are two
reasons for maintaining this even in the modern era of very large and high
resolution screens:

65
66
67
68
69
70
71

72
73
74

75
76
77

78
79

80
81
82

83
84
85
86

87
88
89
90
91
92

93
94
95
96
97
98

99
100
101
102
103
104

105
106
107

108
109
110
111
112
113
114

115
116
117
118
119

120
121
122
123
124
125

126
127

128
129
130

131
132
133

134
135
136
137
138
139

140
141
142
143

144
145
146

147
148

149
150
151
152
153
154
155
156
157

158
159
160
161
162
163
164
165
166
167
168

169
170
171
172
173

174
175
176
177

178
179
180
181
182
183

184

185
186
187
188
189
190
191
192
193
194
195
196
197

198
199
200
201
202
203

204
205
206

207
208

209
210
211

212
213
214
215
216
217

218
219
220

221
222
223

224
225
226
227
228
229
230
231
232
233
234
235
236

237
238
239
240
241
242
243
244
245
246

247
248
249
250
251
252

253
254
255
256
257

258
259
260

261
262
263
264
265


## Braces

In if/while/do/for expressions, we write the open brace on the same line as
the keyword and we then set the closing brace on the same indentation level as
the initial keyword. Like this:


    if(age < 40) {
      /* clearly a youngster */
    }


You may omit the braces if they would contain only a one-line statement:


    if(!x)
      continue;


For functions the opening brace should be on a separate line:


    int main(int argc, char **argv)
    {
      return 1;
    }


## 'else' on the following line

When adding an **else** clause to a conditional expression using braces, we
add it on a new line after the closing brace. Like this:


    if(age < 40) {
      /* clearly a youngster */
    }
    else {
      /* probably grumpy */
    }


## No space before parentheses

When writing expressions using if/while/do/for, there shall be no space
between the keyword and the open parenthesis. Like this:


    while(1) {
      /* loop forever */
    }


## Use boolean conditions

Rather than test a conditional value such as a bool against TRUE or FALSE, a
pointer against NULL or != NULL and an int against zero or not zero in
if/while conditions we prefer:


    result = do_something();
    if(!result) {
      /* something went wrong */
      return result;
    }


## No assignments in conditions

To increase readability and reduce complexity of conditionals, we avoid
assigning variables within if/while conditions. We frown upon this style:


    if((ptr = malloc(100)) == NULL)
      return NULL;


and instead we encourage the above version to be spelled out more clearly:


    ptr = malloc(100);
    if(!ptr)
      return NULL;


## New block on a new line

We never write multiple statements on the same source line, even for very
short if() conditions.


    if(a)
      return TRUE;
    else if(b)
      return FALSE;


and NEVER:


    if(a) return TRUE;
    else if(b) return FALSE;


## Space around operators

Please use spaces on both sides of operators in C expressions.  Postfix **(),
[], ->, ., ++, --** and Unary **+, - !, ~, &** operators excluded they should
have no space.

Examples:


    bla = func();
    who = name[0];
    age += 1;
    true = !false;
    size += -2 + 3 * (a + b);
    ptr->member = a++;
    struct.field = b--;
    ptr = &address;
    contents = *pointer;
    complement = ~bits;
    empty = (!*string) ? TRUE : FALSE;


## No parentheses for return values

We use the 'return' statement without extra parentheses around the value:


    int works(void)
    {
      return TRUE;
    }


## Parentheses for sizeof arguments

When using the sizeof operator in code, we prefer it to be written with
parentheses around its argument:


    int size = sizeof(int);


## Column alignment

Some statements cannot be completed on a single line because the line would be
too long, the statement too hard to read, or due to other style guidelines
above. In such a case the statement will span multiple lines.

If a continuation line is part of an expression or sub-expression then you
should align on the appropriate column so that it's easy to tell what part of
the statement it is. Operators should not start continuation lines. In other
cases follow the 2-space indent guideline. Here are some examples from
libcurl:


    if(Curl_pipeline_wanted(handle->multi, CURLPIPE_HTTP1) &&
       (handle->set.httpversion != CURL_HTTP_VERSION_1_0) &&
       (handle->set.httpreq == HTTPREQ_GET ||
        handle->set.httpreq == HTTPREQ_HEAD))
      /* didn't ask for HTTP/1.0 and a GET or HEAD */
      return TRUE;


If no parenthesis, use the default indent:


    data->set.http_disable_hostname_check_before_authentication =
      (0 != va_arg(param, long)) ? TRUE : FALSE;


Function invoke with an open parenthesis:


    if(option) {
      result = parse_login_details(option, strlen(option),
                                   (userp ? &user : NULL),
                                   (passwdp ? &passwd : NULL),
                                   NULL);
    }


Align with the "current open" parenthesis:


    DEBUGF(infof(data, "Curl_pp_readresp_ %d bytes of trailing "
                 "server response left\n",
                 (int)clipamount));


## Platform dependent code

Use **#ifdef HAVE_FEATURE** to do conditional code. We avoid checking for
particular operating systems or hardware in the #ifdef lines. The HAVE_FEATURE
shall be generated by the configure script for unix-like systems and they are
hard-coded in the `config-[system].h` files for the others.

We also encourage use of macros/functions that possibly are empty or defined
to constants when libcurl is built without that feature, to make the code
seamless. Like this example where the **magic()** function works differently
depending on a build-time conditional:


    #ifdef HAVE_MAGIC
    void magic(int a)
    {
      return a + 2;
    }
    #else
    #define magic(x) 1
    #endif

    int content = magic(3);


## No typedefed structs

Use structs by all means, but do not typedef them. Use the `struct name` way
of identifying them:


    struct something {
       void *valid;
       size_t way_to_write;
    };
    struct something instance;


**Not okay**:


    typedef struct {
       void *wrong;
       size_t way_to_write;
    } something;
    something instance;








>
|
|
|
>



>
|
|
>



>
|
|
|
|
>






>
|
|
|
|
|
|
>






>
|
|
|
>







>
|
|
|
|
|
>






>
|
|
>



>
|
|
|
>






>
|
|
|
|
>



>
|
|
>









>
|
|
|
|
|
|
|
|
|
|
|
>





>
|
|
|
|
>






>
|
>













>
|
|
|
|
|
|
>



>
|
|
>



>
|
|
|
|
|
|
>



>
|
|
|
>













>
|
|
|
|
|
|
|
|

|
>






>
|
|
|
|
|
>



>
|
|
|
|
|
>
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309

## Braces

In if/while/do/for expressions, we write the open brace on the same line as
the keyword and we then set the closing brace on the same indentation level as
the initial keyword. Like this:

```c
if(age < 40) {
  /* clearly a youngster */
}
```

You may omit the braces if they would contain only a one-line statement:

```c
if(!x)
  continue;
```

For functions the opening brace should be on a separate line:

```c
int main(int argc, char **argv)
{
  return 1;
}
```

## 'else' on the following line

When adding an **else** clause to a conditional expression using braces, we
add it on a new line after the closing brace. Like this:

```c
if(age < 40) {
  /* clearly a youngster */
}
else {
  /* probably grumpy */
}
```

## No space before parentheses

When writing expressions using if/while/do/for, there shall be no space
between the keyword and the open parenthesis. Like this:

```c
while(1) {
  /* loop forever */
}
```

## Use boolean conditions

Rather than test a conditional value such as a bool against TRUE or FALSE, a
pointer against NULL or != NULL and an int against zero or not zero in
if/while conditions we prefer:

```c
result = do_something();
if(!result) {
  /* something went wrong */
  return result;
}
```

## No assignments in conditions

To increase readability and reduce complexity of conditionals, we avoid
assigning variables within if/while conditions. We frown upon this style:

```c
if((ptr = malloc(100)) == NULL)
  return NULL;
```

and instead we encourage the above version to be spelled out more clearly:

```c
ptr = malloc(100);
if(!ptr)
  return NULL;
```

## New block on a new line

We never write multiple statements on the same source line, even for very
short if() conditions.

```c
if(a)
  return TRUE;
else if(b)
  return FALSE;
```

and NEVER:

```c
if(a) return TRUE;
else if(b) return FALSE;
```

## Space around operators

Please use spaces on both sides of operators in C expressions.  Postfix **(),
[], ->, ., ++, --** and Unary **+, - !, ~, &** operators excluded they should
have no space.

Examples:

```c
bla = func();
who = name[0];
age += 1;
true = !false;
size += -2 + 3 * (a + b);
ptr->member = a++;
struct.field = b--;
ptr = &address;
contents = *pointer;
complement = ~bits;
empty = (!*string) ? TRUE : FALSE;
```

## No parentheses for return values

We use the 'return' statement without extra parentheses around the value:

```c
int works(void)
{
  return TRUE;
}
```

## Parentheses for sizeof arguments

When using the sizeof operator in code, we prefer it to be written with
parentheses around its argument:

```c
int size = sizeof(int);
```

## Column alignment

Some statements cannot be completed on a single line because the line would be
too long, the statement too hard to read, or due to other style guidelines
above. In such a case the statement will span multiple lines.

If a continuation line is part of an expression or sub-expression then you
should align on the appropriate column so that it's easy to tell what part of
the statement it is. Operators should not start continuation lines. In other
cases follow the 2-space indent guideline. Here are some examples from
libcurl:

```c
if(Curl_pipeline_wanted(handle->multi, CURLPIPE_HTTP1) &&
   (handle->set.httpversion != CURL_HTTP_VERSION_1_0) &&
   (handle->set.httpreq == HTTPREQ_GET ||
    handle->set.httpreq == HTTPREQ_HEAD))
  /* didn't ask for HTTP/1.0 and a GET or HEAD */
  return TRUE;
```

If no parenthesis, use the default indent:

```c
data->set.http_disable_hostname_check_before_authentication =
  (0 != va_arg(param, long)) ? TRUE : FALSE;
```

Function invoke with an open parenthesis:

```c
if(option) {
  result = parse_login_details(option, strlen(option),
                               (userp ? &user : NULL),
                               (passwdp ? &passwd : NULL),
                               NULL);
}
```

Align with the "current open" parenthesis:

```c
DEBUGF(infof(data, "Curl_pp_readresp_ %d bytes of trailing "
             "server response left\n",
             (int)clipamount));
```

## Platform dependent code

Use **#ifdef HAVE_FEATURE** to do conditional code. We avoid checking for
particular operating systems or hardware in the #ifdef lines. The HAVE_FEATURE
shall be generated by the configure script for unix-like systems and they are
hard-coded in the `config-[system].h` files for the others.

We also encourage use of macros/functions that possibly are empty or defined
to constants when libcurl is built without that feature, to make the code
seamless. Like this example where the **magic()** function works differently
depending on a build-time conditional:

```c
#ifdef HAVE_MAGIC
void magic(int a)
{
  return a + 2;
}
#else
#define magic(x) 1
#endif

int content = magic(3);
```

## No typedefed structs

Use structs by all means, but do not typedef them. Use the `struct name` way
of identifying them:

```c
struct something {
   void *valid;
   size_t way_to_write;
};
struct something instance;
```

**Not okay**:

```c
typedef struct {
   void *wrong;
   size_t way_to_write;
} something;
something instance;
```
Changes to jni/curl/docs/DYNBUF.md.
1
2
3
4
5
6
7
8
9
10
11
12
13

14

15
16
17
18
19
20
21

22

23
24
25
26
27
28

29

30
31
32
33
34

35

36
37
38
39
40

41

42
43
44
45
46

47

48
49
50
51
52

53

54
55
56
57
58

59

60
61
62
63
64
65
66

67

68
69
70
71
72
73
74

75

76
77
78
79
80
81
82

83

84
85
86
# dynbuf

This is the internal module for creating and handling "dynamic buffers". This
means buffers that can be appended to, dynamically and grow in size to adapt.

There will always be a terminating zero put at the end of the dynamic buffer.

The `struct dynbuf` is used to hold data for each instance of a dynamic
buffer. The members of that struct **MUST NOT** be accessed or modified
without using the dedicated dynbuf API.

## init


    void Curl_dyn_init(struct dynbuf *s, size_t toobig);


This inits a struct to use for dynbuf and it can't fail. The `toobig` value
**must** be set to the maximum size we allow this buffer instance to grow to.
The functions below will return `CURLE_OUT_OF_MEMORY` when hitting this limit.

## free


    void Curl_dyn_free(struct dynbuf *s);


Free the associated memory and clean up. After a free, the `dynbuf` struct can
be re-used to start appending new data to.

## addn


    CURLcode Curl_dyn_addn(struct dynbuf *s, const void *mem, size_t len);


Append arbitrary data of a given length to the end of the buffer.

## add


    CURLcode Curl_dyn_add(struct dynbuf *s, const char *str);


Append a C string to the end of the buffer.

## addf


    CURLcode Curl_dyn_addf(struct dynbuf *s, const char *fmt, ...);


Append a `printf()`-style string to the end of the buffer.

## vaddf


    CURLcode Curl_dyn_vaddf(struct dynbuf *s, const char *fmt, va_list ap);


Append a `vprintf()`-style string to the end of the buffer.

## reset


    void Curl_dyn_reset(struct dynbuf *s);


Reset the buffer length, but leave the allocation.

## tail


    CURLcode Curl_dyn_tail(struct dynbuf *s, size_t length)


Keep `length` bytes of the buffer tail (the last `length` bytes of the
buffer). The rest of the buffer is dropped. The specified `length` must not be
larger than the buffer length.

## ptr


    char *Curl_dyn_ptr(const struct dynbuf *s);


Returns a `char *` to the buffer if it has a length, otherwise a NULL. Since
the buffer may be reallocated, this pointer should not be trusted or used
anymore after the next buffer manipulation call.

## uptr


    unsigned char *Curl_dyn_uptr(const struct dynbuf *s);


Returns an `unsigned char *` to the buffer if it has a length, otherwise a
NULL. Since the buffer may be reallocated, this pointer should not be trusted
or used anymore after the next buffer manipulation call.

## len


    size_t Curl_dyn_len(const struct dynbuf *s);


Returns the length of the buffer in bytes. Does not include the terminating
zero byte.













>
|
>







>
|
>






>
|
>





>
|
>





>
|
>





>
|
>





>
|
>





>
|
>







>
|
>







>
|
>







>
|
>



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
# dynbuf

This is the internal module for creating and handling "dynamic buffers". This
means buffers that can be appended to, dynamically and grow in size to adapt.

There will always be a terminating zero put at the end of the dynamic buffer.

The `struct dynbuf` is used to hold data for each instance of a dynamic
buffer. The members of that struct **MUST NOT** be accessed or modified
without using the dedicated dynbuf API.

## init

```c
void Curl_dyn_init(struct dynbuf *s, size_t toobig);
```

This inits a struct to use for dynbuf and it can't fail. The `toobig` value
**must** be set to the maximum size we allow this buffer instance to grow to.
The functions below will return `CURLE_OUT_OF_MEMORY` when hitting this limit.

## free

```c
void Curl_dyn_free(struct dynbuf *s);
```

Free the associated memory and clean up. After a free, the `dynbuf` struct can
be re-used to start appending new data to.

## addn

```c
CURLcode Curl_dyn_addn(struct dynbuf *s, const void *mem, size_t len);
```

Append arbitrary data of a given length to the end of the buffer.

## add

```c
CURLcode Curl_dyn_add(struct dynbuf *s, const char *str);
```

Append a C string to the end of the buffer.

## addf

```c
CURLcode Curl_dyn_addf(struct dynbuf *s, const char *fmt, ...);
```

Append a `printf()`-style string to the end of the buffer.

## vaddf

```c
CURLcode Curl_dyn_vaddf(struct dynbuf *s, const char *fmt, va_list ap);
```

Append a `vprintf()`-style string to the end of the buffer.

## reset

```c
void Curl_dyn_reset(struct dynbuf *s);
```

Reset the buffer length, but leave the allocation.

## tail

```c
CURLcode Curl_dyn_tail(struct dynbuf *s, size_t length);
```

Keep `length` bytes of the buffer tail (the last `length` bytes of the
buffer). The rest of the buffer is dropped. The specified `length` must not be
larger than the buffer length.

## ptr

```c
char *Curl_dyn_ptr(const struct dynbuf *s);
```

Returns a `char *` to the buffer if it has a length, otherwise a NULL. Since
the buffer may be reallocated, this pointer should not be trusted or used
anymore after the next buffer manipulation call.

## uptr

```c
unsigned char *Curl_dyn_uptr(const struct dynbuf *s);
```

Returns an `unsigned char *` to the buffer if it has a length, otherwise a
NULL. Since the buffer may be reallocated, this pointer should not be trusted
or used anymore after the next buffer manipulation call.

## len

```c
size_t Curl_dyn_len(const struct dynbuf *s);
```

Returns the length of the buffer in bytes. Does not include the terminating
zero byte.
Changes to jni/curl/docs/EXPERIMENTAL.md.
14
15
16
17
18
19
20

21
22
23
24
4. **We reserve the right to change behavior** of the feature without sticking
   to our API/ABI rules as we do for regular features, as long as it is marked
   experimental.
5. Experimental features are clearly marked so in documentation. Beware.

## Experimental features right now


 - HTTP/3 support and options
 - CURLSSLOPT_NATIVE_CA (No configure option, feature built in when supported)
 - HSTS support and options
 







>



<
14
15
16
17
18
19
20
21
22
23
24

4. **We reserve the right to change behavior** of the feature without sticking
   to our API/ABI rules as we do for regular features, as long as it is marked
   experimental.
5. Experimental features are clearly marked so in documentation. Beware.

## Experimental features right now

 - The Hyper HTTP backend
 - HTTP/3 support and options
 - CURLSSLOPT_NATIVE_CA (No configure option, feature built in when supported)
 - HSTS support and options

Changes to jni/curl/docs/FAQ.
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
  4.19 Why doesn't curl return an error when the network cable is unplugged?
  4.20 curl doesn't return error for HTTP non-200 responses!

 5. libcurl Issues
  5.1 Is libcurl thread-safe?
  5.2 How can I receive all data into a large memory chunk?
  5.3 How do I fetch multiple files with libcurl?
  5.4 Does libcurl do Winsock initing on win32 systems?
  5.5 Does CURLOPT_WRITEDATA and CURLOPT_READDATA work on win32 ?
  5.6 What about Keep-Alive or persistent connections?
  5.7 Link errors when building libcurl on Windows!
  5.8 libcurl.so.X: open failed: No such file or directory
  5.9 How does libcurl resolve host names?
  5.10 How do I prevent libcurl from writing the response to stdout?
  5.11 How do I make libcurl not receive the whole HTTP response?







|







79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
  4.19 Why doesn't curl return an error when the network cable is unplugged?
  4.20 curl doesn't return error for HTTP non-200 responses!

 5. libcurl Issues
  5.1 Is libcurl thread-safe?
  5.2 How can I receive all data into a large memory chunk?
  5.3 How do I fetch multiple files with libcurl?
  5.4 Does libcurl do Winsock initialization on win32 systems?
  5.5 Does CURLOPT_WRITEDATA and CURLOPT_READDATA work on win32 ?
  5.6 What about Keep-Alive or persistent connections?
  5.7 Link errors when building libcurl on Windows!
  5.8 libcurl.so.X: open failed: No such file or directory
  5.9 How does libcurl resolve host names?
  5.10 How do I prevent libcurl from writing the response to stdout?
  5.11 How do I make libcurl not receive the whole HTTP response?
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
  choose to ignore it and return the full document anyway.

  4.12 Why do I get "certificate verify failed" ?

  When you invoke curl and get an error 60 error back it means that curl
  couldn't verify that the server's certificate was good. curl verifies the
  certificate using the CA cert bundle and verifying for which names the
  certficiate has been granted.

  To completely disable the certficiate verification, use -k. This does
  however enable man-in-the-middle attacks and makes the transfer INSECURE.
  We strongly advice against doing this for more than experiments.

  If you get this failure with a CA cert bundle installed and used, the
  server's certificate might not be signed by one of the CA's in yout CA
  store. It might for example be self-signed. You then correct this problem by
  obtaining a valid CA cert for the server. Or again, decrease the security by







|

|







911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
  choose to ignore it and return the full document anyway.

  4.12 Why do I get "certificate verify failed" ?

  When you invoke curl and get an error 60 error back it means that curl
  couldn't verify that the server's certificate was good. curl verifies the
  certificate using the CA cert bundle and verifying for which names the
  certificate has been granted.

  To completely disable the certificate verification, use -k. This does
  however enable man-in-the-middle attacks and makes the transfer INSECURE.
  We strongly advice against doing this for more than experiments.

  If you get this failure with a CA cert bundle installed and used, the
  server's certificate might not be signed by one of the CA's in yout CA
  store. It might for example be self-signed. You then correct this problem by
  obtaining a valid CA cert for the server. Or again, decrease the security by
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
  libcurl will potentially internally use threads for name resolving, if it
  was built to work like that, but in those cases it'll create the child
  threads by itself and they will only be used and then killed internally by
  libcurl and never exposed to the outside.

6. License Issues

  curl and libcurl are released under a MIT/X derivate license. The license is
  very liberal and should not impose a problem for your project. This section
  is just a brief summary for the cases we get the most questions. (Parts of
  this section was much enhanced by Bjorn Reese.)

  We are not lawyers and this is not legal advice. You should probably consult
  one if you want true and accurate legal insights without our prejudice. Note
  especially that this section concerns the libcurl license only; compiling in
  features of libcurl that depend on other libraries (e.g. OpenSSL) may affect
  the licensing obligations of your application.

  6.1 I have a GPL program, can I use the libcurl library?

  Yes!

  Since libcurl may be distributed under the MIT/X derivate license, it can be
  used together with GPL in any software.

  6.2 I have a closed-source program, can I use the libcurl library?

  Yes!

  libcurl does not put any restrictions on the program that uses the library.







|














|







1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
  libcurl will potentially internally use threads for name resolving, if it
  was built to work like that, but in those cases it'll create the child
  threads by itself and they will only be used and then killed internally by
  libcurl and never exposed to the outside.

6. License Issues

  curl and libcurl are released under a MIT/X derivative license. The license is
  very liberal and should not impose a problem for your project. This section
  is just a brief summary for the cases we get the most questions. (Parts of
  this section was much enhanced by Bjorn Reese.)

  We are not lawyers and this is not legal advice. You should probably consult
  one if you want true and accurate legal insights without our prejudice. Note
  especially that this section concerns the libcurl license only; compiling in
  features of libcurl that depend on other libraries (e.g. OpenSSL) may affect
  the licensing obligations of your application.

  6.1 I have a GPL program, can I use the libcurl library?

  Yes!

  Since libcurl may be distributed under the MIT/X derivative license, it can be
  used together with GPL in any software.

  6.2 I have a closed-source program, can I use the libcurl library?

  Yes!

  libcurl does not put any restrictions on the program that uses the library.
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434

  The LGPL license doesn't clash with other licenses.

  6.5 Can I modify curl/libcurl for my program and keep the changes secret?

  Yes!

  The MIT/X derivate license practically allows you to do almost anything with
  the sources, on the condition that the copyright texts in the sources are
  left intact.

  6.6 Can you please change the curl/libcurl license to XXXX?

  No.








|







1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434

  The LGPL license doesn't clash with other licenses.

  6.5 Can I modify curl/libcurl for my program and keep the changes secret?

  Yes!

  The MIT/X derivative license practically allows you to do almost anything with
  the sources, on the condition that the copyright texts in the sources are
  left intact.

  6.6 Can you please change the curl/libcurl license to XXXX?

  No.

Changes to jni/curl/docs/HELP-US.md.
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
enough. Simple issues get handled very fast.

If you're looking for a smaller or simpler task in the project to help out
with as an entry-point into the project, perhaps because you are a newcomer or
even maybe not a terribly experienced developer, here's our advice:

 - Read through this document to get a grasp on a general approach to use
 - Consider adding a test case for something not currentled tested (correctly)
 - Consider updating or adding documentation
 - One way to get your feet wet gently in the project, is to participate in an
   existing issue/PR and help out by reproducing the issue, review the code in
   the PR etc.

## Help wanted








|







22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
enough. Simple issues get handled very fast.

If you're looking for a smaller or simpler task in the project to help out
with as an entry-point into the project, perhaps because you are a newcomer or
even maybe not a terribly experienced developer, here's our advice:

 - Read through this document to get a grasp on a general approach to use
 - Consider adding a test case for something not currently tested (correctly)
 - Consider updating or adding documentation
 - One way to get your feet wet gently in the project, is to participate in an
   existing issue/PR and help out by reproducing the issue, review the code in
   the PR etc.

## Help wanted

Changes to jni/curl/docs/HISTORY.md.
1
2
3
4
5
6
7
8
9
10
11
12



13
14
15


16
17
18



19
20
21
22
23
24
25







26
27
28






29
30
31
32
33
34
35
36
37
38
39
How curl Became Like This
=========================

Towards the end of 1996, Daniel Stenberg was spending time writing an IRC bot
for an Amiga related channel on EFnet. He then came up with the idea to make
currency-exchange calculations available to Internet Relay Chat (IRC)
users. All the necessary data were published on the Web; he just needed to
automate their retrieval.

1996
----




Daniel adopted an existing command-line open-source tool, httpget, that
Brazilian Rafael Sagula had written and recently released version 0.1
of. After a few minor adjustments, it did just what he needed.



1997
----




HttpGet 1.0 was released on April 8th 1997 with brand new HTTP proxy support.

We soon found and fixed support for getting currencies over GOPHER.  Once FTP
download support was added, the name of the project was changed and urlget 2.0
was released in August 1997. The http-only days were already passed.








1998
----







The project slowly grew bigger. When upload capabilities were added and the
name once again was misleading, a second name change was made and on March 20,
1998 curl 4 was released. (The version numbering from the previous names was
kept.)

(Unrelated to this project a company called Curl Corporation registered a US
trademark on the name "CURL" on May 18 1998. That company had then already
registered the curl.com domain back in November of the previous year. All this
was revealed to us much later.)

SSL support was added, powered by the SSLeay library.












>
>
>
|
<
|
>
>



>
>
>







>
>
>
>
>
>
>



>
>
>
>
>
>
|
|
|
<







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51

52
53
54
55
56
57
58
How curl Became Like This
=========================

Towards the end of 1996, Daniel Stenberg was spending time writing an IRC bot
for an Amiga related channel on EFnet. He then came up with the idea to make
currency-exchange calculations available to Internet Relay Chat (IRC)
users. All the necessary data were published on the Web; he just needed to
automate their retrieval.

1996
----

On November 11, 1996 the Brazilian developer Rafael Sagula wrote and released
HttpGet version 0.1.

Daniel extended this existing command-line open-source tool. After a few minor

adjustments, it did just what he needed. The first release with Daniel's
additions was 0.2, released on December 17, 1996. Daniel quickly became the
new maintainer of the project.

1997
----

HttpGet 0.3 was released in January 1997 and now it accepted HTTP URLs on the
command line.

HttpGet 1.0 was released on April 8th 1997 with brand new HTTP proxy support.

We soon found and fixed support for getting currencies over GOPHER.  Once FTP
download support was added, the name of the project was changed and urlget 2.0
was released in August 1997. The http-only days were already passed.

Version 2.2 was released on August 14 1997 and introduced support to build for
and run on Windows and Solaris.

November 24 1997: Version 3.1 added FTP upload support.

Version 3.5 added support for HTTP POST.

1998
----

February 4: urlget 3.10

February 9: urlget 3.11

March 14: urlget 3.12 added proxy authentication.

The project slowly grew bigger. With upload capabilities, the name was once
again misleading and a second name change was made. On March 20, 1998 curl 4
was released. (The version numbering from the previous names was kept.)


(Unrelated to this project a company called Curl Corporation registered a US
trademark on the name "CURL" on May 18 1998. That company had then already
registered the curl.com domain back in November of the previous year. All this
was revealed to us much later.)

SSL support was added, powered by the SSLeay library.
Changes to jni/curl/docs/HTTP2.md.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
HTTP/2 with curl
================

[HTTP/2 Spec](https://www.rfc-editor.org/rfc/rfc7540.txt)
[http2 explained](https://daniel.haxx.se/http2/)

Build prerequisites
-------------------
  - nghttp2
  - OpenSSL, libressl, BoringSSL, NSS, GnutTLS, mbedTLS, wolfSSL or Schannel
    with a new enough version.

[nghttp2](https://nghttp2.org/)
-------------------------------

libcurl uses this 3rd party library for the low level protocol handling
parts. The reason for this is that HTTP/2 is much more complex at that layer









|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
HTTP/2 with curl
================

[HTTP/2 Spec](https://www.rfc-editor.org/rfc/rfc7540.txt)
[http2 explained](https://daniel.haxx.se/http2/)

Build prerequisites
-------------------
  - nghttp2
  - OpenSSL, libressl, BoringSSL, NSS, GnuTLS, mbedTLS, wolfSSL or Schannel
    with a new enough version.

[nghttp2](https://nghttp2.org/)
-------------------------------

libcurl uses this 3rd party library for the low level protocol handling
parts. The reason for this is that HTTP/2 is much more complex at that layer
Changes to jni/curl/docs/HTTP3.md.
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126

## build

Build quiche and BoringSSL:

     % git clone --recursive https://github.com/cloudflare/quiche
     % cd quiche
     % cargo build --release --features pkg-config-meta,qlog
     % mkdir deps/boringssl/src/lib
     % ln -vnf $(find target/release -name libcrypto.a -o -name libssl.a) deps/boringssl/src/lib/

Build curl:

     % cd ..
     % git clone https://github.com/curl/curl







|







112
113
114
115
116
117
118
119
120
121
122
123
124
125
126

## build

Build quiche and BoringSSL:

     % git clone --recursive https://github.com/cloudflare/quiche
     % cd quiche
     % cargo build --release --features ffi,pkg-config-meta,qlog
     % mkdir deps/boringssl/src/lib
     % ln -vnf $(find target/release -name libcrypto.a -o -name libssl.a) deps/boringssl/src/lib/

Build curl:

     % cd ..
     % git clone https://github.com/curl/curl
Added jni/curl/docs/HYPER.md.
































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
# Hyper

Hyper is a separate HTTP library written in Rust. curl can be told to use this
library as a backend to deal with HTTP.

## Experimental!

Hyper support in curl is considered **EXPERIMENTAL** until further notice. It
needs to be explicitly enabled at build-time.

Further development and tweaking of the Hyper backend support in curl will
happen in in the master branch using pull-requests, just like ordinary
changes.

## Hyper version

The C API for Hyper is brand new and under development. This description
assumes that you get and build that C API off [the branch in Hyper's git
repository](https://github.com/hyperium/hyper/tree/hyper-capi).

## build curl with hyper

Build hyper and enable the C API:

     % git clone https://github.com/hyperium/hyper
     % cd hyper
     % RUSTFLAGS="--cfg hyper_unstable_ffi" cargo build --features client,http1,http2,ffi

Build curl to use hyper's C API:

     % git clone https://github.com/curl/curl
     % cd curl
     % ./buildconf
     % ./configure --with-hyper=<hyper dir>
     % make

# using Hyper internally

Hyper is a low level HTTP transport library. curl itself provides all HTTP
headers and Hyper provides all received headers back to curl.

Therefore, most of the "header logic" in curl as in responding to and acting
on specific input and output headers are done the same way in curl code.

The API in Hyper delivers received HTTP headers as (cleaned up) name=value
pairs, making it impossible for curl to know the exact byte representation
over the wire with Hyper.

## Remaining issues

This backend is still not feature complete with the native backend. Areas that
still need attention and verification include:

- multiplexed HTTP/2
- h2 Upgrade:
- pausing transfers
- co-exist with a HTTP/3 build
- receiving HTTP/1 trailers
- sending HTTP/1 trailers
- accept-encoding
- transfer encoding
- alt-svc
- hsts
- DoH ([#6389](https://github.com/curl/curl/issues/6389))
Changes to jni/curl/docs/INSTALL.md.
144
145
146
147
148
149
150

151

152
153
154
155
156
157
158
159
160
161
162
163
164
165
166

167
168
169

170
171
172
173
174

175
176

177
178
179

180

181
182
183
184
185
186
187

 If you get linkage errors read section 5.7 of the FAQ document.

## MingW32

Make sure that MinGW32's bin dir is in the search path, for example:


    set PATH=c:\mingw32\bin;%PATH%


then run `mingw32-make mingw32` in the root dir. There are other
make targets available to build libcurl with more features, use:

 - `mingw32-make mingw32-zlib` to build with Zlib support;
 - `mingw32-make mingw32-ssl-zlib` to build with SSL and Zlib enabled;
 - `mingw32-make mingw32-ssh2-ssl-zlib` to build with SSH2, SSL, Zlib;
 - `mingw32-make mingw32-ssh2-ssl-sspi-zlib` to build with SSH2, SSL, Zlib
   and SSPI support.

If you have any problems linking libraries or finding header files, be sure
to verify that the provided `Makefile.m32` files use the proper paths, and
adjust as necessary. It is also possible to override these paths with
environment variables, for example:


    set ZLIB_PATH=c:\zlib-1.2.8
    set OPENSSL_PATH=c:\openssl-1.0.2c
    set LIBSSH2_PATH=c:\libssh2-1.6.0


It is also possible to build with other LDAP SDKs than MS LDAP; currently
it is possible to build with native Win32 OpenLDAP, or with the Novell CLDAP
SDK. If you want to use these you need to set these vars:


    set LDAP_SDK=c:\openldap
    set USE_LDAP_OPENLDAP=1


or for using the Novell SDK:


    set USE_LDAP_NOVELL=1


If you want to enable LDAPS support then set LDAPS=1.

## Cygwin

Almost identical to the unix installation. Run the configure script in the
curl source tree root with `sh configure`. Make sure you have the `sh`







>
|
>















>
|
|
|
>





>
|
|
>



>
|
>







144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195

 If you get linkage errors read section 5.7 of the FAQ document.

## MingW32

Make sure that MinGW32's bin dir is in the search path, for example:

```cmd
set PATH=c:\mingw32\bin;%PATH%
```

then run `mingw32-make mingw32` in the root dir. There are other
make targets available to build libcurl with more features, use:

 - `mingw32-make mingw32-zlib` to build with Zlib support;
 - `mingw32-make mingw32-ssl-zlib` to build with SSL and Zlib enabled;
 - `mingw32-make mingw32-ssh2-ssl-zlib` to build with SSH2, SSL, Zlib;
 - `mingw32-make mingw32-ssh2-ssl-sspi-zlib` to build with SSH2, SSL, Zlib
   and SSPI support.

If you have any problems linking libraries or finding header files, be sure
to verify that the provided `Makefile.m32` files use the proper paths, and
adjust as necessary. It is also possible to override these paths with
environment variables, for example:

```cmd
set ZLIB_PATH=c:\zlib-1.2.8
set OPENSSL_PATH=c:\openssl-1.0.2c
set LIBSSH2_PATH=c:\libssh2-1.6.0
```

It is also possible to build with other LDAP SDKs than MS LDAP; currently
it is possible to build with native Win32 OpenLDAP, or with the Novell CLDAP
SDK. If you want to use these you need to set these vars:

```cmd
set LDAP_SDK=c:\openldap
set USE_LDAP_OPENLDAP=1
```

or for using the Novell SDK:

```cmd
set USE_LDAP_NOVELL=1
```

If you want to enable LDAPS support then set LDAPS=1.

## Cygwin

Almost identical to the unix installation. Run the configure script in the
curl source tree root with `sh configure`. Make sure you have the `sh`
276
277
278
279
280
281
282

283
284
285

286
287
288
289
290
291
292
293
294
295
296
297

298
299
300
301
302
303
304
305
306
307

308
309
310
311
312
313
314
you set the `MACOSX_DEPLOYMENT_TARGET` environmental variable to an earlier
version of macOS prior to building curl, then curl will use the new Secure
Transport API on Mountain Lion and later, and fall back on the older API when
the same curl binary is executed on older cats. For example, running these
commands in curl's directory in the shell will build the code such that it
will run on cats as old as OS X 10.6 ("Snow Leopard") (using bash):


    export MACOSX_DEPLOYMENT_TARGET="10.6"
    ./configure --with-secure-transport
    make


# Android

When building curl for Android it's recommended to use a Linux environment
since using curl's `configure` script is the easiest way to build curl
for Android. Before you can build curl for Android, you need to install the
Android NDK first. This can be done using the SDK Manager that is part of
Android Studio. Once you have installed the Android NDK, you need to figure out
where it has been installed and then set up some environment variables before
launching `configure`. On macOS, those variables could look like this to compile
for `aarch64` and API level 29:


    export NDK=~/Library/Android/sdk/ndk/20.1.5948944
    export HOST_TAG=darwin-x86_64
    export TOOLCHAIN=$NDK/toolchains/llvm/prebuilt/$HOST_TAG
    export AR=$TOOLCHAIN/bin/aarch64-linux-android-ar
    export AS=$TOOLCHAIN/bin/aarch64-linux-android-as
    export CC=$TOOLCHAIN/bin/aarch64-linux-android29-clang
    export CXX=$TOOLCHAIN/bin/aarch64-linux-android29-clang++
    export LD=$TOOLCHAIN/bin/aarch64-linux-android-ld
    export RANLIB=$TOOLCHAIN/bin/aarch64-linux-android-ranlib
    export STRIP=$TOOLCHAIN/bin/aarch64-linux-android-strip


When building on Linux or targeting other API levels or architectures, you need
to adjust those variables accordingly. After that you can build curl like this:

    ./configure --host aarch64-linux-android --with-pic --disable-shared

Note that this won't give you SSL/TLS support. If you need SSL/TLS, you have







>
|
|
|
>












>
|
|
|
|
|
|
|
|
|
|
>







284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
you set the `MACOSX_DEPLOYMENT_TARGET` environmental variable to an earlier
version of macOS prior to building curl, then curl will use the new Secure
Transport API on Mountain Lion and later, and fall back on the older API when
the same curl binary is executed on older cats. For example, running these
commands in curl's directory in the shell will build the code such that it
will run on cats as old as OS X 10.6 ("Snow Leopard") (using bash):

```bash
export MACOSX_DEPLOYMENT_TARGET="10.6"
./configure --with-secure-transport
make
```

# Android

When building curl for Android it's recommended to use a Linux environment
since using curl's `configure` script is the easiest way to build curl
for Android. Before you can build curl for Android, you need to install the
Android NDK first. This can be done using the SDK Manager that is part of
Android Studio. Once you have installed the Android NDK, you need to figure out
where it has been installed and then set up some environment variables before
launching `configure`. On macOS, those variables could look like this to compile
for `aarch64` and API level 29:

```bash
export NDK=~/Library/Android/sdk/ndk/20.1.5948944
export HOST_TAG=darwin-x86_64
export TOOLCHAIN=$NDK/toolchains/llvm/prebuilt/$HOST_TAG
export AR=$TOOLCHAIN/bin/aarch64-linux-android-ar
export AS=$TOOLCHAIN/bin/aarch64-linux-android-as
export CC=$TOOLCHAIN/bin/aarch64-linux-android29-clang
export CXX=$TOOLCHAIN/bin/aarch64-linux-android29-clang++
export LD=$TOOLCHAIN/bin/aarch64-linux-android-ld
export RANLIB=$TOOLCHAIN/bin/aarch64-linux-android-ranlib
export STRIP=$TOOLCHAIN/bin/aarch64-linux-android-strip
```

When building on Linux or targeting other API levels or architectures, you need
to adjust those variables accordingly. After that you can build curl like this:

    ./configure --host aarch64-linux-android --with-pic --disable-shared

Note that this won't give you SSL/TLS support. If you need SSL/TLS, you have
333
334
335
336
337
338
339

340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355

356
357
358
359
360
361
362

Set environment variables to point to the cross-compile toolchain and call
configure with any options you need.  Be sure and specify the `--host` and
`--build` parameters at configuration time.  The following script is an
example of cross-compiling for the IBM 405GP PowerPC processor using the
toolchain from MonteVista for Hardhat Linux.


    #! /bin/sh

    export PATH=$PATH:/opt/hardhat/devkit/ppc/405/bin
    export CPPFLAGS="-I/opt/hardhat/devkit/ppc/405/target/usr/include"
    export AR=ppc_405-ar
    export AS=ppc_405-as
    export LD=ppc_405-ld
    export RANLIB=ppc_405-ranlib
    export CC=ppc_405-gcc
    export NM=ppc_405-nm

    ./configure --target=powerpc-hardhat-linux
        --host=powerpc-hardhat-linux
        --build=i586-pc-linux-gnu
        --prefix=/opt/hardhat/devkit/ppc/405/target/usr/local
        --exec-prefix=/usr/local


You may also need to provide a parameter like `--with-random=/dev/urandom` to
configure as it cannot detect the presence of a random number generating
device for a target system.  The `--prefix` parameter specifies where curl
will be installed.  If `configure` completes successfully, do `make` and `make
install` as usual.








>
|

|
|
|
|
|
|
|
|

|
|
|
|
|
>







345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376

Set environment variables to point to the cross-compile toolchain and call
configure with any options you need.  Be sure and specify the `--host` and
`--build` parameters at configuration time.  The following script is an
example of cross-compiling for the IBM 405GP PowerPC processor using the
toolchain from MonteVista for Hardhat Linux.

```bash
#! /bin/sh

export PATH=$PATH:/opt/hardhat/devkit/ppc/405/bin
export CPPFLAGS="-I/opt/hardhat/devkit/ppc/405/target/usr/include"
export AR=ppc_405-ar
export AS=ppc_405-as
export LD=ppc_405-ld
export RANLIB=ppc_405-ranlib
export CC=ppc_405-gcc
export NM=ppc_405-nm

./configure --target=powerpc-hardhat-linux
    --host=powerpc-hardhat-linux
    --build=i586-pc-linux-gnu
    --prefix=/opt/hardhat/devkit/ppc/405/target/usr/local
    --exec-prefix=/usr/local
```

You may also need to provide a parameter like `--with-random=/dev/urandom` to
configure as it cannot detect the presence of a random number generating
device for a target system.  The `--prefix` parameter specifies where curl
will be installed.  If `configure` completes successfully, do `make` and `make
install` as usual.

429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492

493




494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509

 - `--disable-cookies`          !cookies
 - `--disable-manual`           !--manual
 - `--disable-proxy`            !HTTP\ proxy !proxytunnel !SOCKS4 !SOCKS5

# PORTS

This is a probably incomplete list of known hardware and operating systems
that curl has been compiled for. If you know a system curl compiles and
runs on, that isn't listed, please let us know!

  - Alpha DEC OSF 4
  - Alpha Digital UNIX v3.2
  - Alpha FreeBSD 4.1, 4.5
  - Alpha Linux 2.2, 2.4
  - Alpha NetBSD 1.5.2
  - Alpha OpenBSD 3.0
  - Alpha OpenVMS V7.1-1H2
  - Alpha Tru64 v5.0 5.1
  - AVR32 Linux
  - ARM Android 1.5, 2.1, 2.3, 3.2, 4.x
  - ARM INTEGRITY
  - ARM iOS
  - Cell Linux
  - Cell Cell OS
  - HP-PA HP-UX 9.X 10.X 11.X
  - HP-PA Linux
  - HP3000 MPE/iX
  - MicroBlaze uClinux
  - MIPS IRIX 6.2, 6.5
  - MIPS Linux
  - OS/400
  - Pocket PC/Win CE 3.0
  - Power AIX 3.2.5, 4.2, 4.3.1, 4.3.2, 5.1, 5.2
  - PowerPC Darwin 1.0
  - PowerPC INTEGRITY
  - PowerPC Linux
  - PowerPC Mac OS 9
  - PowerPC Mac OS X
  - SH4 Linux 2.6.X
  - SH4 OS21
  - SINIX-Z v5
  - Sparc Linux
  - Sparc Solaris 2.4, 2.5, 2.5.1, 2.6, 7, 8, 9, 10
  - Sparc SunOS 4.1.X
  - StrongARM (and other ARM) RISC OS 3.1, 4.02
  - StrongARM/ARM7/ARM9 Linux 2.4, 2.6
  - StrongARM NetBSD 1.4.1
  - Symbian OS (P.I.P.S.) 9.x
  - TPF
  - Ultrix 4.3a
  - UNICOS 9.0
  - i386 BeOS
  - i386 DOS
  - i386 eCos 1.3.1
  - i386 Esix 4.1
  - i386 FreeBSD
  - i386 HURD
  - i386 Haiku OS
  - i386 Linux 1.3, 2.0, 2.2, 2.3, 2.4, 2.6
  - i386 Mac OS X
  - i386 MINIX 3.1
  - i386 NetBSD
  - i386 Novell NetWare

  - i386 OS/2




  - i386 OpenBSD
  - i386 QNX 6
  - i386 SCO unix
  - i386 Solaris 2.7
  - i386 Windows 95, 98, ME, NT, 2000, XP, 2003
  - i486 ncr-sysv4.3.03 (NCR MP-RAS)
  - ia64 Linux 2.3.99
  - m68k AmigaOS 3
  - m68k Linux
  - m68k uClinux
  - m68k OpenBSD
  - m88k dg-dgux5.4R3.00
  - s390 Linux
  - x86_64 Linux
  - XScale/PXA250 Linux 2.4
  - Nios II uClinux







|
|
|

<
<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
<
<
<
<
<
<
<
|
<
<
<
|
<
|
<
|
|
<
<
>
|
>
>
>
>
|
<
<
|
|
<
<
<
|
<
<
<
|
<
<
<
443
444
445
446
447
448
449
450
451
452
453





454



























455







456



457

458

459
460


461
462
463
464
465
466
467


468
469



470



471




 - `--disable-cookies`          !cookies
 - `--disable-manual`           !--manual
 - `--disable-proxy`            !HTTP\ proxy !proxytunnel !SOCKS4 !SOCKS5

# PORTS

This is a probably incomplete list of known CPU architectures and operating
systems that curl has been compiled for. If you know a system curl compiles
and runs on, that isn't listed, please let us know!






## 85 Operating Systems



































AIX, AmigaOS, Android, Aros, BeOS, Blackberry 10, Blackberry Tablet OS, Cell



OS, ChromeOS, Cisco IOS, Cygwin, Dragonfly BSD, eCOS, FreeBSD, FreeDOS,

FreeRTOS, Fuchsia, Garmin OS, Genode, Haiku, HardenedBSD, HP-UX, Hurd,

Illumos, Integrity, iOS, ipadOS, IRIX, LineageOS, Linux, Lua RTOS, Mac OS 9,
macOS, Mbed, Micrium, MINIX, MorphOS, MPE/iX, MS-DOS, NCR MP-RAS, NetBSD,


Netware, Nintendo Switch, NonStop OS, NuttX, OpenBSD, OpenStep, Orbis OS,
OS/2, OS/400, OS21, Plan 9, PlayStation Portable, QNX, Qubes OS, ReactOS,
Redox, RICS OS, Sailfish OS, SCO Unix, Serenity, SINIX-Z, Solaris, SunOS,
Syllable OS, Symbian, Tizen, TPF, Tru64, tvOS, ucLinux, Ultrix, UNICOS,
UnixWare, VMS, vxWorks, WebOS, Wii system software, Windows, Windows CE, Xbox
System, z/OS, z/TPF, z/VM, z/VSE



## 22 CPU Architectures




Alpha, ARC, ARM, AVR32, Cell, HP-PA, Itanium, m68k, MicroBlaze, MIPS, Nios,



OpenRISC, POWER, PowerPC, RISC-V, s390, SH4, SPARC, VAX, x86, x86-64, Xtensa



Changes to jni/curl/docs/INTERNALS.md.
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
   the same in all places except for the header file that defines them. The
   macros in use are `sclose()`, `sread()` and `swrite()`.

 2. Windows requires a couple of init calls for the socket stuff.

   That's taken care of by the `curl_global_init()` call, but if other libs
   also do it etc there might be reasons for applications to alter that
   behaviour.

   We require WinSock version 2.2 and load this version during global init.

 3. The file descriptors for network communication and file operations are
    not as easily interchangeable as in Unix.

   We avoid this by not trying any funny tricks on file descriptors.







|







141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
   the same in all places except for the header file that defines them. The
   macros in use are `sclose()`, `sread()` and `swrite()`.

 2. Windows requires a couple of init calls for the socket stuff.

   That's taken care of by the `curl_global_init()` call, but if other libs
   also do it etc there might be reasons for applications to alter that
   behavior.

   We require WinSock version 2.2 and load this version during global init.

 3. The file descriptors for network communication and file operations are
    not as easily interchangeable as in Unix.

   We avoid this by not trying any funny tricks on file descriptors.
180
181
182
183
184
185
186
187
188

189
190
191
192
193
194
195
 There are plenty of entry points to the library, namely each publicly defined
 function that libcurl offers to applications. All of those functions are
 rather small and easy-to-follow. All the ones prefixed with `curl_easy` are
 put in the `lib/easy.c` file.

 `curl_global_init()` and `curl_global_cleanup()` should be called by the
 application to initialize and clean up global stuff in the library. As of
 today, it can handle the global SSL initing if SSL is enabled and it can init
 the socket layer on windows machines. libcurl itself has no "global" scope.


 All printf()-style functions use the supplied clones in `lib/mprintf.c`. This
 makes sure we stay absolutely platform independent.

 [ `curl_easy_init()`][2] allocates an internal struct and makes some
 initializations.  The returned handle does not reveal internals. This is the
 `Curl_easy` struct which works as an "anchor" struct for all `curl_easy`







|
|
>







180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
 There are plenty of entry points to the library, namely each publicly defined
 function that libcurl offers to applications. All of those functions are
 rather small and easy-to-follow. All the ones prefixed with `curl_easy` are
 put in the `lib/easy.c` file.

 `curl_global_init()` and `curl_global_cleanup()` should be called by the
 application to initialize and clean up global stuff in the library. As of
 today, it can handle the global SSL initialization if SSL is enabled and it
 can initialize the socket layer on Windows machines. libcurl itself has no
 "global" scope.

 All printf()-style functions use the supplied clones in `lib/mprintf.c`. This
 makes sure we stay absolutely platform independent.

 [ `curl_easy_init()`][2] allocates an internal struct and makes some
 initializations.  The returned handle does not reveal internals. This is the
 `Curl_easy` struct which works as an "anchor" struct for all `curl_easy`
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
   When `Curl_connect` is done, we are connected to the remote site. Then it
   is time to tell the server to get a document/file. `Curl_do()` arranges
   this.

   This function makes sure there's an allocated and initiated `connectdata`
   struct that is used for this particular connection only (although there may
   be several requests performed on the same connect). A bunch of things are
   inited/inherited from the `Curl_easy` struct.

<a name="multi_do"></a>
multi_do()
---------

   `multi_do()` makes sure the proper protocol-specific function is called.
   The functions are named after the protocols they handle.







|







223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
   When `Curl_connect` is done, we are connected to the remote site. Then it
   is time to tell the server to get a document/file. `Curl_do()` arranges
   this.

   This function makes sure there's an allocated and initiated `connectdata`
   struct that is used for this particular connection only (although there may
   be several requests performed on the same connect). A bunch of things are
   initialized/inherited from the `Curl_easy` struct.

<a name="multi_do"></a>
multi_do()
---------

   `multi_do()` makes sure the proper protocol-specific function is called.
   The functions are named after the protocols they handle.
769
770
771
772
773
774
775

776

777
778
779
780
781
782
783

  This will create a library that has memory debugging enabled.

## Modify Your Application

  Add a line in your application code:


       `curl_dbg_memdebug("dump");`


  This will make the malloc debug system output a full trace of all resource
  using functions to the given file name. Make sure you rebuild your program
  and that you link with the same libcurl you built for this purpose as
  described above.

## Run Your Application







>
|
>







770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786

  This will create a library that has memory debugging enabled.

## Modify Your Application

  Add a line in your application code:

```c
  curl_dbg_memdebug("dump");
```

  This will make the malloc debug system output a full trace of all resource
  using functions to the given file name. Make sure you rebuild your program
  and that you link with the same libcurl you built for this purpose as
  described above.

## Run Your Application
Changes to jni/curl/docs/KNOWN_BUGS.
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
 2.6 CURL_GLOBAL_SSL
 2.7 Client cert (MTLS) issues with Schannel
 2.8 Schannel disable CURLOPT_SSL_VERIFYPEER and verify hostname
 2.9 TLS session cache doesn't work with TFO
 2.10 Store TLS context per transfer instead of per connection
 2.11 Schannel TLS 1.2 handshake bug in old Windows versions
 2.12 FTPS with Schannel times out file list operation
 2.13 curl with wolfSSL lacks support for renegotiation

 3. Email protocols
 3.1 IMAP SEARCH ALL truncated response
 3.2 No disconnect command
 3.3 POP3 expects "CRLF.CRLF" eob for some single-line responses
 3.4 AUTH PLAIN for SMTP is not working on all servers








|







31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
 2.6 CURL_GLOBAL_SSL
 2.7 Client cert (MTLS) issues with Schannel
 2.8 Schannel disable CURLOPT_SSL_VERIFYPEER and verify hostname
 2.9 TLS session cache doesn't work with TFO
 2.10 Store TLS context per transfer instead of per connection
 2.11 Schannel TLS 1.2 handshake bug in old Windows versions
 2.12 FTPS with Schannel times out file list operation
 2.14 Secure Transport disabling hostname validation also disables SNI

 3. Email protocols
 3.1 IMAP SEARCH ALL truncated response
 3.2 No disconnect command
 3.3 POP3 expects "CRLF.CRLF" eob for some single-line responses
 3.4 AUTH PLAIN for SMTP is not working on all servers

66
67
68
69
70
71
72


73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92

93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111

112
113
114
115
116
117
118
 6.2 MIT Kerberos for Windows build
 6.3 NTLM in system context uses wrong name
 6.4 Negotiate and Kerberos V5 need a fake user name
 6.5 NTLM doesn't support password with § character
 6.6 libcurl can fail to try alternatives with --proxy-any
 6.7 Don't clear digest for single realm
 6.8 RTSP authentication breaks without redirect support



 7. FTP
 7.1 FTP without or slow 220 response
 7.2 FTP with CONNECT and slow server
 7.3 FTP with NOBODY and FAILONERROR
 7.4 FTP with ACCT
 7.5 ASCII FTP
 7.6 FTP with NULs in URL parts
 7.7 FTP and empty path parts in the URL
 7.8 Premature transfer end but healthy control channel
 7.9 Passive transfer tries only one IP address
 7.10 FTPS needs session reuse

 8. TELNET
 8.1 TELNET and time limitations don't work
 8.2 Microsoft telnet server

 9. SFTP and SCP
 9.1 SFTP doesn't do CURLOPT_POSTQUOTE correct
 9.2 wolfssh: publickey auth doesn't work


 10. SOCKS
 10.3 FTPS over SOCKS
 10.4 active FTP over a SOCKS

 11. Internals
 11.1 Curl leaks .onion hostnames in DNS
 11.2 error buffer not set if connection to multiple addresses fails
 11.3 c-ares deviates from stock resolver on http://1346569778
 11.4 HTTP test server 'connection-monitor' problems
 11.5 Connection information when using TCP Fast Open
 11.6 slow connect to localhost on Windows
 11.7 signal-based resolver timeouts
 11.8 DoH leaks memory after followlocation
 11.9 DoH doesn't inherit all transfer options
 11.10 Blocking socket operations in non-blocking API
 11.11 A shared connection cache is not thread-safe
 11.12 'no_proxy' string-matches IPv6 numerical addresses
 11.13 wakeup socket disconnect causes havoc


 12. LDAP
 12.1 OpenLDAP hangs after returning results
 12.2 LDAP on Windows does authentication wrong?
 12.3 LDAP on Windows doesn't work
 12.4 LDAPS with NSS is slow








>
>




















>



















>







66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
 6.2 MIT Kerberos for Windows build
 6.3 NTLM in system context uses wrong name
 6.4 Negotiate and Kerberos V5 need a fake user name
 6.5 NTLM doesn't support password with § character
 6.6 libcurl can fail to try alternatives with --proxy-any
 6.7 Don't clear digest for single realm
 6.8 RTSP authentication breaks without redirect support
 6.9 SHA-256 digest not supported in Windows SSPI builds
 6.10 curl never completes Negotiate over HTTP

 7. FTP
 7.1 FTP without or slow 220 response
 7.2 FTP with CONNECT and slow server
 7.3 FTP with NOBODY and FAILONERROR
 7.4 FTP with ACCT
 7.5 ASCII FTP
 7.6 FTP with NULs in URL parts
 7.7 FTP and empty path parts in the URL
 7.8 Premature transfer end but healthy control channel
 7.9 Passive transfer tries only one IP address
 7.10 FTPS needs session reuse

 8. TELNET
 8.1 TELNET and time limitations don't work
 8.2 Microsoft telnet server

 9. SFTP and SCP
 9.1 SFTP doesn't do CURLOPT_POSTQUOTE correct
 9.2 wolfssh: publickey auth doesn't work
 9.3 Remote recursive folder creation with SFTP

 10. SOCKS
 10.3 FTPS over SOCKS
 10.4 active FTP over a SOCKS

 11. Internals
 11.1 Curl leaks .onion hostnames in DNS
 11.2 error buffer not set if connection to multiple addresses fails
 11.3 c-ares deviates from stock resolver on http://1346569778
 11.4 HTTP test server 'connection-monitor' problems
 11.5 Connection information when using TCP Fast Open
 11.6 slow connect to localhost on Windows
 11.7 signal-based resolver timeouts
 11.8 DoH leaks memory after followlocation
 11.9 DoH doesn't inherit all transfer options
 11.10 Blocking socket operations in non-blocking API
 11.11 A shared connection cache is not thread-safe
 11.12 'no_proxy' string-matches IPv6 numerical addresses
 11.13 wakeup socket disconnect causes havoc
 11.14 Multi perform hangs waiting for threaded resolver

 12. LDAP
 12.1 OpenLDAP hangs after returning results
 12.2 LDAP on Windows does authentication wrong?
 12.3 LDAP on Windows doesn't work
 12.4 LDAPS with NSS is slow

129
130
131
132
133
134
135




136
137
138
139
140
141
142
 15.4 build docs/curl.1
 15.5 build on Linux links libcurl to libdl
 15.6 uses -lpthread instead of Threads::Threads
 15.7 generated .pc file contains strange entries
 15.8 libcurl.pc uses absolute library paths
 15.9 cert paths autodetected when cross-compiling
 15.10 libspsl is not supported





==============================================================================

1. HTTP

1.2 Multiple methods in a single WWW-Authenticate: header








>
>
>
>







133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
 15.4 build docs/curl.1
 15.5 build on Linux links libcurl to libdl
 15.6 uses -lpthread instead of Threads::Threads
 15.7 generated .pc file contains strange entries
 15.8 libcurl.pc uses absolute library paths
 15.9 cert paths autodetected when cross-compiling
 15.10 libspsl is not supported
 15.11 ExternalProject_Add does not set CURL_CA_PATH

 16. Applications
 16.1 pulseUI VPN client

==============================================================================

1. HTTP

1.2 Multiple methods in a single WWW-Authenticate: header

309
310
311
312
313
314
315
316
317





318
319
320

321
322
323
324
325
326
327
328
329

2.12 FTPS with Schannel times out file list operation

 "Instead of the command completing, it just sits there until the timeout
 expires." - the same command line seems to work with other TLS backends and
 other operating systems. See https://github.com/curl/curl/issues/5284.

2.13 curl with wolfSSL lacks support for renegotiation






 I am using curl (with wolfSSL) to connect https endpoint, but connection with
 this https endpoint gets terminated because server initiates the
 renegotiation and client does not handle renegotiation.


 See https://github.com/curl/curl/issues/5839

3. Email protocols

3.1 IMAP SEARCH ALL truncated response

 IMAP "SEARCH ALL" truncates output on large boxes. "A quick search of the
 code reveals that pingpong.c contains some truncation code, at line 408, when







|

>
>
>
>
>
|
|
|
>

|







317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343

2.12 FTPS with Schannel times out file list operation

 "Instead of the command completing, it just sits there until the timeout
 expires." - the same command line seems to work with other TLS backends and
 other operating systems. See https://github.com/curl/curl/issues/5284.

2.14 Secure Transport disabling hostname validation also disables SNI

 SNI is the hostname that is sent by the TLS library to the server as part of
 the TLS handshake. Secure Transport does not send SNI when hostname validation
 is disabled. Servers that host multiple websites may not know which
 certificate to serve without SNI or which backend server to connect to. The
 server may serve the certificate of a default server or abort.

 If a server aborts a handshake then curl shows error "SSL peer handshake
 failed, the server most likely requires a client certificate to connect".
 In this case the error may also have been caused by lack of SNI.

 https://github.com/curl/curl/issues/6347

3. Email protocols

3.1 IMAP SEARCH ALL truncated response

 IMAP "SEARCH ALL" truncates output on large boxes. "A quick search of the
 code reveals that pingpong.c contains some truncation code, at line 408, when
554
555
556
557
558
559
560

















561
562
563
564
565
566
567
 RTSP authentication broke in 7.66.0. A work-around is to enable RTSP in
 CURLOPT_REDIR_PROTOCOLS. Authentication should however not be considered an
 actual redirect so a "proper" fix needs to be different and not require users
 to allow redirects to RTSP to work.

 See https://github.com/curl/curl/pull/4750


















7. FTP

7.1 FTP without or slow 220 response

 If a connection is made to a FTP server but the server then just never sends
 the 220 response or otherwise is dead slow, libcurl will not acknowledge the
 connection timeout during that phase but only the "real" timeout - which may







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
 RTSP authentication broke in 7.66.0. A work-around is to enable RTSP in
 CURLOPT_REDIR_PROTOCOLS. Authentication should however not be considered an
 actual redirect so a "proper" fix needs to be different and not require users
 to allow redirects to RTSP to work.

 See https://github.com/curl/curl/pull/4750

6.9 SHA-256 digest not supported in Windows SSPI builds

 Windows builds of curl that have SSPI enabled use the native Windows API calls
 to create authentication strings. The call to InitializeSecurityContext fails
 with SEC_E_QOP_NOT_SUPPORTED which causes curl to fail with CURLE_AUTH_ERROR.

 Microsoft does not document supported digest algorithms and that SEC_E error
 code is not a documented error for InitializeSecurityContext (digest).

 https://github.com/curl/curl/issues/6302

6.10 curl never completes Negotiate over HTTP

 Apparently it isn't working correctly...?

 See https://github.com/curl/curl/issues/5235

7. FTP

7.1 FTP without or slow 220 response

 If a connection is made to a FTP server but the server then just never sends
 the 220 response or otherwise is dead slow, libcurl will not acknowledge the
 connection timeout during that phase but only the "real" timeout - which may
682
683
684
685
686
687
688








689
690
691
692
693
694
695
9.2 wolfssh: publickey auth doesn't work

 When building curl to use the wolfSSH backend for SFTP, the publickey
 authentication doesn't work. This is simply functionality not written for curl
 yet, the necessary API for make this work is provided by wolfSSH.

 See https://github.com/curl/curl/issues/4820









10. SOCKS

10.3 FTPS over SOCKS

 libcurl doesn't support FTPS over a SOCKS proxy.








>
>
>
>
>
>
>
>







713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
9.2 wolfssh: publickey auth doesn't work

 When building curl to use the wolfSSH backend for SFTP, the publickey
 authentication doesn't work. This is simply functionality not written for curl
 yet, the necessary API for make this work is provided by wolfSSH.

 See https://github.com/curl/curl/issues/4820

9.3 Remote recursive folder creation with SFTP

 On this servers, the curl fails to create directories on the remote server
 even when CURLOPT_FTP_CREATE_MISSING_DIRS option is set.

 See https://github.com/curl/curl/issues/5204


10. SOCKS

10.3 FTPS over SOCKS

 libcurl doesn't support FTPS over a SOCKS proxy.

803
804
805
806
807
808
809









810
811
812
813
814
815
816
 This condition, and other possible error conditions on the wakeup socket, are
 not handled, so the condition remains on the FD and curl_multi_poll will
 never block again.

 See https://github.com/curl/curl/issues/6132 and
 https://github.com/curl/curl/pull/6133










12. LDAP

12.1 OpenLDAP hangs after returning results

 By configuration defaults, openldap automatically chase referrals on
 secondary socket descriptors. The OpenLDAP backend is asynchronous and thus
 should monitor all socket descriptors involved. Currently, these secondary







>
>
>
>
>
>
>
>
>







842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
 This condition, and other possible error conditions on the wakeup socket, are
 not handled, so the condition remains on the FD and curl_multi_poll will
 never block again.

 See https://github.com/curl/curl/issues/6132 and
 https://github.com/curl/curl/pull/6133

11.14 Multi perform hangs waiting for threaded resolver

 If a threaded resolver takes a long time to complete, libcurl can be blocked
 waiting for it for a longer time than expected - and longer than the set
 timeouts.

 See https://github.com/curl/curl/issues/2975 and
 https://github.com/curl/curl/issues/4852

12. LDAP

12.1 OpenLDAP hangs after returning results

 By configuration defaults, openldap automatically chase referrals on
 secondary socket descriptors. The OpenLDAP backend is asynchronous and thus
 should monitor all socket descriptors involved. Currently, these secondary
914
915
916
917
918
919
920






















 cross-compiling. The cmake build keeps doing the detection.

 See https://github.com/curl/curl/issues/6178

15.10 libspsl is not supported

 See https://github.com/curl/curl/issues/6214





























>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
 cross-compiling. The cmake build keeps doing the detection.

 See https://github.com/curl/curl/issues/6178

15.10 libspsl is not supported

 See https://github.com/curl/curl/issues/6214

15.11 ExternalProject_Add does not set CURL_CA_PATH

 CURL_CA_BUNDLE and CURL_CA_PATH are not set properly when cmake's
 ExternalProject_Add is used to build curl as a dependency.

 See https://github.com/curl/curl/issues/6313

16. Applications

16.1 pulseUI VPN client

 This application crashes at startup with libcurl 7.74.0 (and presumably later
 versions too) after we cleaned up OpenSSL initialization. Since this is the
 only known application to do this, we suspect it is related to something they
 are doing in their setup that isn't kosher. We have not been able to get in
 contact with them nor got any technical details to help us debug this
 further.

 See
 https://community.pulsesecure.net/t5/Pulse-Desktop-Clients/Linux-Pulse-Client-does-not-work-with-curl-7-74/m-p/44378
 and https://github.com/curl/curl/issues/6306
Changes to jni/curl/docs/Makefile.am.
63
64
65
66
67
68
69

70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88

89
90
91
92
93
94
95
 GOVERNANCE.md                                  \
 HELP-US.md                                     \
 HISTORY.md                                     \
 HSTS.md                                        \
 HTTP-COOKIES.md                                \
 HTTP2.md                                       \
 HTTP3.md                                       \

 INSTALL                                        \
 INSTALL.cmake                                  \
 INSTALL.md                                     \
 INTERNALS.md                                   \
 KNOWN_BUGS                                     \
 MAIL-ETIQUETTE                                 \
 MQTT.md                                        \
 NEW-PROTOCOL.md                                \
 options-in-versions                            \
 PARALLEL-TRANSFERS.md                          \
 README.md                                      \
 RELEASE-PROCEDURE.md                           \
 ROADMAP.md                                     \
 SECURITY-PROCESS.md                            \
 SSL-PROBLEMS.md                                \
 SSLCERTS.md                                    \
 THANKS                                         \
 TODO                                           \
 TheArtOfHttpScripting.md                       \

 VERSIONS.md

MAN2HTML= roffit $< >$@

SUFFIXES = .1 .html .pdf

# $(abs_builddir) is to disable VPATH when searching for this file, which







>



















>







63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
 GOVERNANCE.md                                  \
 HELP-US.md                                     \
 HISTORY.md                                     \
 HSTS.md                                        \
 HTTP-COOKIES.md                                \
 HTTP2.md                                       \
 HTTP3.md                                       \
 HYPER.md                                       \
 INSTALL                                        \
 INSTALL.cmake                                  \
 INSTALL.md                                     \
 INTERNALS.md                                   \
 KNOWN_BUGS                                     \
 MAIL-ETIQUETTE                                 \
 MQTT.md                                        \
 NEW-PROTOCOL.md                                \
 options-in-versions                            \
 PARALLEL-TRANSFERS.md                          \
 README.md                                      \
 RELEASE-PROCEDURE.md                           \
 ROADMAP.md                                     \
 SECURITY-PROCESS.md                            \
 SSL-PROBLEMS.md                                \
 SSLCERTS.md                                    \
 THANKS                                         \
 TODO                                           \
 TheArtOfHttpScripting.md                       \
 URL-SYNTAX.md                                  \
 VERSIONS.md

MAN2HTML= roffit $< >$@

SUFFIXES = .1 .html .pdf

# $(abs_builddir) is to disable VPATH when searching for this file, which
Changes to jni/curl/docs/Makefile.in.
377
378
379
380
381
382
383

384
385
386
387
388
389
390
STRIP = @STRIP@
SUPPORT_FEATURES = @SUPPORT_FEATURES@
SUPPORT_PROTOCOLS = @SUPPORT_PROTOCOLS@
USE_ARES = @USE_ARES@
USE_BEARSSL = @USE_BEARSSL@
USE_GNUTLS = @USE_GNUTLS@
USE_GNUTLS_NETTLE = @USE_GNUTLS_NETTLE@

USE_LIBRTMP = @USE_LIBRTMP@
USE_LIBSSH = @USE_LIBSSH@
USE_LIBSSH2 = @USE_LIBSSH2@
USE_MBEDTLS = @USE_MBEDTLS@
USE_MESALINK = @USE_MESALINK@
USE_NGHTTP2 = @USE_NGHTTP2@
USE_NGHTTP3 = @USE_NGHTTP3@







>







377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
STRIP = @STRIP@
SUPPORT_FEATURES = @SUPPORT_FEATURES@
SUPPORT_PROTOCOLS = @SUPPORT_PROTOCOLS@
USE_ARES = @USE_ARES@
USE_BEARSSL = @USE_BEARSSL@
USE_GNUTLS = @USE_GNUTLS@
USE_GNUTLS_NETTLE = @USE_GNUTLS_NETTLE@
USE_HYPER = @USE_HYPER@
USE_LIBRTMP = @USE_LIBRTMP@
USE_LIBSSH = @USE_LIBSSH@
USE_LIBSSH2 = @USE_LIBSSH2@
USE_MBEDTLS = @USE_MBEDTLS@
USE_MESALINK = @USE_MESALINK@
USE_NGHTTP2 = @USE_NGHTTP2@
USE_NGHTTP3 = @USE_NGHTTP3@
499
500
501
502
503
504
505

506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524

525
526
527
528
529
530
531
 GOVERNANCE.md                                  \
 HELP-US.md                                     \
 HISTORY.md                                     \
 HSTS.md                                        \
 HTTP-COOKIES.md                                \
 HTTP2.md                                       \
 HTTP3.md                                       \

 INSTALL                                        \
 INSTALL.cmake                                  \
 INSTALL.md                                     \
 INTERNALS.md                                   \
 KNOWN_BUGS                                     \
 MAIL-ETIQUETTE                                 \
 MQTT.md                                        \
 NEW-PROTOCOL.md                                \
 options-in-versions                            \
 PARALLEL-TRANSFERS.md                          \
 README.md                                      \
 RELEASE-PROCEDURE.md                           \
 ROADMAP.md                                     \
 SECURITY-PROCESS.md                            \
 SSL-PROBLEMS.md                                \
 SSLCERTS.md                                    \
 THANKS                                         \
 TODO                                           \
 TheArtOfHttpScripting.md                       \

 VERSIONS.md

MAN2HTML = roffit $< >$@
SUFFIXES = .1 .html .pdf
all: all-recursive

.SUFFIXES:







>



















>







500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
 GOVERNANCE.md                                  \
 HELP-US.md                                     \
 HISTORY.md                                     \
 HSTS.md                                        \
 HTTP-COOKIES.md                                \
 HTTP2.md                                       \
 HTTP3.md                                       \
 HYPER.md                                       \
 INSTALL                                        \
 INSTALL.cmake                                  \
 INSTALL.md                                     \
 INTERNALS.md                                   \
 KNOWN_BUGS                                     \
 MAIL-ETIQUETTE                                 \
 MQTT.md                                        \
 NEW-PROTOCOL.md                                \
 options-in-versions                            \
 PARALLEL-TRANSFERS.md                          \
 README.md                                      \
 RELEASE-PROCEDURE.md                           \
 ROADMAP.md                                     \
 SECURITY-PROCESS.md                            \
 SSL-PROBLEMS.md                                \
 SSLCERTS.md                                    \
 THANKS                                         \
 TODO                                           \
 TheArtOfHttpScripting.md                       \
 URL-SYNTAX.md                                  \
 VERSIONS.md

MAN2HTML = roffit $< >$@
SUFFIXES = .1 .html .pdf
all: all-recursive

.SUFFIXES:
Changes to jni/curl/docs/NEW-PROTOCOL.md.
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49

The protocol implementation is for a client's side of a "communication
session".

### Transfer oriented

The protocol itself should be focused on *transfers*. Be it uploads or
downloads or both. I should at least be possible to view the transfers as
such, like we can view reading emails over POP3 as a downloading and sending
emails over SMTP as an upload.

If you cannot even shoehorn the protocol into a transfer focused view, then
you are up for a tough argument.

### URL








|
|







34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49

The protocol implementation is for a client's side of a "communication
session".

### Transfer oriented

The protocol itself should be focused on *transfers*. Be it uploads or
downloads or both. It should at least be possible to view the transfers as
such, like we can view reading emails over POP3 as a download and sending
emails over SMTP as an upload.

If you cannot even shoehorn the protocol into a transfer focused view, then
you are up for a tough argument.

### URL

Changes to jni/curl/docs/ROADMAP.md.
1
2
3
4
5
6
7

8



9

10

11

12
13
14
15
16
17
18
19
curl the next few years - perhaps
=================================

Roadmap of things Daniel Stenberg wants to work on next. It is intended to
serve as a guideline for others for information, feedback and possible
participation.


HSTS



----



 Merge [the existing PR](https://github.com/curl/curl/pull/5896).


ECH (Encrypted Client Hello - formerly known as ESNI)
-----------------------------------------------------

 See Daniel's post on [Support of Encrypted
 SNI](https://curl.se/mail/lib-2019-03/0000.html) on the mailing list.

 Initial work exists in https://github.com/curl/curl/pull/4011
|
<





>
|
>
>
>
|
>

>
|
>

|
<





1

2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

20
21
22
23
24
# curl the next few years - perhaps


Roadmap of things Daniel Stenberg wants to work on next. It is intended to
serve as a guideline for others for information, feedback and possible
participation.

## "Complete" the HTTP/3 support

curl has experimental support for HTTP/3 since a good while back. There are
some functionality missing and once the final specs are published we want to
eventually remove the "experimental" label from this functionality.

## HTTPS DNS records

As a DNS version of alt-svc and also a pre-requisite for ECH (see below).

See: https://tools.ietf.org/html/draft-ietf-dnsop-svcb-https-02

## ECH (Encrypted Client Hello - formerly known as ESNI)


 See Daniel's post on [Support of Encrypted
 SNI](https://curl.se/mail/lib-2019-03/0000.html) on the mailing list.

 Initial work exists in https://github.com/curl/curl/pull/4011
Changes to jni/curl/docs/THANKS.
1
2
3
4
5
6

7
8
9
10
11
12
13
 This project has been alive for many years. Countless people have provided
 feedback that have improved curl. Here follows a list of people that have
 contributed (a-z order).

 If you have contributed but are missing here, please let us know!


1ocalhost on github
3dyd on github
Aaro Koskinen
Aaron Oneal
Aaron Orenstein
Aaron Scarisbrick
aasivov on github






>







1
2
3
4
5
6
7
8
9
10
11
12
13
14
 This project has been alive for many years. Countless people have provided
 feedback that have improved curl. Here follows a list of people that have
 contributed (a-z order).

 If you have contributed but are missing here, please let us know!

0xflotus on github
1ocalhost on github
3dyd on github
Aaro Koskinen
Aaron Oneal
Aaron Orenstein
Aaron Scarisbrick
aasivov on github
147
148
149
150
151
152
153

154
155
156
157
158
159
160
Andrew Krieger
Andrew Kurushin
Andrew Lambert
Andrew Moise
Andrew Potter
Andrew Robbins
Andrew Wansink

Andrey Labunets
Andrii Moiseiev
Andrius Merkys
Andrés García
Andy Cedilnik
Andy Fiddaman
Andy Serpa







>







148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
Andrew Krieger
Andrew Kurushin
Andrew Lambert
Andrew Moise
Andrew Potter
Andrew Robbins
Andrew Wansink
Andrey Gursky
Andrey Labunets
Andrii Moiseiev
Andrius Merkys
Andrés García
Andy Cedilnik
Andy Fiddaman
Andy Serpa
301
302
303
304
305
306
307

308
309
310
311
312
313
314
BrumBrum on hackerone
Bruno de Carvalho
Bruno Grasselli
Bruno Thomsen
Bryan Henderson
Bryan Kemp
bsammon on github

buzo-ffm on github
bxac on github
Bylon2 on github
Byrial Jensen
Caleb Raitto
Calvin Buckley
Cameron Cawley







>







303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
BrumBrum on hackerone
Bruno de Carvalho
Bruno Grasselli
Bruno Thomsen
Bryan Henderson
Bryan Kemp
bsammon on github
Bubu on github
buzo-ffm on github
bxac on github
Bylon2 on github
Byrial Jensen
Caleb Raitto
Calvin Buckley
Cameron Cawley
485
486
487
488
489
490
491

492
493
494
495
496
497
498
David Bau
David Benjamin
David Binderman
David Blaikie
David Byron
David Cohen
David E. Narváez

David Eriksson
David Garske
David Houlder
David Hull
David J Meyer
David James
David Kalnischkies







>







488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
David Bau
David Benjamin
David Binderman
David Blaikie
David Byron
David Cohen
David E. Narváez
David Earl
David Eriksson
David Garske
David Houlder
David Hull
David J Meyer
David James
David Kalnischkies
521
522
523
524
525
526
527

528
529
530
531
532
533
534
davidedec on github
dbrowndan on github
Dengminwen
Denis Baručić
Denis Chaplygin
Denis Feklushkin
Denis Goleshchikhin

Denis Ollier
Dennis Clarke
Dennis Felsing
Derek Higgins
Desmond O. Chang
destman on github
Detlef Schmier







>







525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
davidedec on github
dbrowndan on github
Dengminwen
Denis Baručić
Denis Chaplygin
Denis Feklushkin
Denis Goleshchikhin
Denis Laxalde
Denis Ollier
Dennis Clarke
Dennis Felsing
Derek Higgins
Desmond O. Chang
destman on github
Detlef Schmier
565
566
567
568
569
570
571

572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587

588
589
590
591
592
593
594
Dmitry Falko
Dmitry Kostjuchenko
Dmitry Kurochkin
Dmitry Mikhirev
Dmitry Popov
Dmitry Rechkin
Dmitry S. Baikov

dnivras on github
Dolbneff A.V
Domenico Andreoli
Dominick Meglio
Dominik Hölzl
Dominique Leuenberger
Don J Olmstead
Dongliang Mu
Doron Behar
Doug Kaufman
Doug Porter
Douglas Creager
Douglas E. Wegscheid
Douglas Kilpatrick
Douglas Mencken
Douglas R. Horner

Douglas Steinwand
Dov Murik
dpull on github
Drake Arconis
dtmsecurity on github
Duane Cathey
Duncan Mac-Vicar Prett







>
















>







570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
Dmitry Falko
Dmitry Kostjuchenko
Dmitry Kurochkin
Dmitry Mikhirev
Dmitry Popov
Dmitry Rechkin
Dmitry S. Baikov
Dmitry Wagin
dnivras on github
Dolbneff A.V
Domenico Andreoli
Dominick Meglio
Dominik Hölzl
Dominique Leuenberger
Don J Olmstead
Dongliang Mu
Doron Behar
Doug Kaufman
Doug Porter
Douglas Creager
Douglas E. Wegscheid
Douglas Kilpatrick
Douglas Mencken
Douglas R. Horner
Douglas R. Reno
Douglas Steinwand
Dov Murik
dpull on github
Drake Arconis
dtmsecurity on github
Duane Cathey
Duncan Mac-Vicar Prett
657
658
659
660
661
662
663

664
665
666
667
668
669
670
Eric Wu
Eric Young
Erick Nuwendam
Erik Jacobsen
Erik Janssen
Erik Johansson
Erik Minekus

Ernest Beinrohr
Ernst Sjöstrand
Erwan Legrand
Erwin Authried
Estanislau Augé-Pujadas
Ethan Glasser Camp
Etienne Simard







>







664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
Eric Wu
Eric Young
Erick Nuwendam
Erik Jacobsen
Erik Janssen
Erik Johansson
Erik Minekus
Erik Olsson
Ernest Beinrohr
Ernst Sjöstrand
Erwan Legrand
Erwin Authried
Estanislau Augé-Pujadas
Ethan Glasser Camp
Etienne Simard
694
695
696
697
698
699
700

701
702
703
704
705
706
707
Felix Hädicke
Felix Kaiser
Felix von Leitner
Felix Yan
Feng Tu
Fernando Muñoz
Filip Salomonsson

Flavio Medeiros
Florian Pritz
Florian Schoppmann
Florian Weimer
Florin Petriuc
Forrest Cahoon
Francisco Moraes







>







702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
Felix Hädicke
Felix Kaiser
Felix von Leitner
Felix Yan
Feng Tu
Fernando Muñoz
Filip Salomonsson
Flameborn on github
Flavio Medeiros
Florian Pritz
Florian Schoppmann
Florian Weimer
Florin Petriuc
Forrest Cahoon
Francisco Moraes
727
728
729
730
731
732
733

734
735
736
737
738
739
740
Frederik B
Frederik Wedel-Heinen
Fredrik Thulin
FuccDucc on github
fullincome on github
Gabriel Kuri
Gabriel Sjoberg

Garrett Holmstrom
Gary Maxwell
Gaurav Malhotra
Gautam Kachroo
Gautam Mani
Gavin Wong
Gavrie Philipson







>







736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
Frederik B
Frederik Wedel-Heinen
Fredrik Thulin
FuccDucc on github
fullincome on github
Gabriel Kuri
Gabriel Sjoberg
Ganesh Kamath
Garrett Holmstrom
Gary Maxwell
Gaurav Malhotra
Gautam Kachroo
Gautam Mani
Gavin Wong
Gavrie Philipson
807
808
809
810
811
812
813

814
815
816
817
818
819
820
Han Qiao
Hang Kin Lau
Hang Su
Hannes Magnusson
Hanno Böck
Hanno Kranzhoff
Hans Steegers

Hans-Jurgen May
Hao Wu
Hardeep Singh
Haris Okanovic
Harold Stuart
Harry Sintonen
Harshal Pradhan







>







817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
Han Qiao
Hang Kin Lau
Hang Su
Hannes Magnusson
Hanno Böck
Hanno Kranzhoff
Hans Steegers
Hans-Christian Noren Egtvedt
Hans-Jurgen May
Hao Wu
Hardeep Singh
Haris Okanovic
Harold Stuart
Harry Sintonen
Harshal Pradhan
830
831
832
833
834
835
836

837
838
839

840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855

856
857
858
859
860
861
862
863
864
865
866

867
868
869
870
871
872
873
Henri Gomez
Henrik Gaßmann
Henrik Storner
Henry Ludemann
Henry Roeland
Herve Amblard
Hidemoto Nakada

Ho-chi Chen
Hoi-Ho Chan
Hongli Lai

Howard Blaise
Howard Chu
hsiao yi
htasta on github
Hubert Kario
Hugo van Kemenade
Huzaifa Sidhpurwala
huzunhao on github
hydra3333 on github
Hzhijun
iammrtau on github
Ian D Allen
Ian Fette
Ian Ford
Ian Gulliver
Ian Lynagh

Ian Turner
Ian Wilkes
Ignacio Vazquez-Abrams
Igor Franchuk
Igor Khristophorov
Igor Makarov
Igor Novoseltsev
Igor Polyakov
Ihor Karpenko
ihsinme on github
Iida Yosiaki

Ilguiz Latypov
Ilja van Sprundel
Ilya Kosarev
imilli on github
Immanuel Gregoire
Inca R
infinnovation-dev on github







>



>
















>











>







841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
Henri Gomez
Henrik Gaßmann
Henrik Storner
Henry Ludemann
Henry Roeland
Herve Amblard
Hidemoto Nakada
Himanshu Gupta
Ho-chi Chen
Hoi-Ho Chan
Hongli Lai
Hongyi Zhao
Howard Blaise
Howard Chu
hsiao yi
htasta on github
Hubert Kario
Hugo van Kemenade
Huzaifa Sidhpurwala
huzunhao on github
hydra3333 on github
Hzhijun
iammrtau on github
Ian D Allen
Ian Fette
Ian Ford
Ian Gulliver
Ian Lynagh
Ian Spence
Ian Turner
Ian Wilkes
Ignacio Vazquez-Abrams
Igor Franchuk
Igor Khristophorov
Igor Makarov
Igor Novoseltsev
Igor Polyakov
Ihor Karpenko
ihsinme on github
Iida Yosiaki
Ikko Ashimine
Ilguiz Latypov
Ilja van Sprundel
Ilya Kosarev
imilli on github
Immanuel Gregoire
Inca R
infinnovation-dev on github
974
975
976
977
978
979
980

981
982
983
984
985
986
987
Jeremy Friesner
Jeremy Huddleston
Jeremy Lainé
Jeremy Lin
Jeremy Maitin-Shepard
Jeremy Pearson
Jeremy Tan

Jeroen Koekkoek
Jeroen Ooms
Jerome Muffat-Meridol
Jerome Robert
Jerome Vouillon
Jerry Krinock
Jerry Wu







>







989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
Jeremy Friesner
Jeremy Huddleston
Jeremy Lainé
Jeremy Lin
Jeremy Maitin-Shepard
Jeremy Pearson
Jeremy Tan
Jeremy Thibault
Jeroen Koekkoek
Jeroen Ooms
Jerome Muffat-Meridol
Jerome Robert
Jerome Vouillon
Jerry Krinock
Jerry Wu
1061
1062
1063
1064
1065
1066
1067

1068
1069
1070
1071
1072
1073
1074
Jon Rumsey
Jon Sargeant
Jon Seymour
Jon Spencer
Jon Torrey
Jon Travis
Jon Turner

Jonas Forsman
Jonas Minnberg
Jonas Schnelli
Jonas Vautherin
Jonatan Lander
Jonatan Vela
Jonathan Cardoso Machado







>







1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
Jon Rumsey
Jon Sargeant
Jon Seymour
Jon Spencer
Jon Torrey
Jon Travis
Jon Turner
Jon Wilkes
Jonas Forsman
Jonas Minnberg
Jonas Schnelli
Jonas Vautherin
Jonatan Lander
Jonatan Vela
Jonathan Cardoso Machado
1096
1097
1098
1099
1100
1101
1102

1103
1104
1105
1106
1107
1108
1109
Juan F. Codagnone
Juan Ignacio Hervás
Juan RP
Judson Bishop
Juergen Hoetzel
Juergen Wilke
Jukka Pihl

Julian Noble
Julian Ospald
Julian Romero Nieto
Julian Taylor
Julian Z
Julien Chaffraix
Julien Nabet







>







1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
Juan F. Codagnone
Juan Ignacio Hervás
Juan RP
Judson Bishop
Juergen Hoetzel
Juergen Wilke
Jukka Pihl
Julian Montes
Julian Noble
Julian Ospald
Julian Romero Nieto
Julian Taylor
Julian Z
Julien Chaffraix
Julien Nabet
1159
1160
1161
1162
1163
1164
1165

1166
1167
1168
1169
1170
1171
1172
Kevin Fisk
Kevin Ji
Kevin Lussier
Kevin R. Bulgrien
Kevin Reed
Kevin Roth
Kevin Smith

Kim Minjoong
Kim Rinnewitz
Kim Vandry
Kimmo Kinnunen
Kirill Marchuk
Kjell Ericson
Kjetil Jacobsen







>







1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
Kevin Fisk
Kevin Ji
Kevin Lussier
Kevin R. Bulgrien
Kevin Reed
Kevin Roth
Kevin Smith
Kevin Ushey
Kim Minjoong
Kim Rinnewitz
Kim Vandry
Kimmo Kinnunen
Kirill Marchuk
Kjell Ericson
Kjetil Jacobsen
1374
1375
1376
1377
1378
1379
1380

1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394

1395
1396
1397
1398
1399
1400
1401
Mateusz Loskot
Mathias Axelsson
Mathias Gumz
Mathieu Legare
Mats Lidell
Matt Arsenault
Matt Ford

Matt Kraai
Matt McClure
Matt Veenstra
Matt Witherspoon
Matt Wixson
Matteo Bignotti
Matteo Bignottignotti
Matteo Rocco
Matthew Blain
Matthew Clarke
Matthew Hall
Matthew Kerwin
Matthew Whitehead
Matthias Bolte

Matthias Naegler
Mattias Fornander
Matus Uzak
Maurice Barnum
Mauro Iorio
Mauro Rappa
Max Dymond







>














>







1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
Mateusz Loskot
Mathias Axelsson
Mathias Gumz
Mathieu Legare
Mats Lidell
Matt Arsenault
Matt Ford
Matt Holt
Matt Kraai
Matt McClure
Matt Veenstra
Matt Witherspoon
Matt Wixson
Matteo Bignotti
Matteo Bignottignotti
Matteo Rocco
Matthew Blain
Matthew Clarke
Matthew Hall
Matthew Kerwin
Matthew Whitehead
Matthias Bolte
Matthias Gatto
Matthias Naegler
Mattias Fornander
Matus Uzak
Maurice Barnum
Mauro Iorio
Mauro Rappa
Max Dymond
1469
1470
1471
1472
1473
1474
1475

1476
1477
1478
1479
1480
1481
1482
1483
1484

1485
1486
1487
1488
1489
1490
1491
Mikael Sennerholm
Mikalai Ananenka
Mike Bytnar
Mike Crowe
Mike Dobbs
Mike Dowell
Mike Frysinger

Mike Giancola
Mike Hasselberg
Mike Henshaw
Mike Hommey
Mike Mio
Mike Norton
Mike Power
Mike Protts
Mike Revi

Miklos Nemeth
Miloš Ljumović
Mingliang Zhu
Mingtao Yang
Miroslav Franc
Miroslav Spousta
Mischa Salle







>









>







1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
Mikael Sennerholm
Mikalai Ananenka
Mike Bytnar
Mike Crowe
Mike Dobbs
Mike Dowell
Mike Frysinger
Mike Gelfand
Mike Giancola
Mike Hasselberg
Mike Henshaw
Mike Hommey
Mike Mio
Mike Norton
Mike Power
Mike Protts
Mike Revi
Mike Tzou
Miklos Nemeth
Miloš Ljumović
Mingliang Zhu
Mingtao Yang
Miroslav Franc
Miroslav Spousta
Mischa Salle
1572
1573
1574
1575
1576
1577
1578

1579
1580
1581
1582
1583
1584
1585
nosajsnikta on github
NTMan on Github
Octavio Schroeder
Ofer
Okhin Vasilij
Ola Mork
Olaf Flebbe

Olaf Stüben
Oleg Pudeyev
Olen Andoni
olesteban on github
Oli Kingshott
Oliver Gondža
Oliver Graute







>







1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
nosajsnikta on github
NTMan on Github
Octavio Schroeder
Ofer
Okhin Vasilij
Ola Mork
Olaf Flebbe
Olaf Hering
Olaf Stüben
Oleg Pudeyev
Olen Andoni
olesteban on github
Oli Kingshott
Oliver Gondža
Oliver Graute
1602
1603
1604
1605
1606
1607
1608

1609
1610
1611
1612
1613
1614
1615
Oumph on github
ovidiu-benea on github
P R Schaffner
Palo Markovic
Paolo Mossino
Paolo Piacentini
Paras Sethia

Pascal Gaudette
Pascal Terjan
Pasha Kuznetsov
Pasi Karkkainen
Pat Ray
patelvivekv1993 on github
patnyb on github







>







1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
Oumph on github
ovidiu-benea on github
P R Schaffner
Palo Markovic
Paolo Mossino
Paolo Piacentini
Paras Sethia
parazyd on github
Pascal Gaudette
Pascal Terjan
Pasha Kuznetsov
Pasi Karkkainen
Pat Ray
patelvivekv1993 on github
patnyb on github
1882
1883
1884
1885
1886
1887
1888

1889
1890
1891
1892
1893
1894
1895
Ryan Nelson
Ryan Schmidt
Ryan Scott
Ryan Winograd
Ryuichi KAWAMATA
Rémy Léone
S. Moonesamy

Salah-Eddin Shaban
Saleem Abdulrasool
Salvador Dávila
Salvatore Sorrentino
Sam Deane
Sam Hurst
Sam Roth







>







1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
Ryan Nelson
Ryan Schmidt
Ryan Scott
Ryan Winograd
Ryuichi KAWAMATA
Rémy Léone
S. Moonesamy
Sai Ram Kunala
Salah-Eddin Shaban
Saleem Abdulrasool
Salvador Dávila
Salvatore Sorrentino
Sam Deane
Sam Hurst
Sam Roth
1918
1919
1920
1921
1922
1923
1924

1925
1926
1927
1928
1929
1930
1931
Scott Barrett
Scott Cantor
Scott Davis
Scott McCreary
Sean Boudreau
Sean Burford
Sean MacLennan

Sean Miller
Sebastiaan van Erk
Sebastian Haglund
Sebastian Mundry
Sebastian Pohlschmidt
Sebastian Rasmussen
Senthil Raja Velu







>







1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
Scott Barrett
Scott Cantor
Scott Davis
Scott McCreary
Sean Boudreau
Sean Burford
Sean MacLennan
Sean McArthur
Sean Miller
Sebastiaan van Erk
Sebastian Haglund
Sebastian Mundry
Sebastian Pohlschmidt
Sebastian Rasmussen
Senthil Raja Velu
2176
2177
2178
2179
2180
2181
2182

2183
2184
2185
2186
2187
2188
2189
Tyler Hall
Török Edwin
Ulf Härnhammar
Ulf Samuelsson
Ulrich Doehner
Ulrich Telle
Ulrich Zadow

Valentin David
Valentyn Korniienko
Valerii Zapodovnikov
vanillajonathan on github
Varnavas Papaioannou
Vasiliy Faronov
Vasily Lobaskin







>







2203
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
Tyler Hall
Török Edwin
Ulf Härnhammar
Ulf Samuelsson
Ulrich Doehner
Ulrich Telle
Ulrich Zadow
UrsusArctos on github
Valentin David
Valentyn Korniienko
Valerii Zapodovnikov
vanillajonathan on github
Varnavas Papaioannou
Vasiliy Faronov
Vasily Lobaskin
2243
2244
2245
2246
2247
2248
2249

2250
2251
2252
2253
2254
2255
2256
wmsch on github
wncboy on github
Wojciech Zwiefka
Wouter Van Rooy
Wu Yongzheng
Wyatt O'Day
Xavier Bouchoux

XhstormR on github
Xiang Xiao
Xiangbin Li
Xiaoyin Liu
XmiliaH on github
xnynx on github
xwxbug on github







>







2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
wmsch on github
wncboy on github
Wojciech Zwiefka
Wouter Van Rooy
Wu Yongzheng
Wyatt O'Day
Xavier Bouchoux
XhmikosR on github
XhstormR on github
Xiang Xiao
Xiangbin Li
Xiaoyin Liu
XmiliaH on github
xnynx on github
xwxbug on github
2291
2292
2293
2294
2295
2296
2297

2298
Zvi Har'El
zzq1015 on github
İsmail Dönmez
Łukasz Domeradzki
Štefan Kremeň
Коваленко Анатолий Викторович
Никита Дорохин

加藤郁之







>

2320
2321
2322
2323
2324
2325
2326
2327
2328
Zvi Har'El
zzq1015 on github
İsmail Dönmez
Łukasz Domeradzki
Štefan Kremeň
Коваленко Анатолий Викторович
Никита Дорохин
不确定
加藤郁之
Changes to jni/curl/docs/TODO.
69
70
71
72
73
74
75

76
77
78
79
80
81
82

 5. HTTP
 5.1 Better persistency for HTTP 1.0
 5.2 Set custom client ip when using haproxy protocol
 5.3 Rearrange request header order
 5.4 Allow SAN names in HTTP/2 server push
 5.5 auth= in URLs


 6. TELNET
 6.1 ditch stdin
 6.2 ditch telnet-specific select
 6.3 feature negotiation debug data

 7. SMTP







>







69
70
71
72
73
74
75
76
77
78
79
80
81
82
83

 5. HTTP
 5.1 Better persistency for HTTP 1.0
 5.2 Set custom client ip when using haproxy protocol
 5.3 Rearrange request header order
 5.4 Allow SAN names in HTTP/2 server push
 5.5 auth= in URLs
 5.6 alt-svc should fallback if alt-svc doesn't work

 6. TELNET
 6.1 ditch stdin
 6.2 ditch telnet-specific select
 6.3 feature negotiation debug data

 7. SMTP
96
97
98
99
100
101
102
103

104
105
106
107
108
109
110

 11. SMB
 11.1 File listing support
 11.2 Honor file timestamps
 11.3 Use NTLMv2
 11.4 Create remote directories

 12. New protocols


 13. SSL
 13.1 TLS-PSK with OpenSSL
 13.2 Provide mutex locking API
 13.3 Support in-memory certs/ca certs/keys
 13.4 Cache/share OpenSSL contexts
 13.5 Export session ids







|
>







97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112

 11. SMB
 11.1 File listing support
 11.2 Honor file timestamps
 11.3 Use NTLMv2
 11.4 Create remote directories

 12. FILE
 12.1 Directory listing for FILE:

 13. SSL
 13.1 TLS-PSK with OpenSSL
 13.2 Provide mutex locking API
 13.3 Support in-memory certs/ca certs/keys
 13.4 Cache/share OpenSSL contexts
 13.5 Export session ids
157
158
159
160
161
162
163

164
165

166
167
168
169
170

171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
 18.15 --retry should resume
 18.16 send only part of --data
 18.17 consider file name from the redirected URL with -O ?
 18.18 retry on network is unreachable
 18.19 expand ~/ in config files
 18.20 host name sections in config files
 18.21 retry on the redirected-to URL

 18.23 Set the modification date on an uploaded file
 18.24 Use multiple parallel transfers for a single download


 19. Build
 19.1 roffit
 19.2 Enable PIE and RELRO by default
 19.3 Don't use GNU libtool on OpenBSD


 20. Test suite
 20.1 SSL tunnel
 20.2 nicer lacking perl message
 20.3 more protocols supported
 20.4 more platforms supported
 20.5 Add support for concurrent connections
 20.6 Use the RFC6265 test suite
 20.7 Support LD_PRELOAD on macOS
 20.8 Run web-platform-tests url tests
 20.9 Use "random" ports for the test servers

 21. Next SONAME bump
 21.1 http-style HEAD output for FTP
 21.2 combine error codes
 21.3 extend CURLOPT_SOCKOPTFUNCTION prototype

 22. Next major release
 22.1 cleanup return codes
 22.2 remove obsolete defines
 22.3 size_t
 22.4 remove several functions
 22.5 remove CURLOPT_FAILONERROR
 22.7 remove progress meter from libcurl
 22.8 remove 'curl_httppost' from public

==============================================================================

1. libcurl

1.1 TFO support on Windows

 TCP Fast Open is supported on several platforms but not on Windows. Work on







>


>





>












<
<
<
<
<
<
<
<
<
<
<
<
<
<







159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187














188
189
190
191
192
193
194
 18.15 --retry should resume
 18.16 send only part of --data
 18.17 consider file name from the redirected URL with -O ?
 18.18 retry on network is unreachable
 18.19 expand ~/ in config files
 18.20 host name sections in config files
 18.21 retry on the redirected-to URL
 18.22 --fail-with-body
 18.23 Set the modification date on an uploaded file
 18.24 Use multiple parallel transfers for a single download
 18.25 Prevent terminal injection when writing to terminal

 19. Build
 19.1 roffit
 19.2 Enable PIE and RELRO by default
 19.3 Don't use GNU libtool on OpenBSD
 19.4 Package curl for Windows in a signed installer

 20. Test suite
 20.1 SSL tunnel
 20.2 nicer lacking perl message
 20.3 more protocols supported
 20.4 more platforms supported
 20.5 Add support for concurrent connections
 20.6 Use the RFC6265 test suite
 20.7 Support LD_PRELOAD on macOS
 20.8 Run web-platform-tests url tests
 20.9 Use "random" ports for the test servers















==============================================================================

1. libcurl

1.1 TFO support on Windows

 TCP Fast Open is supported on several platforms but not on Windows. Work on
600
601
602
603
604
605
606







607
608
609
610
611
612
613
 For example:

 http://test:pass;auth=NTLM@example.com would be equivalent to specifying
 --user test:pass;auth=NTLM or --user test:pass --ntlm from the command line.

 Additionally this should be implemented for proxy base URLs as well.









6. TELNET

6.1 ditch stdin

 Reading input (to send to the remote server) on stdin is a crappy solution
 for library purposes. We need to invent a good way for the application to be







>
>
>
>
>
>
>







591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
 For example:

 http://test:pass;auth=NTLM@example.com would be equivalent to specifying
 --user test:pass;auth=NTLM or --user test:pass --ntlm from the command line.

 Additionally this should be implemented for proxy base URLs as well.

5.6 alt-svc should fallback if alt-svc doesn't work

 The alt-svc: header provides a set of alternative services for curl to use
 instead of the original. If the first attempted one fails, it should try the
 next etc and if all alternatives fail go back to the original.

 See https://github.com/curl/curl/issues/4908

6. TELNET

6.1 ditch stdin

 Reading input (to send to the remote server) on stdin is a crappy solution
 for library purposes. We need to invent a good way for the application to be
677
678
679
680
681
682
683
684
685
686
687
688
689

690
691
692
693
694
695
696
697
698
699
700







701
702
703
704
705
706
707

 https://github.com/curl/curl/issues/4452

11. SMB

11.1 File listing support

Add support for listing the contents of a SMB share. The output should probably
be the same as/similar to FTP.

11.2 Honor file timestamps

The timestamp of the transferred file should reflect that of the original file.


11.3 Use NTLMv2

Currently the SMB authentication uses NTLMv1.

11.4 Create remote directories

Support for creating remote directories when uploading a file to a directory
that doesn't exist on the server, just like --ftp-create-dirs.

12. New protocols








13. SSL

13.1 TLS-PSK with OpenSSL

 Transport Layer Security pre-shared key ciphersuites (TLS-PSK) is a set of
 cryptographic protocols that provide secure communication based on pre-shared







|
|



|
>



|



|
|

|
>
>
>
>
>
>
>







675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713

 https://github.com/curl/curl/issues/4452

11. SMB

11.1 File listing support

 Add support for listing the contents of a SMB share. The output should
 probably be the same as/similar to FTP.

11.2 Honor file timestamps

 The timestamp of the transferred file should reflect that of the original
 file.

11.3 Use NTLMv2

 Currently the SMB authentication uses NTLMv1.

11.4 Create remote directories

 Support for creating remote directories when uploading a file to a directory
 that doesn't exist on the server, just like --ftp-create-dirs.


12. FILE

12.1 Directory listing for FILE:

 Add support for listing the contents of a directory accessed with FILE. The
 output should probably be the same as/similar to FTP.


13. SSL

13.1 TLS-PSK with OpenSSL

 Transport Layer Security pre-shared key ciphersuites (TLS-PSK) is a set of
 cryptographic protocols that provide secure communication based on pre-shared
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
 independently of OpenSSL or GnutTLS being used.

13.3 Support in-memory certs/ca certs/keys

 You can specify the private and public keys for SSH/SSL as file paths. Some
 programs want to avoid using files and instead just pass them as in-memory
 data blobs. There's probably a challenge to make this work across the
 plethory of different TLS and SSH backends that curl supports.
 https://github.com/curl/curl/issues/2310

13.4 Cache/share OpenSSL contexts

 "Look at SSL cafile - quick traces look to me like these are done on every
 request as well, when they should only be necessary once per SSL context (or
 once per handle)". The major improvement we can rather easily do is to make







|







723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
 independently of OpenSSL or GnutTLS being used.

13.3 Support in-memory certs/ca certs/keys

 You can specify the private and public keys for SSH/SSL as file paths. Some
 programs want to avoid using files and instead just pass them as in-memory
 data blobs. There's probably a challenge to make this work across the
 plethora of different TLS and SSH backends that curl supports.
 https://github.com/curl/curl/issues/2310

13.4 Cache/share OpenSSL contexts

 "Look at SSL cafile - quick traces look to me like these are done on every
 request as well, when they should only be necessary once per SSL context (or
 once per handle)". The major improvement we can rather easily do is to make
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809

13.11 Support intermediate & root pinning for PINNEDPUBLICKEY

 CURLOPT_PINNEDPUBLICKEY does not consider the hashes of intermediate & root
 certificates when comparing the pinned keys. Therefore it is not compatible
 with "HTTP Public Key Pinning" as there also intermediate and root
 certificates can be pinned. This is very useful as it prevents webadmins from
 "locking themself out of their servers".

 Adding this feature would make curls pinning 100% compatible to HPKP and
 allow more flexible pinning.

13.12 Support HSTS

 "HTTP Strict Transport Security" is TOFU (trust on first use), time-based







|







801
802
803
804
805
806
807
808
809
810
811
812
813
814
815

13.11 Support intermediate & root pinning for PINNEDPUBLICKEY

 CURLOPT_PINNEDPUBLICKEY does not consider the hashes of intermediate & root
 certificates when comparing the pinned keys. Therefore it is not compatible
 with "HTTP Public Key Pinning" as there also intermediate and root
 certificates can be pinned. This is very useful as it prevents webadmins from
 "locking themselves out of their servers".

 Adding this feature would make curls pinning 100% compatible to HPKP and
 allow more flexible pinning.

13.12 Support HSTS

 "HTTP Strict Transport Security" is TOFU (trust on first use), time-based
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
 post-handshake authentication. We should make sure to live up to that.

 See https://github.com/curl/curl/issues/5396

13.14 Support the clienthello extension

 Certain stupid networks and middle boxes have a problem with SSL handshake
 pakets that are within a certain size range because how that sets some bits
 that previously (in older TLS version) were not set. The clienthello
 extension adds padding to avoid that size range.

 https://tools.ietf.org/html/rfc7685
 https://github.com/curl/curl/issues/2299

14. GnuTLS







|







826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
 post-handshake authentication. We should make sure to live up to that.

 See https://github.com/curl/curl/issues/5396

13.14 Support the clienthello extension

 Certain stupid networks and middle boxes have a problem with SSL handshake
 packets that are within a certain size range because how that sets some bits
 that previously (in older TLS version) were not set. The clienthello
 extension adds padding to avoid that size range.

 https://tools.ietf.org/html/rfc7685
 https://github.com/curl/curl/issues/2299

14. GnuTLS
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
 invoke can talk to the still running instance and ask for transfers to get
 done, and thus maintain its connection pool, DNS cache and more.

18.13 Ratelimit or wait between serial requests

 Consider a command line option that can make curl do multiple serial requests
 slow, potentially with a (random) wait between transfers. There's also a
 propsed set of standard HTTP headers to let servers let the client adapt to
 its rate limits:
 https://www.ietf.org/id/draft-polli-ratelimit-headers-02.html

 See https://github.com/curl/curl/issues/5406

18.14 --dry-run








|







1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
 invoke can talk to the still running instance and ask for transfers to get
 done, and thus maintain its connection pool, DNS cache and more.

18.13 Ratelimit or wait between serial requests

 Consider a command line option that can make curl do multiple serial requests
 slow, potentially with a (random) wait between transfers. There's also a
 proposed set of standard HTTP headers to let servers let the client adapt to
 its rate limits:
 https://www.ietf.org/id/draft-polli-ratelimit-headers-02.html

 See https://github.com/curl/curl/issues/5406

18.14 --dry-run

1137
1138
1139
1140
1141
1142
1143








1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
 URL only instead of the original operation to the original URL.

 Perhaps extra emphasized if the original transfer is a large POST that
 redirects to a separate GET, and that GET is what gets the 529

 See https://github.com/curl/curl/issues/5462









18.23 Set the modification date on an uploaded file

 For SFTP and posssibly FTP, curl could offer an option to set the
 modification time for the uploaded file.

 See https://github.com/curl/curl/issues/5768

18.24 Use multiple parallel transfers for a single download

 To enhance transfer speed, downloading a single URL can be split up into







>
>
>
>
>
>
>
>


|







1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
 URL only instead of the original operation to the original URL.

 Perhaps extra emphasized if the original transfer is a large POST that
 redirects to a separate GET, and that GET is what gets the 529

 See https://github.com/curl/curl/issues/5462

18.22 --fail-with-body

 Lots of users who want --fail still want the response body saved as well -
 which --fail doesn't offer. The current solution for users is to use
 --write-out with %{response_code} and script the missing logic, but adding a
 --fail-with-body option could be an easier way for users without requiring
 external conditional checks.

18.23 Set the modification date on an uploaded file

 For SFTP and possibly FTP, curl could offer an option to set the
 modification time for the uploaded file.

 See https://github.com/curl/curl/issues/5768

18.24 Use multiple parallel transfers for a single download

 To enhance transfer speed, downloading a single URL can be split up into
1164
1165
1166
1167
1168
1169
1170









1171
1172
1173
1174
1175
1176
1177
   again. Then again, etc up to a limit.

 This way, if transfer B fails (because Range: isn't supported) it will let
 transfer A remain the single one. N and M could be set to some sensible
 defaults.

 See https://github.com/curl/curl/issues/5774










19. Build

19.1 roffit

 Consider extending 'roffit' to produce decent ASCII output, and use that
 instead of (g)nroff when building src/tool_hugehelp.c







>
>
>
>
>
>
>
>
>







1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
   again. Then again, etc up to a limit.

 This way, if transfer B fails (because Range: isn't supported) it will let
 transfer A remain the single one. N and M could be set to some sensible
 defaults.

 See https://github.com/curl/curl/issues/5774

18.25 Prevent terminal injection when writing to terminal

 curl could offer an option to make escape sequence either non-functional or
 avoid cursor moves or similar to reduce the risk of a user getting tricked by
 clever tricks.

 See https://github.com/curl/curl/issues/6150


19. Build

19.1 roffit

 Consider extending 'roffit' to produce decent ASCII output, and use that
 instead of (g)nroff when building src/tool_hugehelp.c
1193
1194
1195
1196
1197
1198
1199




1200
1201
1202
1203
1204
1205
1206
 errors when you use GNU libtool. This can be fixed by using the libtool
 provided by OpenBSD itself. However for this the user always needs to invoke
 make with "LIBTOOL=/usr/bin/libtool". It would be nice if the script could
 have some magic to detect if this system is an OpenBSD host and then use the
 OpenBSD libtool instead.

 See https://github.com/curl/curl/issues/5862





20. Test suite

20.1 SSL tunnel

 Make our own version of stunnel for simple port forwarding to enable HTTPS
 and FTP-SSL tests without the stunnel dependency, and it could allow us to







>
>
>
>







1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
 errors when you use GNU libtool. This can be fixed by using the libtool
 provided by OpenBSD itself. However for this the user always needs to invoke
 make with "LIBTOOL=/usr/bin/libtool". It would be nice if the script could
 have some magic to detect if this system is an OpenBSD host and then use the
 OpenBSD libtool instead.

 See https://github.com/curl/curl/issues/5862

19.4 Package curl for Windows in a signed installer

 See https://github.com/curl/curl/issues/5424

20. Test suite

20.1 SSL tunnel

 Make our own version of stunnel for simple port forwarding to enable HTTPS
 and FTP-SSL tests without the stunnel dependency, and it could allow us to
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
 they can be changed with a switch), consider letting each server pick a
 random available one at start-up, store that info in a file and let the test
 suite use that.

 We could then remove the "check that it is our server that's running"-check
 and we would immediately detect when we write tests wrongly to use hard-coded
 port numbers.

21. Next SONAME bump

21.1 http-style HEAD output for FTP

 #undef CURL_FTP_HTTPSTYLE_HEAD in lib/ftp.c to remove the HTTP-style headers
 from being output in NOBODY requests over FTP

21.2 combine error codes

 Combine some of the error codes to remove duplicates.  The original
 numbering should not be changed, and the old identifiers would be
 macroed to the new ones in an CURL_NO_OLDIES section to help with
 backward compatibility.

 Candidates for removal and their replacements:

    CURLE_FILE_COULDNT_READ_FILE => CURLE_REMOTE_FILE_NOT_FOUND

    CURLE_FTP_COULDNT_RETR_FILE => CURLE_REMOTE_FILE_NOT_FOUND

    CURLE_FTP_COULDNT_USE_REST => CURLE_RANGE_ERROR

    CURLE_FUNCTION_NOT_FOUND => CURLE_FAILED_INIT

    CURLE_LDAP_INVALID_URL => CURLE_URL_MALFORMAT

    CURLE_TFTP_NOSUCHUSER => CURLE_TFTP_ILLEGAL

    CURLE_TFTP_NOTFOUND => CURLE_REMOTE_FILE_NOT_FOUND

    CURLE_TFTP_PERM => CURLE_REMOTE_ACCESS_DENIED

21.3 extend CURLOPT_SOCKOPTFUNCTION prototype

 The current prototype only provides 'purpose' that tells what the
 connection/socket is for, but not any protocol or similar. It makes it hard
 for applications to differentiate on TCP vs UDP and even HTTP vs FTP and
 similar.

22. Next major release

22.1 cleanup return codes

 curl_easy_cleanup() returns void, but curl_multi_cleanup() returns a
 CURLMcode. These should be changed to be the same.

22.2 remove obsolete defines

 remove obsolete defines from curl/curl.h

22.3 size_t

 make several functions use size_t instead of int in their APIs

22.4 remove several functions

 remove the following functions from the public API:

 curl_getenv

 curl_mprintf (and variations)

 curl_strequal

 curl_strnequal

 They will instead become curlx_ - alternatives. That makes the curl app
 still capable of using them, by building with them from source.

 These functions have no purpose anymore:

 curl_multi_socket

 curl_multi_socket_all

22.5 remove CURLOPT_FAILONERROR

 Remove support for CURLOPT_FAILONERROR, it has gotten too kludgy and weird
 internally. Let the app judge success or not for itself.

22.7 remove progress meter from libcurl

 The internally provided progress meter output doesn't belong in the library.
 Basically no application wants it (apart from curl) but instead applications
 can and should do their own progress meters using the progress callback.

 The progress callback should then be bumped as well to get proper 64bit
 variable types passed to it instead of doubles so that big files work
 correctly.

22.8 remove 'curl_httppost' from public

 curl_formadd() was made to fill in a public struct, but the fact that the
 struct is public is never really used by application for their own advantage
 but instead often restricts how the form functions can or can't be modified.

 Changing them to return a private handle will benefit the implementation and
 allow us much greater freedoms while still maintaining a solid API and ABI.







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
1292
1293
1294
1295
1296
1297
1298



































































































 they can be changed with a switch), consider letting each server pick a
 random available one at start-up, store that info in a file and let the test
 suite use that.

 We could then remove the "check that it is our server that's running"-check
 and we would immediately detect when we write tests wrongly to use hard-coded
 port numbers.



































































































Changes to jni/curl/docs/TheArtOfHttpScripting.md.
218
219
220
221
222
223
224

225
226
227
228

229
230
231
232
233
234
235
 Of course there has to be some kind of program on the server end to receive
 the data you send. You cannot just invent something out of the air.

## GET

 A GET-form uses the method GET, as specified in HTML like:


    <form method="GET" action="junk.cgi">
      <input type=text name="birthyear">
      <input type=submit name=press value="OK">
    </form>


 In your favorite browser, this form will appear with a text box to fill in
 and a press-button labeled "OK". If you fill in '1905' and press the OK
 button, your browser will then create a new URL to get for you. The URL will
 get `junk.cgi?birthyear=1905&press=OK` appended to the path part of the
 previous URL.








>
|
|
|
|
>







218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
 Of course there has to be some kind of program on the server end to receive
 the data you send. You cannot just invent something out of the air.

## GET

 A GET-form uses the method GET, as specified in HTML like:

```html
<form method="GET" action="junk.cgi">
  <input type=text name="birthyear">
  <input type=submit name=press value="OK">
</form>
```

 In your favorite browser, this form will appear with a text box to fill in
 and a press-button labeled "OK". If you fill in '1905' and press the OK
 button, your browser will then create a new URL to get for you. The URL will
 get `junk.cgi?birthyear=1905&press=OK` appended to the path part of the
 previous URL.

254
255
256
257
258
259
260

261
262
263
264

265
266
267
268
269
270
271

 The HTTP protocol then offers the POST method. This way the client sends the
 data separated from the URL and thus you won't see any of it in the URL
 address field.

 The form would look very similar to the previous one:


    <form method="POST" action="junk.cgi">
      <input type=text name="birthyear">
      <input type=submit name=press value=" OK ">
    </form>


 And to use curl to post this form with the same data filled in as before, we
 could do it like:

    curl --data "birthyear=1905&press=%20OK%20" http://www.example.com/when.cgi

 This kind of POST will use the Content-Type







>
|
|
|
|
>







256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275

 The HTTP protocol then offers the POST method. This way the client sends the
 data separated from the URL and thus you won't see any of it in the URL
 address field.

 The form would look very similar to the previous one:

```html
<form method="POST" action="junk.cgi">
  <input type=text name="birthyear">
  <input type=submit name=press value=" OK ">
</form>
```

 And to use curl to post this form with the same data filled in as before, we
 could do it like:

    curl --data "birthyear=1905&press=%20OK%20" http://www.example.com/when.cgi

 This kind of POST will use the Content-Type
289
290
291
292
293
294
295

296
297
298
299

300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317

318
319
320
321
322

323
324
325
326
327
328
329
 Back in late 1995 they defined an additional way to post data over HTTP. It
 is documented in the RFC 1867, why this method sometimes is referred to as
 RFC1867-posting.

 This method is mainly designed to better support file uploads. A form that
 allows a user to upload a file could be written like this in HTML:


    <form method="POST" enctype='multipart/form-data' action="upload.cgi">
      <input type=file name=upload>
      <input type=submit name=press value="OK">
    </form>


 This clearly shows that the Content-Type about to be sent is
 `multipart/form-data`.

 To post to a form like this with curl, you enter a command line like:

    curl --form upload=@localfilename --form press=OK [URL]

## Hidden Fields

 A very common way for HTML based applications to pass state information
 between pages is to add hidden fields to the forms. Hidden fields are already
 filled in, they aren't displayed to the user and they get passed along just
 as all the other fields.

 A similar example form with one visible field, one hidden field and one
 submit button could look like:


    <form method="POST" action="foobar.cgi">
      <input type=text name="birthyear">
      <input type=hidden name="person" value="daniel">
      <input type=submit name="press" value="OK">
    </form>


 To POST this with curl, you won't have to think about if the fields are
 hidden or not. To curl they're all the same:

    curl --data "birthyear=1905&press=OK&person=daniel" [URL]

## Figure Out What A POST Looks Like







>
|
|
|
|
>


















>
|
|
|
|
|
>







293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
 Back in late 1995 they defined an additional way to post data over HTTP. It
 is documented in the RFC 1867, why this method sometimes is referred to as
 RFC1867-posting.

 This method is mainly designed to better support file uploads. A form that
 allows a user to upload a file could be written like this in HTML:

```html
<form method="POST" enctype='multipart/form-data' action="upload.cgi">
  <input type=file name=upload>
  <input type=submit name=press value="OK">
</form>
```

 This clearly shows that the Content-Type about to be sent is
 `multipart/form-data`.

 To post to a form like this with curl, you enter a command line like:

    curl --form upload=@localfilename --form press=OK [URL]

## Hidden Fields

 A very common way for HTML based applications to pass state information
 between pages is to add hidden fields to the forms. Hidden fields are already
 filled in, they aren't displayed to the user and they get passed along just
 as all the other fields.

 A similar example form with one visible field, one hidden field and one
 submit button could look like:

```html
<form method="POST" action="foobar.cgi">
  <input type=text name="birthyear">
  <input type=hidden name="person" value="daniel">
  <input type=submit name="press" value="OK">
</form>
```

 To POST this with curl, you won't have to think about if the fields are
 hidden or not. To curl they're all the same:

    curl --data "birthyear=1905&press=OK&person=daniel" [URL]

## Figure Out What A POST Looks Like
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
## Proxy Authentication

 Sometimes your HTTP access is only available through the use of a HTTP
 proxy. This seems to be especially common at various companies. A HTTP proxy
 may require its own user and password to allow the client to get through to
 the Internet. To specify those with curl, run something like:

        curl --proxy-user proxyuser:proxypassword curl.se

 If your proxy requires the authentication to be done using the NTLM method,
 use [`--proxy-ntlm`](https://curl.se/docs/manpage.html#--proxy-ntlm), if
 it requires Digest use
 [`--proxy-digest`](https://curl.se/docs/manpage.html#--proxy-digest).

 If you use any one of these user+password options but leave out the password







|







387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
## Proxy Authentication

 Sometimes your HTTP access is only available through the use of a HTTP
 proxy. This seems to be especially common at various companies. A HTTP proxy
 may require its own user and password to allow the client to get through to
 the Internet. To specify those with curl, run something like:

    curl --proxy-user proxyuser:proxypassword curl.se

 If your proxy requires the authentication to be done using the NTLM method,
 use [`--proxy-ntlm`](https://curl.se/docs/manpage.html#--proxy-ntlm), if
 it requires Digest use
 [`--proxy-digest`](https://curl.se/docs/manpage.html#--proxy-digest).

 If you use any one of these user+password options but leave out the password
Added jni/curl/docs/URL-SYNTAX.md.


































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
# URL syntax and their use in curl

## Specifications

The official "URL syntax" is primarily defined in these two different
specifications:

 - [RFC 3986](https://tools.ietf.org/html/rfc3986) (although URL is called "URI" in there)
 - [The WHATWG URL Specification](https://url.spec.whatwg.org/)

RFC 3986 is the earlier one, and curl has always tried to adhere to that one
(since it shipped in January 2005).

The WHATWG URL spec was written later, is incompatible with the RFC 3986 and
changes over time.

## Variations

URL parsers as implemented in browsers, libraries and tools usually opt to
support one of the mentioned specifications. Bugs, differences in
interpretations and the moving nature of the WHATWG spec does however make it
very unlikely that multiple parsers treat URLs the exact same way!

## Security

Due to the inherent differences between URL parser implementations, it is
considered a security risk to mix different implementations and assume the
same behavior!

For example, if you use one parser to check if a URL uses a good host name or
the correct auth field, and then pass on that same URL to a *second* parser,
there will always be a risk it treats the same URL differently. There is no
right and wrong in URL land, only differences of opinions.

libcurl offers a separate API to its URL parser for this reason, among others.

Applications may at times find it convenient to allow users to specify URLs
for various purposes and that string would then end up fed to curl. Getting a
URL from an external untrusted party and using it with curl brings several
security concerns:

1. If you have an application that runs as or in a server application, getting
   an unfiltered URL can trick your application to access a local resource
   instead of a remote resource. Protecting yourself against localhost accesses is very
   hard when accepting user provided URLs.

2. Such custom URLs can access other ports than you planned as port numbers
   are part of the regular URL format. The combination of a local host and a
   custom port number can allow external users to play tricks with your local
   services.

3. Such a URL might use other schemes than you thought of or planned for.

## "RFC3986 plus"

curl recognizes a URL syntax that we call "RFC 3986 plus". It is grounded on
the well established RFC 3986 to make sure previously written command lines and
curl using scripts will remain working.

curl's URL parser allows a few deviations from the spec in order to
inter-operate better with URLs that appear in the wild.

### spaces

In particular `Location:` headers that indicate to the client where a resource
has been redirected to, sometimes contain spaces. This is a violation of RFC
3986 but is fine in the WHATWG spec. curl handles these by re-encoding them to
`%20`.

### non-ASCII

Byte values in a provided URL that are outside of the printable ASCII range
are percent-encoded by curl.

### multiple slashes

An absolute URL always starts with a "scheme" followed by a colon. For all the
schemes curl supports, the colon must be followed by two slashes according to
RFC 3986 but not according to the WHATWG spec - which allows one to infinity
amount.

curl allows one, two or three slashes after the colon to still be considered a
valid URL.

### "scheme-less"

curl supports "URLs" that do not start with a scheme. This is not supported by
any of the specifications. This is a shortcut to entering URLs that was
supported by browsers early on and has been mimicked by curl.

Based on what the host name starts with, curl will "guess" what protocol to
use:

 - `ftp.` means FTP
 - `dict.` means DICT
 - `ldap.` means LDAP
 - `imap.` means IMAP
 - `smtp.` means SMTP
 - `pop3.` means POP3
 - all other means HTTP

### globbing letters

The curl command line tool supports "globbing" of URLs. It means that you can
create ranges and lists using `[N-M]` and `{one,two,three}` sequences. The
letters used for this (`[]{}`) are reserved in RFC 3986 and can therefore not
legitimately be part of such a URL.

They are however not reserved or special in the WHATWG specification, so
globbing can mess up such URLs. Globbing can be turned off for such occasions
(using `--globoff`).

# URL syntax details

A URL may consist of the following components - many of them are optional:

    [scheme][divider][userinfo][hostname][port number][path][query][fragment]

Each component is separated from the following component with a divider
character or string.

For example, this could look like:

    http://user:password@www.example.com:80/index.hmtl?foo=bar#top

## Scheme

The scheme specifies the protocol to use. A curl build can support a few or
many different schemes. You can limit what schemes curl should accept.

curl supports the following schemes on URLs specified to transfer. They are
matched case insensitively:

`dict`, `file`, `ftp`, `ftps`, `gopher`, `gophers`, `http`, `https`, `imap`,
`imaps`, `ldap`, `ldaps`, `mqtt`, `pop3`, `pop3s`, `rtmp`, `rtmpe`, `rtmps`,
`rtmpt`, `rtmpte`, `rtmpts`, `rtsp`, `smb`, `smbs`, `smtp`, `smtps`, `telnet`,
`tftp`

When the URL is specified to identify a proxy, curl recognizes the following
schemes:

`http`, `https`, `socks4`, `socks4a`, `socks5`, `socks5h`, `socks`

## Userinfo

The userinfo field can be used to set user name and password for
authentication purposes in this transfer. The use of this field is discouraged
since it often means passing around the password in plain text and is thus a
security risk.

URLs for IMAP, POP3 and SMTP also support *login options* as part of the
userinfo field. They're provided as a semicolon after the password and then
the options.

## Hostname

The hostname part of the URL contains the address of the server that you want
to connect to. This can be the fully qualified domain name of the server, the
local network name of the machine on your network or the IP address of the
server or machine represented by either an IPv4 or IPv6 address (within
brackets). For example:

    http://www.example.com/

    http://hostname/

    http://192.168.0.1/

    http://[2001:1890:1112:1::20]/

### IDNA

If curl was built with International Domain Name (IDN) support, it can also
handle host names using non-ASCII characters.

curl supports IDN host names using the IDNA 2008 standard. This differs from
browsers that follow the WHATWG URL spec, which dictates IDNA 2003 to be used.
The two standards have a huge overlap but differ slightly, perhaps most
famously in how they deal with the German "double s" (`ß`).

## Port number

If there's a colon after the hostname, that should be followed by the port
number to use. 1 - 65535. curl also supports a blank port number field - but
only if the URL starts with a scheme.

If the port number is not specified in the URL, curl will used a default port
based on the provide scheme:

DICT 2628, FTP 21, FTPS 990, GOPHER 70, GOPHERS 70, HTTP 80, HTTPS 443,
IMAP 132, IMAPS 993, LDAP 369, LDAPS 636, MQTT 1883, POP3 110, POP3S 995,
RTMP 1935, RTMPS 443, RTMPT 80, RTSP 554, SCP 22, SFTP 22, SMB 445, SMBS 445,
SMTP 25, SMTPS 465, TELNET 23, TFTP 69

# Scheme specific behaviors

## FTP

The path part of an FTP request specifies the file to retrieve and from which
directory. If the file part is omitted then libcurl downloads the directory
listing for the directory specified. If the directory is omitted then the
directory listing for the root / home directory will be returned.

FTP servers typically put the user in its "home directory" after login, which
then differs between users. To explicitly specify the root directory of an FTP
server start the path with double slash `//` or `/%2f` (2F is the hexadecimal
value of the ascii code for the slash).

## FILE

When a `FILE://` URL is accessed on Windows systems, it can be crafted in a
way so that Windows attempts to connect to a (remote) machine when curl wants
to read or write such a path.

curl only allows the hostname part of a FILE URL to be one out of these three
alternatives: `localhost`, `127.0.0.1` or blank ("", zero characters).
Anything else will make curl fail to parse the URL.

### Windows-specific FILE details

curl accepts that the FILE URL's path starts with a "drive letter". That's a
single letter `a` to `z` followed by a colon or a pipe character (`|`).

The Windows operating system itself will convert some file accesses to perform
network accesses over SMB/CIFS, through several different file path patterns.
This way, a `file://` URL passed to curl *might* be converted into a network
access inadvertently and unknowingly to curl. This is a Windows feature curl
cannot control or disable.

## IMAP

The path part of an IMAP request not only specifies the mailbox to list or
select, but can also be used to check the `UIDVALIDITY` of the mailbox, to
specify the `UID`, `SECTION` and `PARTIAL` octets of the message to fetch and
to specify what messages to search for.

A top level folder list:

    imap://user:password@mail.example.com

A folder list on the user's inbox:

    imap://user:password@mail.example.com/INBOX

Select the user's inbox and fetch message with uid = 1:

    imap://user:password@mail.example.com/INBOX/;UID=1

Select the user's inbox and fetch the first message in the mail box:

    imap://user:password@mail.example.com/INBOX/;MAILINDEX=1

Select the user's inbox, check the `UIDVALIDITY` of the mailbox is 50 and
fetch message 2 if it is:

    imap://user:password@mail.example.com/INBOX;UIDVALIDITY=50/;UID=2

Select the user's inbox and fetch the text portion of message 3:

    imap://user:password@mail.example.com/INBOX/;UID=3/;SECTION=TEXT

Select the user's inbox and fetch the first 1024 octets of message 4:

    imap://user:password@mail.example.com/INBOX/;UID=4/;PARTIAL=0.1024

Select the user's inbox and check for NEW messages:

    imap://user:password@mail.example.com/INBOX?NEW

Select the user's inbox and search for messages containing "shadows" in the
subject line:

    imap://user:password@mail.example.com/INBOX?SUBJECT%20shadows

For more information about the individual components of an IMAP URL please see
RFC 5092.

## LDAP

The path part of a LDAP request can be used to specify the: Distinguished
Name, Attributes, Scope, Filter and Extension for a LDAP search. Each field is
separated by a question mark and when that field is not required an empty
string with the question mark separator should be included.

Search for the DN as `My Organisation`:

    ldap://ldap.example.com/o=My%20Organisation

the same search but will only return postalAddress attributes:

    ldap://ldap.example.com/o=My%20Organisation?postalAddress

Search for an empty DN and request information about the
`rootDomainNamingContext` attribute for an Active Directory server:

    ldap://ldap.example.com/?rootDomainNamingContext

For more information about the individual components of a LDAP URL please
see [RFC 4516](https://tools.ietf.org/html/rfc4516).

## POP3

The path part of a POP3 request specifies the message ID to retrieve. If the
ID is not specified then a list of waiting messages is returned instead.

## SCP

The path part of an SCP URL specifies the path and file to retrieve or
upload. The file is taken as an absolute path from the root directory on the
server.

To specify a path relative to the user's home directory on the server, prepend
`~/` to the path portion.

## SFTP

The path part of an SFTP URL specifies the file to retrieve or upload. If the
path ends with a slash (`/`) then a directory listing is returned instead of a
file. If the path is omitted entirely then the directory listing for the root
/ home directory will be returned.

## SMB
The path part of a SMB request specifies the file to retrieve and from what
share and directory or the share to upload to and as such, may not be omitted.
If the user name is embedded in the URL then it must contain the domain name
and as such, the backslash must be URL encoded as %2f.

curl supports SMB version 1 (only)

## SMTP

The path part of a SMTP request specifies the host name to present during
communication with the mail server. If the path is omitted, then libcurl will
attempt to resolve the local computer's host name. However, this may not
return the fully qualified domain name that is required by some mail servers
and specifying this path allows you to set an alternative name, such as your
machine's fully qualified domain name, which you might have obtained from an
external function such as gethostname or getaddrinfo.

The default smtp port is 25. Some servers use port 587 as an alternative.

## RTMP

There's no official URL spec for RTMP so libcurl uses the URL syntax supported
by the underlying librtmp library. It has a syntax where it wants a
traditional URL, followed by a space and a series of space-separated
`name=value` pairs.

While space is not typically a "legal" letter, libcurl accepts them. When a
user wants to pass in a `#` (hash) character it will be treated as a fragment
and get cut off by libcurl if provided literally. You will instead have to
escape it by providing it as backslash and its ASCII value in hexadecimal:
`\23`.
Changes to jni/curl/docs/VERSIONS.md.
37
38
39
40
41
42
43

44

45
46
47
48
49
50
51

 As a service to any application that might want to support new libcurl
 features while still being able to build with older versions, all releases
 have the libcurl version stored in the curl/curlver.h file using a static
 numbering scheme that can be used for comparison. The version number is
 defined as:


        #define LIBCURL_VERSION_NUM 0xXXYYZZ


 Where XX, YY and ZZ are the main version, release and patch numbers in
 hexadecimal. All three number fields are always represented using two digits
 (eight bits each). 1.2 would appear as "0x010200" while version 9.11.7
 appears as "0x090b07".

 This 6-digit hexadecimal number is always a greater number in a more recent







>
|
>







37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53

 As a service to any application that might want to support new libcurl
 features while still being able to build with older versions, all releases
 have the libcurl version stored in the curl/curlver.h file using a static
 numbering scheme that can be used for comparison. The version number is
 defined as:

```c
#define LIBCURL_VERSION_NUM 0xXXYYZZ
```

 Where XX, YY and ZZ are the main version, release and patch numbers in
 hexadecimal. All three number fields are always represented using two digits
 (eight bits each). 1.2 would appear as "0x010200" while version 9.11.7
 appears as "0x090b07".

 This 6-digit hexadecimal number is always a greater number in a more recent
Changes to jni/curl/docs/cmdline-opts/Makefile.in.
310
311
312
313
314
315
316

317
318
319
320
321
322
323
STRIP = @STRIP@
SUPPORT_FEATURES = @SUPPORT_FEATURES@
SUPPORT_PROTOCOLS = @SUPPORT_PROTOCOLS@
USE_ARES = @USE_ARES@
USE_BEARSSL = @USE_BEARSSL@
USE_GNUTLS = @USE_GNUTLS@
USE_GNUTLS_NETTLE = @USE_GNUTLS_NETTLE@

USE_LIBRTMP = @USE_LIBRTMP@
USE_LIBSSH = @USE_LIBSSH@
USE_LIBSSH2 = @USE_LIBSSH2@
USE_MBEDTLS = @USE_MBEDTLS@
USE_MESALINK = @USE_MESALINK@
USE_NGHTTP2 = @USE_NGHTTP2@
USE_NGHTTP3 = @USE_NGHTTP3@







>







310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
STRIP = @STRIP@
SUPPORT_FEATURES = @SUPPORT_FEATURES@
SUPPORT_PROTOCOLS = @SUPPORT_PROTOCOLS@
USE_ARES = @USE_ARES@
USE_BEARSSL = @USE_BEARSSL@
USE_GNUTLS = @USE_GNUTLS@
USE_GNUTLS_NETTLE = @USE_GNUTLS_NETTLE@
USE_HYPER = @USE_HYPER@
USE_LIBRTMP = @USE_LIBRTMP@
USE_LIBSSH = @USE_LIBSSH@
USE_LIBSSH2 = @USE_LIBSSH2@
USE_MBEDTLS = @USE_MBEDTLS@
USE_MESALINK = @USE_MESALINK@
USE_NGHTTP2 = @USE_NGHTTP2@
USE_NGHTTP3 = @USE_NGHTTP3@
409
410
411
412
413
414
415

416
417
418
419
420
421
422
  config.d					\
  connect-timeout.d				\
  connect-to.d					\
  continue-at.d					\
  cookie-jar.d					\
  cookie.d					\
  create-dirs.d					\

  crlf.d crlfile.d				\
  curves.d					\
  data-ascii.d					\
  data-binary.d					\
  data-urlencode.d				\
  data.d data-raw.d				\
  delegation.d					\







>







410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
  config.d					\
  connect-timeout.d				\
  connect-to.d					\
  continue-at.d					\
  cookie-jar.d					\
  cookie.d					\
  create-dirs.d					\
  create-file-mode.d                            \
  crlf.d crlfile.d				\
  curves.d					\
  data-ascii.d					\
  data-binary.d					\
  data-urlencode.d				\
  data.d data-raw.d				\
  delegation.d					\
604
605
606
607
608
609
610

611
612
613
614
615
616
617
  trace-time.d					\
  trace.d					\
  unix-socket.d					\
  upload-file.d					\
  url.d use-ascii.d				\
  user-agent.d					\
  user.d verbose.d				\

  version.d					\
  write-out.d					\
  xattr.d

OTHERPAGES = page-footer page-header
EXTRA_DIST = $(DPAGES) MANPAGE.md gen.pl $(OTHERPAGES) CMakeLists.txt
all: all-am







>







606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
  trace-time.d					\
  trace.d					\
  unix-socket.d					\
  upload-file.d					\
  url.d use-ascii.d				\
  user-agent.d					\
  user.d verbose.d				\
  aws-sigv4.d                                   \
  version.d					\
  write-out.d					\
  xattr.d

OTHERPAGES = page-footer page-header
EXTRA_DIST = $(DPAGES) MANPAGE.md gen.pl $(OTHERPAGES) CMakeLists.txt
all: all-am
Changes to jni/curl/docs/cmdline-opts/Makefile.inc.
36
37
38
39
40
41
42

43
44
45
46
47
48
49
  config.d					\
  connect-timeout.d				\
  connect-to.d					\
  continue-at.d					\
  cookie-jar.d					\
  cookie.d					\
  create-dirs.d					\

  crlf.d crlfile.d				\
  curves.d					\
  data-ascii.d					\
  data-binary.d					\
  data-urlencode.d				\
  data.d data-raw.d				\
  delegation.d					\







>







36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
  config.d					\
  connect-timeout.d				\
  connect-to.d					\
  continue-at.d					\
  cookie-jar.d					\
  cookie.d					\
  create-dirs.d					\
  create-file-mode.d                            \
  crlf.d crlfile.d				\
  curves.d					\
  data-ascii.d					\
  data-binary.d					\
  data-urlencode.d				\
  data.d data-raw.d				\
  delegation.d					\
231
232
233
234
235
236
237

238
239
240
241
242
  trace-time.d					\
  trace.d					\
  unix-socket.d					\
  upload-file.d					\
  url.d use-ascii.d				\
  user-agent.d					\
  user.d verbose.d				\

  version.d					\
  write-out.d					\
  xattr.d

OTHERPAGES = page-footer page-header







>





232
233
234
235
236
237
238
239
240
241
242
243
244
  trace-time.d					\
  trace.d					\
  unix-socket.d					\
  upload-file.d					\
  url.d use-ascii.d				\
  user-agent.d					\
  user.d verbose.d				\
  aws-sigv4.d                                   \
  version.d					\
  write-out.d					\
  xattr.d

OTHERPAGES = page-footer page-header
Added jni/curl/docs/cmdline-opts/aws-sigv4.d.


































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
Long: aws-sigv4
Arg: <provider1[:provider2[:region[:service]]]>
Help: Use AWS V4 signature authentication
Category: auth http
Added: 7.75.0
---
Use AWS V4 signature authentication in the transfer.

The provider argument is a string that is used by the algorithm when creating
outgoing authentication headers.

The region argument is a string that points to a geographic area of
a resources collection (region-code) when the region name is omitted from
the endpoint.

The service argument is a string that points to a function provided by a cloud
(service-code) when the service name is omitted from the endpoint.
Added jni/curl/docs/cmdline-opts/create-file-mode.d.
























>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
Long: create-file-mode
Help: File mode for created files
Protocols: SFTP SCP FILE
Category: sftp scp file upload
See-also: ftp-create-dirs
Added: 7.75.0
---
When curl is used to create files remotely using one of the supported
protocols, this option allows the user to set which 'mode' to set on the file
at creation time, instead of the default 0644.

This options takes an octal number as argument.
Changes to jni/curl/docs/cmdline-opts/fail.d.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Long: fail
Short: f
Protocols: HTTP
Help: Fail silently (no output at all) on HTTP errors
Category: important http
---
Fail silently (no output at all) on server errors. This is mostly done to
better enable scripts etc to better deal with failed attempts. In normal cases
when an HTTP server fails to deliver a document, it returns an HTML document
stating so (which often also describes why and more). This flag will prevent
curl from outputting that and return error 22.

This method is not fail-safe and there are occasions where non-successful
response codes will slip through, especially when authentication is involved
(response codes 401 and 407).







|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Long: fail
Short: f
Protocols: HTTP
Help: Fail silently (no output at all) on HTTP errors
Category: important http
---
Fail silently (no output at all) on server errors. This is mostly done to
enable scripts etc to better deal with failed attempts. In normal cases
when an HTTP server fails to deliver a document, it returns an HTML document
stating so (which often also describes why and more). This flag will prevent
curl from outputting that and return error 22.

This method is not fail-safe and there are occasions where non-successful
response codes will slip through, especially when authentication is involved
(response codes 401 and 407).
Changes to jni/curl/docs/cmdline-opts/gen.pl.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#!/usr/bin/env perl
#***************************************************************************
#                                  _   _ ____  _
#  Project                     ___| | | |  _ \| |
#                             / __| | | | |_) | |
#                            | (__| |_| |  _ <| |___
#                             \___|\___/|_| \_\_____|
#
# Copyright (C) 1998 - 2020, 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 https://curl.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








|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#!/usr/bin/env perl
#***************************************************************************
#                                  _   _ ____  _
#  Project                     ___| | | |  _ \| |
#                             / __| | | | |_) | |
#                            | (__| |_| |  _ <| |___
#                             \___|\___/|_| \_\_____|
#
# Copyright (C) 1998 - 2021, 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 https://curl.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
165
166
167
168
169
170
171
172

173
174
175

176
177
178
179
180
181
182
            $category=$1;
        }
        elsif(/^Help: *(.*)/i) {
            ;
        }
        elsif(/^---/) {
            if(!$long) {
                print STDERR "WARN: no 'Long:' in $f\n";

            }
            if(!$category) {
                print STDERR "WARN: no 'Category:' in $f\n";

            }
            last;
        }
        else {
            chomp;
            print STDERR "WARN: unrecognized line in $f, ignoring:\n:'$_';"
        }







|
>


|
>







165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
            $category=$1;
        }
        elsif(/^Help: *(.*)/i) {
            ;
        }
        elsif(/^---/) {
            if(!$long) {
                print STDERR "ERROR: no 'Long:' in $f\n";
                exit 1;
            }
            if(!$category) {
                print STDERR "ERROR: no 'Category:' in $f\n";
                exit 2;
            }
            last;
        }
        else {
            chomp;
            print STDERR "WARN: unrecognized line in $f, ignoring:\n:'$_';"
        }
363
364
365
366
367
368
369
370
371



372
373
374
375
376
377
378
            $opt .= " $arg";
        }
        my $desc = $helplong{$f};
        $desc =~ s/\"/\\\"/g; # escape double quotes

        my $line = sprintf "  {\"%s\",\n   \"%s\",\n   %s},\n", $opt, $desc, $bitmask;

        if(length($opt) + length($desc) > 78) {
            print STDERR "WARN: the --$long line is too long\n";



        }
        print $line;
    }
}

sub listcats {
    my %allcats;







|
|
>
>
>







365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
            $opt .= " $arg";
        }
        my $desc = $helplong{$f};
        $desc =~ s/\"/\\\"/g; # escape double quotes

        my $line = sprintf "  {\"%s\",\n   \"%s\",\n   %s},\n", $opt, $desc, $bitmask;

        if(length($opt) > 78) {
            print STDERR "WARN: the --$long name is too long\n";
        }
        elsif(length($desc) > 78) {
            print STDERR "WARN: the --$long description is too long\n";
        }
        print $line;
    }
}

sub listcats {
    my %allcats;
Changes to jni/curl/docs/cmdline-opts/help.d.
1
2
3
4
5
6
7
8
9
10
11
12
Long: help
Arg: <category>
Short: h
Help: Get help for commands
Category: important curl
---
Usage help. This lists all commands of the <category>.
If no arg was provided, curl will display the most important
command line arguments and the list of categories.
If the argument "all" was provided, curl will display all options available.
If the argument "category" was provided, curl will display all categories and
their meanings.








|



1
2
3
4
5
6
7
8
9
10
11
12
Long: help
Arg: <category>
Short: h
Help: Get help for commands
Category: important curl
---
Usage help. This lists all commands of the <category>.
If no arg was provided, curl will display the most important
command line arguments.
If the argument "all" was provided, curl will display all options available.
If the argument "category" was provided, curl will display all categories and
their meanings.
Changes to jni/curl/docs/cmdline-opts/page-header.
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
.SH PROTOCOLS
curl supports numerous protocols, or put in URL terms: schemes. Your
particular build may not support them all.
.IP DICT
Lets you lookup words using online dictionaries.
.IP FILE
Read or write local files. curl does not support accessing file:// URL
remotely, but when running on Microsft Windows using the native UNC approach
will work.
.IP FTP(S)
curl supports the File Transfer Protocol with a lot of tweaks and levers. With
or without using TLS.
.IP GOPHER
Retrieve files.
.IP HTTP(S)







|







111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
.SH PROTOCOLS
curl supports numerous protocols, or put in URL terms: schemes. Your
particular build may not support them all.
.IP DICT
Lets you lookup words using online dictionaries.
.IP FILE
Read or write local files. curl does not support accessing file:// URL
remotely, but when running on Microsoft Windows using the native UNC approach
will work.
.IP FTP(S)
curl supports the File Transfer Protocol with a lot of tweaks and levers. With
or without using TLS.
.IP GOPHER
Retrieve files.
.IP HTTP(S)
Changes to jni/curl/docs/cmdline-opts/post301.d.
1
2
3
4
5
6
7
8
9
10
11
12
Long: post301
Help: Do not switch to GET after following a 301
Protocols: HTTP
See-also: post302 post303 location
Added: 7.17.1
Category: http post
---
Tells curl to respect RFC 7231/6.4.2 and not convert POST requests into GET
requests when following a 301 redirection. The non-RFC behaviour is ubiquitous
in web browsers, so curl does the conversion by default to maintain
consistency. However, a server may require a POST to remain a POST after such
a redirection. This option is meaningful only when using --location.








|



1
2
3
4
5
6
7
8
9
10
11
12
Long: post301
Help: Do not switch to GET after following a 301
Protocols: HTTP
See-also: post302 post303 location
Added: 7.17.1
Category: http post
---
Tells curl to respect RFC 7231/6.4.2 and not convert POST requests into GET
requests when following a 301 redirection. The non-RFC behavior is ubiquitous
in web browsers, so curl does the conversion by default to maintain
consistency. However, a server may require a POST to remain a POST after such
a redirection. This option is meaningful only when using --location.
Changes to jni/curl/docs/cmdline-opts/post302.d.
1
2
3
4
5
6
7
8
9
10
11
12
Long: post302
Help: Do not switch to GET after following a 302
Protocols: HTTP
See-also: post301 post303 location
Added: 7.19.1
Category: http post
---
Tells curl to respect RFC 7231/6.4.3 and not convert POST requests into GET
requests when following a 302 redirection. The non-RFC behaviour is ubiquitous
in web browsers, so curl does the conversion by default to maintain
consistency. However, a server may require a POST to remain a POST after such
a redirection. This option is meaningful only when using --location.








|



1
2
3
4
5
6
7
8
9
10
11
12
Long: post302
Help: Do not switch to GET after following a 302
Protocols: HTTP
See-also: post301 post303 location
Added: 7.19.1
Category: http post
---
Tells curl to respect RFC 7231/6.4.3 and not convert POST requests into GET
requests when following a 302 redirection. The non-RFC behavior is ubiquitous
in web browsers, so curl does the conversion by default to maintain
consistency. However, a server may require a POST to remain a POST after such
a redirection. This option is meaningful only when using --location.
Changes to jni/curl/docs/cmdline-opts/resolve.d.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20






21
22
23
24
25
26
27


28
Long: resolve
Arg: <host:port:addr[,addr]...>
Help: Resolve the host+port to this address
Added: 7.21.3
Category: connection
---
Provide a custom address for a specific host and port pair. Using this, you
can make the curl requests(s) use a specified address and prevent the
otherwise normally resolved address to be used. Consider it a sort of
/etc/hosts alternative provided on the command line. The port number should be
the number used for the specific protocol the host will be used for. It means
you need several entries if you want to provide address for the same host but
different ports.

By specifying '*' as host you can tell curl to resolve any host and specific
port pair to the specified address. Wildcard is resolved last so any --resolve
with a specific host and port will be used first.

The provided address set by this option will be used even if --ipv4 or --ipv6
is set to make curl use another IP version.







Support for providing the IP address within [brackets] was added in 7.57.0.

Support for providing multiple IP addresses per entry was added in 7.59.0.

Support for resolving with wildcard was added in 7.64.0.



This option can be used many times to add many host names to resolve.

|


















>
>
>
>
>
>







>
>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
Long: resolve
Arg: <[+]host:port:addr[,addr]...>
Help: Resolve the host+port to this address
Added: 7.21.3
Category: connection
---
Provide a custom address for a specific host and port pair. Using this, you
can make the curl requests(s) use a specified address and prevent the
otherwise normally resolved address to be used. Consider it a sort of
/etc/hosts alternative provided on the command line. The port number should be
the number used for the specific protocol the host will be used for. It means
you need several entries if you want to provide address for the same host but
different ports.

By specifying '*' as host you can tell curl to resolve any host and specific
port pair to the specified address. Wildcard is resolved last so any --resolve
with a specific host and port will be used first.

The provided address set by this option will be used even if --ipv4 or --ipv6
is set to make curl use another IP version.

By prefixing the host with a '+' you can make the entry time out after curl's
default timeout (1 minute). Note that this will only make sense for long
running parallel transfers with a lot of files. In such cases, if this option
is used curl will try to resolve the host as it normally would once the
timeout has expired.

Support for providing the IP address within [brackets] was added in 7.57.0.

Support for providing multiple IP addresses per entry was added in 7.59.0.

Support for resolving with wildcard was added in 7.64.0.

Support for the '+' prefix was was added in 7.75.0.

This option can be used many times to add many host names to resolve.
Changes to jni/curl/docs/cmdline-opts/retry.d.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
Long: retry
Arg: <num>
Added: 7.12.3
Help: Retry request if transient problems occur
Category: curl
---
If a transient error is returned when curl tries to perform a transfer, it
will retry this number of times before giving up. Setting the number to 0
makes curl do no retries (which is the default). Transient error means either:
a timeout, an FTP 4xx response code or an HTTP 408 or 5xx response code.

When curl is about to retry a transfer, it will first wait one second and then
for all forthcoming retries it will double the waiting time until it reaches
10 minutes which then will be the delay between the rest of the retries.  By
using --retry-delay you disable this exponential backoff algorithm. See also
--retry-max-time to limit the total time allowed for retries.










|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
Long: retry
Arg: <num>
Added: 7.12.3
Help: Retry request if transient problems occur
Category: curl
---
If a transient error is returned when curl tries to perform a transfer, it
will retry this number of times before giving up. Setting the number to 0
makes curl do no retries (which is the default). Transient error means either:
a timeout, an FTP 4xx response code or an HTTP 408, 429 or 5xx response code.

When curl is about to retry a transfer, it will first wait one second and then
for all forthcoming retries it will double the waiting time until it reaches
10 minutes which then will be the delay between the rest of the retries.  By
using --retry-delay you disable this exponential backoff algorithm. See also
--retry-max-time to limit the total time allowed for retries.

Changes to jni/curl/docs/cmdline-opts/write-out.d.
25
26
27
28
29
30
31






32
33
34
35
36
37
38

The variables available are:
.RS
.TP 15
.B content_type
The Content-Type of the requested document, if there was any.
.TP






.B filename_effective
The ultimate filename that curl writes out to. This is only meaningful if curl
is told to write to a file with the --remote-name or --output
option. It's most useful in combination with the --remote-header-name
option. (Added in 7.26.0)
.TP
.B ftp_entry_path







>
>
>
>
>
>







25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44

The variables available are:
.RS
.TP 15
.B content_type
The Content-Type of the requested document, if there was any.
.TP
.B errormsg
The error message. (Added in 7.75.0)
.TP
.B exitcode
The numerical exitcode. (Added in 7.75.0)
.TP
.B filename_effective
The ultimate filename that curl writes out to. This is only meaningful if curl
is told to write to a file with the --remote-name or --output
option. It's most useful in combination with the --remote-header-name
option. (Added in 7.26.0)
.TP
.B ftp_entry_path
70
71
72
73
74
75
76




77
78
79
80
81
82
83
.B num_headers
The number of response headers in the most recent request (restarted at each
 redirect). Note that the status line IS NOT a header. (Added in 7.73.0)
.TP
.B num_redirects
Number of redirects that were followed in the request. (Added in 7.12.3)
.TP




.B proxy_ssl_verify_result
The result of the HTTPS proxy's SSL peer certificate verification that was
requested. 0 means the verification was successful. (Added in 7.52.0)
.TP
.B redirect_url
When an HTTP request was made without --location to follow redirects (or when
--max-redir is met), this variable will show the actual URL a redirect







>
>
>
>







76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
.B num_headers
The number of response headers in the most recent request (restarted at each
 redirect). Note that the status line IS NOT a header. (Added in 7.73.0)
.TP
.B num_redirects
Number of redirects that were followed in the request. (Added in 7.12.3)
.TP
.B onerror
The rest of the output is only shown if the transfer returned a non-zero error
(Added in 7.75.0)
.TP
.B proxy_ssl_verify_result
The result of the HTTPS proxy's SSL peer certificate verification that was
requested. 0 means the verification was successful. (Added in 7.52.0)
.TP
.B redirect_url
When an HTTP request was made without --location to follow redirects (or when
--max-redir is met), this variable will show the actual URL a redirect
157
158
159
160
161
162
163






164
165
166
167
168
169
The time, in seconds, it took from the start until the first byte was just
about to be transferred. This includes time_pretransfer and also the time the
server needed to calculate the result.
.TP
.B time_total
The total time, in seconds, that the full operation lasted.
.TP






.B url_effective
The URL that was fetched last. This is most meaningful if you've told curl
to follow location: headers.
.RE
.IP
If this option is used several times, the last one will be used.







>
>
>
>
>
>






167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
The time, in seconds, it took from the start until the first byte was just
about to be transferred. This includes time_pretransfer and also the time the
server needed to calculate the result.
.TP
.B time_total
The total time, in seconds, that the full operation lasted.
.TP
.B url
The URL that was fetched. (Added in 7.75.0)
.TP
.B urlnum
The URL index number of this transfer, 0-indexed. (Added in 7.75.0)
.TP
.B url_effective
The URL that was fetched last. This is most meaningful if you've told curl
to follow location: headers.
.RE
.IP
If this option is used several times, the last one will be used.
Changes to jni/curl/docs/curl-config.1.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH curl-config 1 "November 04, 2020" "Curl 7.74.0" "curl-config manual"

.SH NAME
curl-config \- Get information about a libcurl installation
.SH SYNOPSIS
.B curl-config [options]
.SH DESCRIPTION
.B curl-config







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH curl-config 1 "November 04, 2020" "Curl 7.75.0" "curl-config manual"

.SH NAME
curl-config \- Get information about a libcurl installation
.SH SYNOPSIS
.B curl-config [options]
.SH DESCRIPTION
.B curl-config
Changes to jni/curl/docs/curl.1.
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
.\" * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
.\" * KIND, either express or implied.
.\" *
.\" **************************************************************************
.\"
.\" DO NOT EDIT. Generated by the curl project gen.pl man page generator.
.\"
.TH curl 1 "November 16, 2016" "Curl 7.74.0" "Curl Manual"

.SH NAME
curl \- transfer a URL
.SH SYNOPSIS
.B curl [options / URLs]
.SH DESCRIPTION
.B curl







|







18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
.\" * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
.\" * KIND, either express or implied.
.\" *
.\" **************************************************************************
.\"
.\" DO NOT EDIT. Generated by the curl project gen.pl man page generator.
.\"
.TH curl 1 "November 16, 2016" "Curl 7.75.0" "Curl Manual"

.SH NAME
curl \- transfer a URL
.SH SYNOPSIS
.B curl [options / URLs]
.SH DESCRIPTION
.B curl
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
.SH PROTOCOLS
curl supports numerous protocols, or put in URL terms: schemes. Your
particular build may not support them all.
.IP DICT
Lets you lookup words using online dictionaries.
.IP FILE
Read or write local files. curl does not support accessing file:// URL
remotely, but when running on Microsft Windows using the native UNC approach
will work.
.IP FTP(S)
curl supports the File Transfer Protocol with a lot of tweaks and levers. With
or without using TLS.
.IP GOPHER
Retrieve files.
.IP HTTP(S)







|







112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
.SH PROTOCOLS
curl supports numerous protocols, or put in URL terms: schemes. Your
particular build may not support them all.
.IP DICT
Lets you lookup words using online dictionaries.
.IP FILE
Read or write local files. curl does not support accessing file:// URL
remotely, but when running on Microsoft Windows using the native UNC approach
will work.
.IP FTP(S)
curl supports the File Transfer Protocol with a lot of tweaks and levers. With
or without using TLS.
.IP GOPHER
Retrieve files.
.IP HTTP(S)
234
235
236
237
238
239
240














241
242
243
244
245
246
247
Used together with \fI-u, --user\fP.

See also \fI--proxy-anyauth\fP, \fI--basic\fP and \fI--digest\fP.
.IP "-a, --append"
(FTP SFTP) When used in an upload, this makes curl append to the target file instead of
overwriting it. If the remote file doesn't exist, it will be created.  Note
that this flag is ignored by some SFTP servers (including OpenSSH).














.IP "--basic"
(HTTP) Tells curl to use HTTP Basic authentication with the remote host. This is the
default and this option is usually pointless, unless you use it to override a
previously set option that sets a different authentication method (such as
\fI--ntlm\fP, \fI--digest\fP, or \fI--negotiate\fP).

Used together with \fI-u, --user\fP.







>
>
>
>
>
>
>
>
>
>
>
>
>
>







234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
Used together with \fI-u, --user\fP.

See also \fI--proxy-anyauth\fP, \fI--basic\fP and \fI--digest\fP.
.IP "-a, --append"
(FTP SFTP) When used in an upload, this makes curl append to the target file instead of
overwriting it. If the remote file doesn't exist, it will be created.  Note
that this flag is ignored by some SFTP servers (including OpenSSH).
.IP "--aws-sigv4 <provider1[:provider2[:region[:service]]]>"
Use AWS V4 signature authentication in the transfer.

The provider argument is a string that is used by the algorithm when creating
outgoing authentication headers.

The region argument is a string that points to a geographic area of
a resources collection (region-code) when the region name is omitted from
the endpoint.

The service argument is a string that points to a function provided by a cloud
(service-code) when the service name is omitted from the endpoint.

Added in 7.75.0.
.IP "--basic"
(HTTP) Tells curl to use HTTP Basic authentication with the remote host. This is the
default and this option is usually pointless, unless you use it to override a
previously set option that sets a different authentication method (such as
\fI--ntlm\fP, \fI--digest\fP, or \fI--negotiate\fP).

Used together with \fI-u, --user\fP.
527
528
529
530
531
532
533








534
535
536
537
538
539
540
necessary local directory hierarchy as needed. This option creates the dirs
mentioned with the \fI-o, --output\fP option, nothing else. If the --output file name
uses no dir or if the dirs it mentions already exist, no dir will be created.

Created dirs are made with mode 0750 on unix style file systems.

To create remote directories when using FTP or SFTP, try \fI--ftp-create-dirs\fP.








.IP "--crlf"
(FTP SMTP) Convert LF to CRLF in upload. Useful for MVS (OS/390).

(SMTP added in 7.40.0)
.IP "--crlfile <file>"
(TLS) Provide a file using PEM format with a Certificate Revocation List that may
specify peer certificates that are to be considered revoked.







>
>
>
>
>
>
>
>







541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
necessary local directory hierarchy as needed. This option creates the dirs
mentioned with the \fI-o, --output\fP option, nothing else. If the --output file name
uses no dir or if the dirs it mentions already exist, no dir will be created.

Created dirs are made with mode 0750 on unix style file systems.

To create remote directories when using FTP or SFTP, try \fI--ftp-create-dirs\fP.
.IP "--create-file-mode"
(SFTP SCP FILE) When curl is used to create files remotely using one of the supported
protocols, this option allows the user to set which 'mode' to set on the file
at creation time, instead of the default 0644.

This options takes an octal number as argument.

See also \fI--ftp-create-dirs\fP. Added in 7.75.0.
.IP "--crlf"
(FTP SMTP) Convert LF to CRLF in upload. Useful for MVS (OS/390).

(SMTP added in 7.40.0)
.IP "--crlfile <file>"
(TLS) Provide a file using PEM format with a Certificate Revocation List that may
specify peer certificates that are to be considered revoked.
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
This option does not imply \fI-f, --fail\fP, which causes transfers to fail due to the
server's HTTP status code. You can combine the two options, however note \fI-f, --fail\fP
is not global and is therefore contained by \fI-:, --next\fP.

Added in 7.52.0.
.IP "-f, --fail"
(HTTP) Fail silently (no output at all) on server errors. This is mostly done to
better enable scripts etc to better deal with failed attempts. In normal cases
when an HTTP server fails to deliver a document, it returns an HTML document
stating so (which often also describes why and more). This flag will prevent
curl from outputting that and return error 22.

This method is not fail-safe and there are occasions where non-successful
response codes will slip through, especially when authentication is involved
(response codes 401 and 407).







|







819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
This option does not imply \fI-f, --fail\fP, which causes transfers to fail due to the
server's HTTP status code. You can combine the two options, however note \fI-f, --fail\fP
is not global and is therefore contained by \fI-:, --next\fP.

Added in 7.52.0.
.IP "-f, --fail"
(HTTP) Fail silently (no output at all) on server errors. This is mostly done to
enable scripts etc to better deal with failed attempts. In normal cases
when an HTTP server fails to deliver a document, it returns an HTML document
stating so (which often also describes why and more). This flag will prevent
curl from outputting that and return error 22.

This method is not fail-safe and there are occasions where non-successful
response codes will slip through, especially when authentication is involved
(response codes 401 and 407).
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174

This option can be used multiple times to add/replace/remove multiple headers.

See also \fI-A, --user-agent\fP and \fI-e, --referer\fP.
.IP "-h, --help <category>"
Usage help. This lists all commands of the <category>.
If no arg was provided, curl will display the most important
command line arguments and the list of categories.
If the argument "all" was provided, curl will display all options available.
If the argument "category" was provided, curl will display all categories and
their meanings.
.IP "--hostpubmd5 <md5>"
(SFTP SCP) Pass a string containing 32 hexadecimal digits. The string should
be the 128 bit MD5 checksum of the remote host's public key, curl will refuse
the connection with the host unless the md5sums match.







|







1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196

This option can be used multiple times to add/replace/remove multiple headers.

See also \fI-A, --user-agent\fP and \fI-e, --referer\fP.
.IP "-h, --help <category>"
Usage help. This lists all commands of the <category>.
If no arg was provided, curl will display the most important
command line arguments.
If the argument "all" was provided, curl will display all options available.
If the argument "category" was provided, curl will display all categories and
their meanings.
.IP "--hostpubmd5 <md5>"
(SFTP SCP) Pass a string containing 32 hexadecimal digits. The string should
be the 128 bit MD5 checksum of the remote host's public key, curl will refuse
the connection with the host unless the md5sums match.
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
  7.44.0: OpenSSL, GnuTLS, NSS and wolfSSL
  7.47.0: mbedtls
Other SSL backends not supported.

If this option is used several times, the last one will be used.
.IP "--post301"
(HTTP) Tells curl to respect RFC 7231/6.4.2 and not convert POST requests into GET
requests when following a 301 redirection. The non-RFC behaviour is ubiquitous
in web browsers, so curl does the conversion by default to maintain
consistency. However, a server may require a POST to remain a POST after such
a redirection. This option is meaningful only when using \fI-L, --location\fP.

See also \fI--post302\fP, \fI--post303\fP and \fI-L, --location\fP. Added in 7.17.1.
.IP "--post302"
(HTTP) Tells curl to respect RFC 7231/6.4.3 and not convert POST requests into GET
requests when following a 302 redirection. The non-RFC behaviour is ubiquitous
in web browsers, so curl does the conversion by default to maintain
consistency. However, a server may require a POST to remain a POST after such
a redirection. This option is meaningful only when using \fI-L, --location\fP.

See also \fI--post301\fP, \fI--post303\fP and \fI-L, --location\fP. Added in 7.19.1.
.IP "--post303"
(HTTP) Tells curl to violate RFC 7231/6.4.4 and not convert POST requests into GET







|







|







1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
  7.44.0: OpenSSL, GnuTLS, NSS and wolfSSL
  7.47.0: mbedtls
Other SSL backends not supported.

If this option is used several times, the last one will be used.
.IP "--post301"
(HTTP) Tells curl to respect RFC 7231/6.4.2 and not convert POST requests into GET
requests when following a 301 redirection. The non-RFC behavior is ubiquitous
in web browsers, so curl does the conversion by default to maintain
consistency. However, a server may require a POST to remain a POST after such
a redirection. This option is meaningful only when using \fI-L, --location\fP.

See also \fI--post302\fP, \fI--post303\fP and \fI-L, --location\fP. Added in 7.17.1.
.IP "--post302"
(HTTP) Tells curl to respect RFC 7231/6.4.3 and not convert POST requests into GET
requests when following a 302 redirection. The non-RFC behavior is ubiquitous
in web browsers, so curl does the conversion by default to maintain
consistency. However, a server may require a POST to remain a POST after such
a redirection. This option is meaningful only when using \fI-L, --location\fP.

See also \fI--post301\fP, \fI--post303\fP and \fI-L, --location\fP. Added in 7.19.1.
.IP "--post303"
(HTTP) Tells curl to violate RFC 7231/6.4.4 and not convert POST requests into GET
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304






2305
2306
2307
2308
2309
2310


2311
2312
2313
2314
2315
2316
2317
(IMAP)
Specifies a custom IMAP command to use instead of LIST. (Added in 7.30.0)

(SMTP)
Specifies a custom SMTP command to use instead of HELP or VRFY. (Added in 7.34.0)

If this option is used several times, the last one will be used.
.IP "--resolve <host:port:addr[,addr]...>"
Provide a custom address for a specific host and port pair. Using this, you
can make the curl requests(s) use a specified address and prevent the
otherwise normally resolved address to be used. Consider it a sort of
/etc/hosts alternative provided on the command line. The port number should be
the number used for the specific protocol the host will be used for. It means
you need several entries if you want to provide address for the same host but
different ports.

By specifying '*' as host you can tell curl to resolve any host and specific
port pair to the specified address. Wildcard is resolved last so any \fI--resolve\fP
with a specific host and port will be used first.

The provided address set by this option will be used even if \fI-4, --ipv4\fP or \fI-6, --ipv6\fP
is set to make curl use another IP version.







Support for providing the IP address within [brackets] was added in 7.57.0.

Support for providing multiple IP addresses per entry was added in 7.59.0.

Support for resolving with wildcard was added in 7.64.0.



This option can be used many times to add many host names to resolve.

Added in 7.21.3.
.IP "--retry-all-errors"
Retry on any error. This option is used together with \fI--retry\fP.








|














>
>
>
>
>
>






>
>







2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
(IMAP)
Specifies a custom IMAP command to use instead of LIST. (Added in 7.30.0)

(SMTP)
Specifies a custom SMTP command to use instead of HELP or VRFY. (Added in 7.34.0)

If this option is used several times, the last one will be used.
.IP "--resolve <[+]host:port:addr[,addr]...>"
Provide a custom address for a specific host and port pair. Using this, you
can make the curl requests(s) use a specified address and prevent the
otherwise normally resolved address to be used. Consider it a sort of
/etc/hosts alternative provided on the command line. The port number should be
the number used for the specific protocol the host will be used for. It means
you need several entries if you want to provide address for the same host but
different ports.

By specifying '*' as host you can tell curl to resolve any host and specific
port pair to the specified address. Wildcard is resolved last so any \fI--resolve\fP
with a specific host and port will be used first.

The provided address set by this option will be used even if \fI-4, --ipv4\fP or \fI-6, --ipv6\fP
is set to make curl use another IP version.

By prefixing the host with a '+' you can make the entry time out after curl's
default timeout (1 minute). Note that this will only make sense for long
running parallel transfers with a lot of files. In such cases, if this option
is used curl will try to resolve the host as it normally would once the
timeout has expired.

Support for providing the IP address within [brackets] was added in 7.57.0.

Support for providing multiple IP addresses per entry was added in 7.59.0.

Support for resolving with wildcard was added in 7.64.0.

Support for the '+' prefix was was added in 7.75.0.

This option can be used many times to add many host names to resolve.

Added in 7.21.3.
.IP "--retry-all-errors"
Retry on any error. This option is used together with \fI--retry\fP.

2355
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
If this option is used several times, the last one will be used.

Added in 7.12.3.
.IP "--retry <num>"
If a transient error is returned when curl tries to perform a transfer, it
will retry this number of times before giving up. Setting the number to 0
makes curl do no retries (which is the default). Transient error means either:
a timeout, an FTP 4xx response code or an HTTP 408 or 5xx response code.

When curl is about to retry a transfer, it will first wait one second and then
for all forthcoming retries it will double the waiting time until it reaches
10 minutes which then will be the delay between the rest of the retries.  By
using \fI--retry-delay\fP you disable this exponential backoff algorithm. See also
\fI--retry-max-time\fP to limit the total time allowed for retries.








|







2385
2386
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
If this option is used several times, the last one will be used.

Added in 7.12.3.
.IP "--retry <num>"
If a transient error is returned when curl tries to perform a transfer, it
will retry this number of times before giving up. Setting the number to 0
makes curl do no retries (which is the default). Transient error means either:
a timeout, an FTP 4xx response code or an HTTP 408, 429 or 5xx response code.

When curl is about to retry a transfer, it will first wait one second and then
for all forthcoming retries it will double the waiting time until it reaches
10 minutes which then will be the delay between the rest of the retries.  By
using \fI--retry-delay\fP you disable this exponential backoff algorithm. See also
\fI--retry-max-time\fP to limit the total time allowed for retries.

2964
2965
2966
2967
2968
2969
2970






2971
2972
2973
2974
2975
2976
2977

The variables available are:
.RS
.TP 15
.B content_type
The Content-Type of the requested document, if there was any.
.TP






.B filename_effective
The ultimate filename that curl writes out to. This is only meaningful if curl
is told to write to a file with the \fI-O, --remote-name\fP or \fI-o, --output\fP
option. It's most useful in combination with the \fI-J, --remote-header-name\fP
option. (Added in 7.26.0)
.TP
.B ftp_entry_path







>
>
>
>
>
>







2994
2995
2996
2997
2998
2999
3000
3001
3002
3003
3004
3005
3006
3007
3008
3009
3010
3011
3012
3013

The variables available are:
.RS
.TP 15
.B content_type
The Content-Type of the requested document, if there was any.
.TP
.B errormsg
The error message. (Added in 7.75.0)
.TP
.B exitcode
The numerical exitcode. (Added in 7.75.0)
.TP
.B filename_effective
The ultimate filename that curl writes out to. This is only meaningful if curl
is told to write to a file with the \fI-O, --remote-name\fP or \fI-o, --output\fP
option. It's most useful in combination with the \fI-J, --remote-header-name\fP
option. (Added in 7.26.0)
.TP
.B ftp_entry_path
3009
3010
3011
3012
3013
3014
3015




3016
3017
3018
3019
3020
3021
3022
.B num_headers
The number of response headers in the most recent request (restarted at each
 redirect). Note that the status line IS NOT a header. (Added in 7.73.0)
.TP
.B num_redirects
Number of redirects that were followed in the request. (Added in 7.12.3)
.TP




.B proxy_ssl_verify_result
The result of the HTTPS proxy's SSL peer certificate verification that was
requested. 0 means the verification was successful. (Added in 7.52.0)
.TP
.B redirect_url
When an HTTP request was made without \fI-L, --location\fP to follow redirects (or when
--max-redir is met), this variable will show the actual URL a redirect







>
>
>
>







3045
3046
3047
3048
3049
3050
3051
3052
3053
3054
3055
3056
3057
3058
3059
3060
3061
3062
.B num_headers
The number of response headers in the most recent request (restarted at each
 redirect). Note that the status line IS NOT a header. (Added in 7.73.0)
.TP
.B num_redirects
Number of redirects that were followed in the request. (Added in 7.12.3)
.TP
.B onerror
The rest of the output is only shown if the transfer returned a non-zero error
(Added in 7.75.0)
.TP
.B proxy_ssl_verify_result
The result of the HTTPS proxy's SSL peer certificate verification that was
requested. 0 means the verification was successful. (Added in 7.52.0)
.TP
.B redirect_url
When an HTTP request was made without \fI-L, --location\fP to follow redirects (or when
--max-redir is met), this variable will show the actual URL a redirect
3096
3097
3098
3099
3100
3101
3102






3103
3104
3105
3106
3107
3108
3109
The time, in seconds, it took from the start until the first byte was just
about to be transferred. This includes time_pretransfer and also the time the
server needed to calculate the result.
.TP
.B time_total
The total time, in seconds, that the full operation lasted.
.TP






.B url_effective
The URL that was fetched last. This is most meaningful if you've told curl
to follow location: headers.
.RE
.IP
If this option is used several times, the last one will be used.
.IP "--xattr"







>
>
>
>
>
>







3136
3137
3138
3139
3140
3141
3142
3143
3144
3145
3146
3147
3148
3149
3150
3151
3152
3153
3154
3155
The time, in seconds, it took from the start until the first byte was just
about to be transferred. This includes time_pretransfer and also the time the
server needed to calculate the result.
.TP
.B time_total
The total time, in seconds, that the full operation lasted.
.TP
.B url
The URL that was fetched. (Added in 7.75.0)
.TP
.B urlnum
The URL index number of this transfer, 0-indexed. (Added in 7.75.0)
.TP
.B url_effective
The URL that was fetched last. This is most meaningful if you've told curl
to follow location: headers.
.RE
.IP
If this option is used several times, the last one will be used.
.IP "--xattr"
Changes to jni/curl/docs/examples/Makefile.am.
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
# KIND, either express or implied.
#
###########################################################################

AUTOMAKE_OPTIONS = foreign nostdinc

EXTRA_DIST = README.md Makefile.example Makefile.inc Makefile.m32 \
  Makefile.netware makefile.dj $(COMPLICATED_EXAMPLES)

# Specify our include paths here, and do it relative to $(top_srcdir) and
# $(top_builddir), to ensure that these paths which belong to the library
# being currently built and tested are searched before the library which
# might possibly already be installed in the system.
#
# $(top_srcdir)/include is for libcurl's external include files







|







19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
# KIND, either express or implied.
#
###########################################################################

AUTOMAKE_OPTIONS = foreign nostdinc

EXTRA_DIST = README.md Makefile.example Makefile.inc Makefile.m32 \
  Makefile.netware makefile.dj $(COMPLICATED_EXAMPLES) .checksrc

# Specify our include paths here, and do it relative to $(top_srcdir) and
# $(top_builddir), to ensure that these paths which belong to the library
# being currently built and tested are searched before the library which
# might possibly already be installed in the system.
#
# $(top_srcdir)/include is for libcurl's external include files
Changes to jni/curl/docs/examples/Makefile.in.
1128
1129
1130
1131
1132
1133
1134

1135
1136
1137
1138
1139
1140
1141
STRIP = @STRIP@
SUPPORT_FEATURES = @SUPPORT_FEATURES@
SUPPORT_PROTOCOLS = @SUPPORT_PROTOCOLS@
USE_ARES = @USE_ARES@
USE_BEARSSL = @USE_BEARSSL@
USE_GNUTLS = @USE_GNUTLS@
USE_GNUTLS_NETTLE = @USE_GNUTLS_NETTLE@

USE_LIBRTMP = @USE_LIBRTMP@
USE_LIBSSH = @USE_LIBSSH@
USE_LIBSSH2 = @USE_LIBSSH2@
USE_MBEDTLS = @USE_MBEDTLS@
USE_MESALINK = @USE_MESALINK@
USE_NGHTTP2 = @USE_NGHTTP2@
USE_NGHTTP3 = @USE_NGHTTP3@







>







1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
STRIP = @STRIP@
SUPPORT_FEATURES = @SUPPORT_FEATURES@
SUPPORT_PROTOCOLS = @SUPPORT_PROTOCOLS@
USE_ARES = @USE_ARES@
USE_BEARSSL = @USE_BEARSSL@
USE_GNUTLS = @USE_GNUTLS@
USE_GNUTLS_NETTLE = @USE_GNUTLS_NETTLE@
USE_HYPER = @USE_HYPER@
USE_LIBRTMP = @USE_LIBRTMP@
USE_LIBSSH = @USE_LIBSSH@
USE_LIBSSH2 = @USE_LIBSSH2@
USE_MBEDTLS = @USE_MBEDTLS@
USE_MESALINK = @USE_MESALINK@
USE_NGHTTP2 = @USE_NGHTTP2@
USE_NGHTTP3 = @USE_NGHTTP3@
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
sysconfdir = @sysconfdir@
target_alias = @target_alias@
top_build_prefix = @top_build_prefix@
top_builddir = @top_builddir@
top_srcdir = @top_srcdir@
AUTOMAKE_OPTIONS = foreign nostdinc
EXTRA_DIST = README.md Makefile.example Makefile.inc Makefile.m32 \
  Makefile.netware makefile.dj $(COMPLICATED_EXAMPLES)


# Specify our include paths here, and do it relative to $(top_srcdir) and
# $(top_builddir), to ensure that these paths which belong to the library
# being currently built and tested are searched before the library which
# might possibly already be installed in the system.
#







|







1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
sysconfdir = @sysconfdir@
target_alias = @target_alias@
top_build_prefix = @top_build_prefix@
top_builddir = @top_builddir@
top_srcdir = @top_srcdir@
AUTOMAKE_OPTIONS = foreign nostdinc
EXTRA_DIST = README.md Makefile.example Makefile.inc Makefile.m32 \
  Makefile.netware makefile.dj $(COMPLICATED_EXAMPLES) .checksrc


# Specify our include paths here, and do it relative to $(top_srcdir) and
# $(top_builddir), to ensure that these paths which belong to the library
# being currently built and tested are searched before the library which
# might possibly already be installed in the system.
#
Changes to jni/curl/docs/examples/anyauthput.c.
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
  default: /* ignore unknown commands */
    return CURLIOE_UNKNOWNCMD;
  }
  return CURLIOE_OK; /* success! */
}

/* read callback function, fread() look alike */
static size_t read_callback(void *ptr, size_t size, size_t nmemb, void *stream)
{
  ssize_t retcode;
  curl_off_t nread;

  int *fdp = (int *)stream;
  int fd = *fdp;








|







74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
  default: /* ignore unknown commands */
    return CURLIOE_UNKNOWNCMD;
  }
  return CURLIOE_OK; /* success! */
}

/* read callback function, fread() look alike */
static size_t read_callback(char *ptr, size_t size, size_t nmemb, void *stream)
{
  ssize_t retcode;
  curl_off_t nread;

  int *fdp = (int *)stream;
  int fd = *fdp;

Changes to jni/curl/docs/examples/cacertinmem.c.
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141

  curl_global_init(CURL_GLOBAL_ALL);
  ch = curl_easy_init();
  curl_easy_setopt(ch, CURLOPT_VERBOSE, 0L);
  curl_easy_setopt(ch, CURLOPT_HEADER, 0L);
  curl_easy_setopt(ch, CURLOPT_NOPROGRESS, 1L);
  curl_easy_setopt(ch, CURLOPT_NOSIGNAL, 1L);
  curl_easy_setopt(ch, CURLOPT_WRITEFUNCTION, *writefunction);
  curl_easy_setopt(ch, CURLOPT_WRITEDATA, stdout);
  curl_easy_setopt(ch, CURLOPT_HEADERFUNCTION, *writefunction);
  curl_easy_setopt(ch, CURLOPT_HEADERDATA, stderr);
  curl_easy_setopt(ch, CURLOPT_SSLCERTTYPE, "PEM");
  curl_easy_setopt(ch, CURLOPT_SSL_VERIFYPEER, 1L);
  curl_easy_setopt(ch, CURLOPT_URL, "https://www.example.com/");

  /* Turn off the default CA locations, otherwise libcurl will load CA
   * certificates from the locations that were detected/specified at







|

|







125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141

  curl_global_init(CURL_GLOBAL_ALL);
  ch = curl_easy_init();
  curl_easy_setopt(ch, CURLOPT_VERBOSE, 0L);
  curl_easy_setopt(ch, CURLOPT_HEADER, 0L);
  curl_easy_setopt(ch, CURLOPT_NOPROGRESS, 1L);
  curl_easy_setopt(ch, CURLOPT_NOSIGNAL, 1L);
  curl_easy_setopt(ch, CURLOPT_WRITEFUNCTION, writefunction);
  curl_easy_setopt(ch, CURLOPT_WRITEDATA, stdout);
  curl_easy_setopt(ch, CURLOPT_HEADERFUNCTION, writefunction);
  curl_easy_setopt(ch, CURLOPT_HEADERDATA, stderr);
  curl_easy_setopt(ch, CURLOPT_SSLCERTTYPE, "PEM");
  curl_easy_setopt(ch, CURLOPT_SSL_VERIFYPEER, 1L);
  curl_easy_setopt(ch, CURLOPT_URL, "https://www.example.com/");

  /* Turn off the default CA locations, otherwise libcurl will load CA
   * certificates from the locations that were detected/specified at
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
   */
  curl_easy_setopt(ch, CURLOPT_FRESH_CONNECT, 1L);

  /* second try: retrieve page using cacerts' certificate -> will succeed
   * load the certificate by installing a function doing the necessary
   * "modifications" to the SSL CONTEXT just before link init
   */
  curl_easy_setopt(ch, CURLOPT_SSL_CTX_FUNCTION, *sslctx_function);
  rv = curl_easy_perform(ch);
  if(rv == CURLE_OK)
    printf("*** transfer succeeded ***\n");
  else
    printf("*** transfer failed ***\n");

  curl_easy_cleanup(ch);
  curl_global_cleanup();
  return rv;
}







|










164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
   */
  curl_easy_setopt(ch, CURLOPT_FRESH_CONNECT, 1L);

  /* second try: retrieve page using cacerts' certificate -> will succeed
   * load the certificate by installing a function doing the necessary
   * "modifications" to the SSL CONTEXT just before link init
   */
  curl_easy_setopt(ch, CURLOPT_SSL_CTX_FUNCTION, sslctx_function);
  rv = curl_easy_perform(ch);
  if(rv == CURLE_OK)
    printf("*** transfer succeeded ***\n");
  else
    printf("*** transfer failed ***\n");

  curl_easy_cleanup(ch);
  curl_global_cleanup();
  return rv;
}
Changes to jni/curl/docs/examples/curlgtk.c.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
/*****************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 *  Copyright (c) 2000 - 2019 David Odin (aka DindinX) for MandrakeSoft
 */
/* <DESC>
 * use the libcurl in a gtk-threaded application
 * </DESC>
 */

#include <stdio.h>
#include <gtk/gtk.h>

#include <curl/curl.h>

GtkWidget *Bar;

size_t my_write_func(void *ptr, size_t size, size_t nmemb, FILE *stream)
{
  return fwrite(ptr, size, nmemb, stream);
}

size_t my_read_func(void *ptr, size_t size, size_t nmemb, FILE *stream)
{
  return fread(ptr, size, nmemb, stream);
}

int my_progress_func(GtkWidget *bar,
                     double t, /* dltotal */
                     double d, /* dlnow */
                     double ultotal,
                     double ulnow)
{
/*  printf("%d / %d (%g %%)\n", d, t, d*100.0/t);*/
  gdk_threads_enter();
  gtk_progress_set_value(GTK_PROGRESS(bar), d*100.0/t);
  gdk_threads_leave();
  return 0;
}

void *my_thread(void *ptr)
{
  CURL *curl;

  curl = curl_easy_init();
  if(curl) {
    gchar *url = ptr;
    const char *filename = "test.curl";







|













|




|




|
|
|
|
|








|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
/*****************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (c) 2000 - 2020 David Odin (aka DindinX) for MandrakeSoft
 */
/* <DESC>
 * use the libcurl in a gtk-threaded application
 * </DESC>
 */

#include <stdio.h>
#include <gtk/gtk.h>

#include <curl/curl.h>

GtkWidget *Bar;

static size_t my_write_func(void *ptr, size_t size, size_t nmemb, FILE *stream)
{
  return fwrite(ptr, size, nmemb, stream);
}

static size_t my_read_func(char *ptr, size_t size, size_t nmemb, FILE *stream)
{
  return fread(ptr, size, nmemb, stream);
}

static int my_progress_func(GtkWidget *bar,
                            double t, /* dltotal */
                            double d, /* dlnow */
                            double ultotal,
                            double ulnow)
{
/*  printf("%d / %d (%g %%)\n", d, t, d*100.0/t);*/
  gdk_threads_enter();
  gtk_progress_set_value(GTK_PROGRESS(bar), d*100.0/t);
  gdk_threads_leave();
  return 0;
}

static void *my_thread(void *ptr)
{
  CURL *curl;

  curl = curl_easy_init();
  if(curl) {
    gchar *url = ptr;
    const char *filename = "test.curl";
93
94
95
96
97
98
99
100
101
102
103
104
105
106
  adj = (GtkAdjustment*)gtk_adjustment_new(0, 0, 100, 0, 0, 0);
  Bar = gtk_progress_bar_new_with_adjustment(adj);
  gtk_container_add(GTK_CONTAINER(Frame2), Bar);
  gtk_widget_show_all(Window);

  if(!g_thread_create(&my_thread, argv[1], FALSE, NULL) != 0)
    g_warning("can't create the thread");


  gdk_threads_enter();
  gtk_main();
  gdk_threads_leave();
  return 0;
}







<






93
94
95
96
97
98
99

100
101
102
103
104
105
  adj = (GtkAdjustment*)gtk_adjustment_new(0, 0, 100, 0, 0, 0);
  Bar = gtk_progress_bar_new_with_adjustment(adj);
  gtk_container_add(GTK_CONTAINER(Frame2), Bar);
  gtk_widget_show_all(Window);

  if(!g_thread_create(&my_thread, argv[1], FALSE, NULL) != 0)
    g_warning("can't create the thread");


  gdk_threads_enter();
  gtk_main();
  gdk_threads_leave();
  return 0;
}
Changes to jni/curl/docs/examples/ftpupload.c.
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
#define REMOTE_URL      "ftp://example.com/"  UPLOAD_FILE_AS
#define RENAME_FILE_TO  "renamed-and-fine.txt"

/* NOTE: if you want this example to work on Windows with libcurl as a
   DLL, you MUST also provide a read callback with CURLOPT_READFUNCTION.
   Failing to do so will give you a crash since a DLL may not use the
   variable's memory when passed in to it from an app like this. */
static size_t read_callback(void *ptr, size_t size, size_t nmemb, void *stream)
{
  curl_off_t nread;
  /* in real-world cases, this would probably get this data differently
     as this fread() stuff is exactly what the library already would do
     by default internally */
  size_t retcode = fread(ptr, size, nmemb, stream);








|







44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
#define REMOTE_URL      "ftp://example.com/"  UPLOAD_FILE_AS
#define RENAME_FILE_TO  "renamed-and-fine.txt"

/* NOTE: if you want this example to work on Windows with libcurl as a
   DLL, you MUST also provide a read callback with CURLOPT_READFUNCTION.
   Failing to do so will give you a crash since a DLL may not use the
   variable's memory when passed in to it from an app like this. */
static size_t read_callback(char *ptr, size_t size, size_t nmemb, void *stream)
{
  curl_off_t nread;
  /* in real-world cases, this would probably get this data differently
     as this fread() stuff is exactly what the library already would do
     by default internally */
  size_t retcode = fread(ptr, size, nmemb, stream);

Changes to jni/curl/docs/examples/ftpuploadfrommem.c.
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
  "lorem.";

struct WriteThis {
  const char *readptr;
  size_t sizeleft;
};

static size_t read_callback(void *ptr, size_t size, size_t nmemb, void *userp)
{
  struct WriteThis *upload = (struct WriteThis *)userp;
  size_t max = size*nmemb;

  if(max < 1)
    return 0;








|







39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
  "lorem.";

struct WriteThis {
  const char *readptr;
  size_t sizeleft;
};

static size_t read_callback(char *ptr, size_t size, size_t nmemb, void *userp)
{
  struct WriteThis *upload = (struct WriteThis *)userp;
  size_t max = size*nmemb;

  if(max < 1)
    return 0;

Changes to jni/curl/docs/examples/ftpuploadresume.c.
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
{
  (void)ptr;
  (void)stream;
  return size * nmemb;
}

/* read data to upload */
static size_t readfunc(void *ptr, size_t size, size_t nmemb, void *stream)
{
  FILE *f = stream;
  size_t n;

  if(ferror(f))
    return CURL_READFUNC_ABORT;








|







47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
{
  (void)ptr;
  (void)stream;
  return size * nmemb;
}

/* read data to upload */
static size_t readfunc(char *ptr, size_t size, size_t nmemb, void *stream)
{
  FILE *f = stream;
  size_t n;

  if(ferror(f))
    return CURL_READFUNC_ABORT;

Changes to jni/curl/docs/examples/http2-pushinmemory.c.
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173


    /*
     * When doing server push, libcurl itself created and added one or more
     * easy handles but *we* need to clean them up when they are done.
     */
    do {
      int msgq = 0;;
      m = curl_multi_info_read(multi, &msgq);
      if(m && (m->msg == CURLMSG_DONE)) {
        CURL *e = m->easy_handle;
        transfers--;
        curl_multi_remove_handle(multi, e);
        curl_easy_cleanup(e);
      }







|







159
160
161
162
163
164
165
166
167
168
169
170
171
172
173


    /*
     * When doing server push, libcurl itself created and added one or more
     * easy handles but *we* need to clean them up when they are done.
     */
    do {
      int msgq = 0;
      m = curl_multi_info_read(multi, &msgq);
      if(m && (m->msg == CURLMSG_DONE)) {
        CURL *e = m->easy_handle;
        transfers--;
        curl_multi_remove_handle(multi, e);
        curl_easy_cleanup(e);
      }
Changes to jni/curl/docs/examples/http2-serverpush.c.
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
    /*
     * A little caution when doing server push is that libcurl itself has
     * created and added one or more easy handles but we need to clean them up
     * when we are done.
     */

    do {
      int msgq = 0;;
      m = curl_multi_info_read(multi_handle, &msgq);
      if(m && (m->msg == CURLMSG_DONE)) {
        CURL *e = m->easy_handle;
        transfers--;
        curl_multi_remove_handle(multi_handle, e);
        curl_easy_cleanup(e);
      }







|







311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
    /*
     * A little caution when doing server push is that libcurl itself has
     * created and added one or more easy handles but we need to clean them up
     * when we are done.
     */

    do {
      int msgq = 0;
      m = curl_multi_info_read(multi_handle, &msgq);
      if(m && (m->msg == CURLMSG_DONE)) {
        CURL *e = m->easy_handle;
        transfers--;
        curl_multi_remove_handle(multi_handle, e);
        curl_easy_cleanup(e);
      }
Changes to jni/curl/docs/examples/http2-upload.c.
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
    break;
  }

  dump(text, num, (unsigned char *)data, size, 1);
  return 0;
}

static size_t read_callback(void *ptr, size_t size, size_t nmemb, void *userp)
{
  struct input *i = userp;
  size_t retcode = fread(ptr, size, nmemb, i->in);
  i->bytes_read += retcode;
  return retcode;
}








|







155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
    break;
  }

  dump(text, num, (unsigned char *)data, size, 1);
  return 0;
}

static size_t read_callback(char *ptr, size_t size, size_t nmemb, void *userp)
{
  struct input *i = userp;
  size_t retcode = fread(ptr, size, nmemb, i->in);
  i->bytes_read += retcode;
  return retcode;
}

Changes to jni/curl/docs/examples/httpput.c.
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
 *
 * This example also uses its own read callback.
 *
 * Here's an article on how to setup a PUT handler for Apache:
 * http://www.apacheweek.com/features/put
 */

static size_t read_callback(void *ptr, size_t size, size_t nmemb, void *stream)
{
  size_t retcode;
  curl_off_t nread;

  /* in real-world cases, this would probably get this data differently
     as this fread() stuff is exactly what the library already would do
     by default internally */







|







34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
 *
 * This example also uses its own read callback.
 *
 * Here's an article on how to setup a PUT handler for Apache:
 * http://www.apacheweek.com/features/put
 */

static size_t read_callback(char *ptr, size_t size, size_t nmemb, void *stream)
{
  size_t retcode;
  curl_off_t nread;

  /* in real-world cases, this would probably get this data differently
     as this fread() stuff is exactly what the library already would do
     by default internally */
Changes to jni/curl/docs/examples/imap-append.c.
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
  NULL
};

struct upload_status {
  int lines_read;
};

static size_t payload_source(void *ptr, size_t size, size_t nmemb, void *userp)
{
  struct upload_status *upload_ctx = (struct upload_status *)userp;
  const char *data;

  if((size == 0) || (nmemb == 0) || ((size*nmemb) < 1)) {
    return 0;
  }







|







55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
  NULL
};

struct upload_status {
  int lines_read;
};

static size_t payload_source(char *ptr, size_t size, size_t nmemb, void *userp)
{
  struct upload_status *upload_ctx = (struct upload_status *)userp;
  const char *data;

  if((size == 0) || (nmemb == 0) || ((size*nmemb) < 1)) {
    return 0;
  }
Changes to jni/curl/docs/examples/multi-single.c.
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50

#ifdef _WIN32
#define WAITMS(x) Sleep(x)
#else
/* Portable sleep for platforms other than Windows. */
#define WAITMS(x)                               \
  struct timeval wait = { 0, (x) * 1000 };      \
  (void)select(0, NULL, NULL, NULL, &wait);
#endif

/*
 * Simply download a HTTP file.
 */
int main(void)
{







|







36
37
38
39
40
41
42
43
44
45
46
47
48
49
50

#ifdef _WIN32
#define WAITMS(x) Sleep(x)
#else
/* Portable sleep for platforms other than Windows. */
#define WAITMS(x)                               \
  struct timeval wait = { 0, (x) * 1000 };      \
  (void)select(0, NULL, NULL, NULL, &wait)
#endif

/*
 * Simply download a HTTP file.
 */
int main(void)
{
Changes to jni/curl/docs/examples/post-callback.c.
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
  "rhoncus ipsum.";

struct WriteThis {
  const char *readptr;
  size_t sizeleft;
};

static size_t read_callback(void *dest, size_t size, size_t nmemb, void *userp)
{
  struct WriteThis *wt = (struct WriteThis *)userp;
  size_t buffer_size = size*nmemb;

  if(wt->sizeleft) {
    /* copy as much as possible from the source to the destination */
    size_t copy_this_much = wt->sizeleft;







|







37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
  "rhoncus ipsum.";

struct WriteThis {
  const char *readptr;
  size_t sizeleft;
};

static size_t read_callback(char *dest, size_t size, size_t nmemb, void *userp)
{
  struct WriteThis *wt = (struct WriteThis *)userp;
  size_t buffer_size = size*nmemb;

  if(wt->sizeleft) {
    /* copy as much as possible from the source to the destination */
    size_t copy_this_much = wt->sizeleft;
Changes to jni/curl/docs/examples/rtsp.c.
57
58
59
60
61
62
63
64

65
66
67
68

69
70

71
72
73
74
75
76
77
78
79
80
81
#endif

#include <curl/curl.h>

#define VERSION_STR  "V1.0"

/* error handling macros */
#define my_curl_easy_setopt(A, B, C)                             \

  res = curl_easy_setopt((A), (B), (C));                         \
  if(res != CURLE_OK)                                            \
    fprintf(stderr, "curl_easy_setopt(%s, %s, %s) failed: %d\n", \
            #A, #B, #C, res);


#define my_curl_easy_perform(A)                                     \

  res = curl_easy_perform(A);                                       \
  if(res != CURLE_OK)                                               \
    fprintf(stderr, "curl_easy_perform(%s) failed: %d\n", #A, res);


/* send RTSP OPTIONS request */
static void rtsp_options(CURL *curl, const char *uri)
{
  CURLcode res = CURLE_OK;
  printf("\nRTSP: OPTIONS %s\n", uri);
  my_curl_easy_setopt(curl, CURLOPT_RTSP_STREAM_URI, uri);







|
>
|
|
|
|
>

|
>
|
|
|
|







57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
#endif

#include <curl/curl.h>

#define VERSION_STR  "V1.0"

/* error handling macros */
#define my_curl_easy_setopt(A, B, C)                               \
  do {                                                             \
    res = curl_easy_setopt((A), (B), (C));                         \
    if(res != CURLE_OK)                                            \
      fprintf(stderr, "curl_easy_setopt(%s, %s, %s) failed: %d\n", \
              #A, #B, #C, res);                                    \
  } while(0)

#define my_curl_easy_perform(A)                                         \
  do {                                                                  \
    res = curl_easy_perform(A);                                         \
    if(res != CURLE_OK)                                                 \
      fprintf(stderr, "curl_easy_perform(%s) failed: %d\n", #A, res);   \
  } while(0)

/* send RTSP OPTIONS request */
static void rtsp_options(CURL *curl, const char *uri)
{
  CURLcode res = CURLE_OK;
  printf("\nRTSP: OPTIONS %s\n", uri);
  my_curl_easy_setopt(curl, CURLOPT_RTSP_STREAM_URI, uri);
Changes to jni/curl/docs/examples/sftpuploadresume.c.
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
 */

#include <stdlib.h>
#include <stdio.h>
#include <curl/curl.h>

/* read data to upload */
static size_t readfunc(void *ptr, size_t size, size_t nmemb, void *stream)
{
  FILE *f = (FILE *)stream;
  size_t n;

  if(ferror(f))
    return CURL_READFUNC_ABORT;








|







25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
 */

#include <stdlib.h>
#include <stdio.h>
#include <curl/curl.h>

/* read data to upload */
static size_t readfunc(char *ptr, size_t size, size_t nmemb, void *stream)
{
  FILE *f = (FILE *)stream;
  size_t n;

  if(ferror(f))
    return CURL_READFUNC_ABORT;

Changes to jni/curl/docs/examples/smtp-authzid.c.
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
  NULL
};

struct upload_status {
  int lines_read;
};

static size_t payload_source(void *ptr, size_t size, size_t nmemb, void *userp)
{
  struct upload_status *upload_ctx = (struct upload_status *)userp;
  const char *data;

  if((size == 0) || (nmemb == 0) || ((size*nmemb) < 1)) {
    return 0;
  }







|







63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
  NULL
};

struct upload_status {
  int lines_read;
};

static size_t payload_source(char *ptr, size_t size, size_t nmemb, void *userp)
{
  struct upload_status *upload_ctx = (struct upload_status *)userp;
  const char *data;

  if((size == 0) || (nmemb == 0) || ((size*nmemb) < 1)) {
    return 0;
  }
Changes to jni/curl/docs/examples/smtp-mail.c.
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
  NULL
};

struct upload_status {
  int lines_read;
};

static size_t payload_source(void *ptr, size_t size, size_t nmemb, void *userp)
{
  struct upload_status *upload_ctx = (struct upload_status *)userp;
  const char *data;

  if((size == 0) || (nmemb == 0) || ((size*nmemb) < 1)) {
    return 0;
  }







|







60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
  NULL
};

struct upload_status {
  int lines_read;
};

static size_t payload_source(char *ptr, size_t size, size_t nmemb, void *userp)
{
  struct upload_status *upload_ctx = (struct upload_status *)userp;
  const char *data;

  if((size == 0) || (nmemb == 0) || ((size*nmemb) < 1)) {
    return 0;
  }
Changes to jni/curl/docs/examples/smtp-multi.c.
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
  NULL
};

struct upload_status {
  int lines_read;
};

static size_t payload_source(void *ptr, size_t size, size_t nmemb, void *userp)
{
  struct upload_status *upload_ctx = (struct upload_status *)userp;
  const char *data;

  if((size == 0) || (nmemb == 0) || ((size*nmemb) < 1)) {
    return 0;
  }







|







57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
  NULL
};

struct upload_status {
  int lines_read;
};

static size_t payload_source(char *ptr, size_t size, size_t nmemb, void *userp)
{
  struct upload_status *upload_ctx = (struct upload_status *)userp;
  const char *data;

  if((size == 0) || (nmemb == 0) || ((size*nmemb) < 1)) {
    return 0;
  }
Changes to jni/curl/docs/examples/smtp-ssl.c.
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
  NULL
};

struct upload_status {
  int lines_read;
};

static size_t payload_source(void *ptr, size_t size, size_t nmemb, void *userp)
{
  struct upload_status *upload_ctx = (struct upload_status *)userp;
  const char *data;

  if((size == 0) || (nmemb == 0) || ((size*nmemb) < 1)) {
    return 0;
  }







|







57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
  NULL
};

struct upload_status {
  int lines_read;
};

static size_t payload_source(char *ptr, size_t size, size_t nmemb, void *userp)
{
  struct upload_status *upload_ctx = (struct upload_status *)userp;
  const char *data;

  if((size == 0) || (nmemb == 0) || ((size*nmemb) < 1)) {
    return 0;
  }
Changes to jni/curl/docs/examples/smtp-tls.c.
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
  NULL
};

struct upload_status {
  int lines_read;
};

static size_t payload_source(void *ptr, size_t size, size_t nmemb, void *userp)
{
  struct upload_status *upload_ctx = (struct upload_status *)userp;
  const char *data;

  if((size == 0) || (nmemb == 0) || ((size*nmemb) < 1)) {
    return 0;
  }







|







57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
  NULL
};

struct upload_status {
  int lines_read;
};

static size_t payload_source(char *ptr, size_t size, size_t nmemb, void *userp)
{
  struct upload_status *upload_ctx = (struct upload_status *)userp;
  const char *data;

  if((size == 0) || (nmemb == 0) || ((size*nmemb) < 1)) {
    return 0;
  }
Changes to jni/curl/docs/examples/synctime.c.
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209

  if(strlen(proxy_user_password) > 0)
    curl_easy_setopt(curl, CURLOPT_PROXYUSERPWD, proxy_user_password);

#ifdef SYNCTIME_UA
  curl_easy_setopt(curl, CURLOPT_USERAGENT, SYNCTIME_UA);
#endif
  curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, *SyncTime_CURL_WriteOutput);
  curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION, *SyncTime_CURL_WriteHeader);
}

int SyncTime_CURL_Fetch(CURL *curl, char *URL_Str, char *OutFileName,
                        int HttpGetBody)
{
  FILE *outfile;
  CURLcode res;







|
|







194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209

  if(strlen(proxy_user_password) > 0)
    curl_easy_setopt(curl, CURLOPT_PROXYUSERPWD, proxy_user_password);

#ifdef SYNCTIME_UA
  curl_easy_setopt(curl, CURLOPT_USERAGENT, SYNCTIME_UA);
#endif
  curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, SyncTime_CURL_WriteOutput);
  curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION, SyncTime_CURL_WriteHeader);
}

int SyncTime_CURL_Fetch(CURL *curl, char *URL_Str, char *OutFileName,
                        int HttpGetBody)
{
  FILE *outfile;
  CURLcode res;
Changes to jni/curl/docs/examples/usercertinmem.c.
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
    printf("*** transfer failed ***\n");
  }

  /* second try: retrieve page using user certificate and key -> will succeed
   * load the certificate and key by installing a function doing the necessary
   * "modifications" to the SSL CONTEXT just before link init
   */
  curl_easy_setopt(ch, CURLOPT_SSL_CTX_FUNCTION, *sslctx_function);
  rv = curl_easy_perform(ch);
  if(rv == CURLE_OK) {
    printf("*** transfer succeeded ***\n");
  }
  else {
    printf("*** transfer failed ***\n");
  }







|







207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
    printf("*** transfer failed ***\n");
  }

  /* second try: retrieve page using user certificate and key -> will succeed
   * load the certificate and key by installing a function doing the necessary
   * "modifications" to the SSL CONTEXT just before link init
   */
  curl_easy_setopt(ch, CURLOPT_SSL_CTX_FUNCTION, sslctx_function);
  rv = curl_easy_perform(ch);
  if(rv == CURLE_OK) {
    printf("*** transfer succeeded ***\n");
  }
  else {
    printf("*** transfer failed ***\n");
  }
Changes to jni/curl/docs/libcurl/Makefile.in.
582
583
584
585
586
587
588

589
590
591
592
593
594
595
STRIP = @STRIP@
SUPPORT_FEATURES = @SUPPORT_FEATURES@
SUPPORT_PROTOCOLS = @SUPPORT_PROTOCOLS@
USE_ARES = @USE_ARES@
USE_BEARSSL = @USE_BEARSSL@
USE_GNUTLS = @USE_GNUTLS@
USE_GNUTLS_NETTLE = @USE_GNUTLS_NETTLE@

USE_LIBRTMP = @USE_LIBRTMP@
USE_LIBSSH = @USE_LIBSSH@
USE_LIBSSH2 = @USE_LIBSSH2@
USE_MBEDTLS = @USE_MBEDTLS@
USE_MESALINK = @USE_MESALINK@
USE_NGHTTP2 = @USE_NGHTTP2@
USE_NGHTTP3 = @USE_NGHTTP3@







>







582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
STRIP = @STRIP@
SUPPORT_FEATURES = @SUPPORT_FEATURES@
SUPPORT_PROTOCOLS = @SUPPORT_PROTOCOLS@
USE_ARES = @USE_ARES@
USE_BEARSSL = @USE_BEARSSL@
USE_GNUTLS = @USE_GNUTLS@
USE_GNUTLS_NETTLE = @USE_GNUTLS_NETTLE@
USE_HYPER = @USE_HYPER@
USE_LIBRTMP = @USE_LIBRTMP@
USE_LIBSSH = @USE_LIBSSH@
USE_LIBSSH2 = @USE_LIBSSH2@
USE_MBEDTLS = @USE_MBEDTLS@
USE_MESALINK = @USE_MESALINK@
USE_NGHTTP2 = @USE_NGHTTP2@
USE_NGHTTP3 = @USE_NGHTTP3@
Changes to jni/curl/docs/libcurl/curl_easy_cleanup.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH curl_easy_cleanup 3 "November 04, 2020" "libcurl 7.74.0" "libcurl Manual"

.SH NAME
curl_easy_cleanup - End a libcurl easy handle
.SH SYNOPSIS
.B #include <curl/curl.h>

.BI "void curl_easy_cleanup(CURL *" handle ");"







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH curl_easy_cleanup 3 "November 04, 2020" "libcurl 7.75.0" "libcurl Manual"

.SH NAME
curl_easy_cleanup - End a libcurl easy handle
.SH SYNOPSIS
.B #include <curl/curl.h>

.BI "void curl_easy_cleanup(CURL *" handle ");"
Changes to jni/curl/docs/libcurl/curl_easy_duphandle.3.
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
.\" * 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.
.\" *
.\" **************************************************************************
.TH curl_easy_duphandle 3 "November 05, 2020" "libcurl 7.74.0" "libcurl Manual"

.SH NAME
curl_easy_duphandle - Clone a libcurl session handle
.SH SYNOPSIS
.B #include <curl/curl.h>

.BI "CURL *curl_easy_duphandle(CURL *"handle ");"







|







15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
.\" * 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.
.\" *
.\" **************************************************************************
.TH curl_easy_duphandle 3 "November 05, 2020" "libcurl 7.75.0" "libcurl Manual"

.SH NAME
curl_easy_duphandle - Clone a libcurl session handle
.SH SYNOPSIS
.B #include <curl/curl.h>

.BI "CURL *curl_easy_duphandle(CURL *"handle ");"
Changes to jni/curl/docs/libcurl/curl_easy_escape.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH curl_easy_escape 3 "November 09, 2020" "libcurl 7.74.0" "libcurl Manual"

.SH NAME
curl_easy_escape - URL encodes the given string
.SH SYNOPSIS
.B #include <curl/curl.h>
.sp
.BI "char *curl_easy_escape( CURL *" curl ", const char *" string







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH curl_easy_escape 3 "November 09, 2020" "libcurl 7.75.0" "libcurl Manual"

.SH NAME
curl_easy_escape - URL encodes the given string
.SH SYNOPSIS
.B #include <curl/curl.h>
.sp
.BI "char *curl_easy_escape( CURL *" curl ", const char *" string
Changes to jni/curl/docs/libcurl/curl_easy_getinfo.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH curl_easy_getinfo 3 "November 04, 2020" "libcurl 7.74.0" "libcurl Manual"

.SH NAME
curl_easy_getinfo - extract information from a curl handle
.SH SYNOPSIS
.B #include <curl/curl.h>

.B "CURLcode curl_easy_getinfo(CURL *curl, CURLINFO info, ... );"







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH curl_easy_getinfo 3 "November 04, 2020" "libcurl 7.75.0" "libcurl Manual"

.SH NAME
curl_easy_getinfo - extract information from a curl handle
.SH SYNOPSIS
.B #include <curl/curl.h>

.B "CURLcode curl_easy_getinfo(CURL *curl, CURLINFO info, ... );"
Changes to jni/curl/docs/libcurl/curl_easy_init.3.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
.\" **************************************************************************
.\" *                                  _   _ ____  _
.\" *  Project                     ___| | | |  _ \| |
.\" *                             / __| | | | |_) | |
.\" *                            | (__| |_| |  _ <| |___
.\" *                             \___|\___/|_| \_\_____|
.\" *
.\" * Copyright (C) 1998 - 2020, 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 https://curl.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.
.\" *
.\" **************************************************************************
.TH curl_easy_init 3 "November 04, 2020" "libcurl 7.74.0" "libcurl Manual"

.SH NAME
curl_easy_init - Start a libcurl easy session
.SH SYNOPSIS
.B #include <curl/curl.h>

.BI "CURL *curl_easy_init( );"
.SH DESCRIPTION
This function must be the first function to call, and it returns a CURL easy
handle that you must use as input to other functions in the easy
interface. This call \fBMUST\fP have a corresponding call to
\fIcurl_easy_cleanup(3)\fP when the operation is complete.

If you did not already call \fIcurl_global_init(3)\fP, \fIcurl_easy_init(3)\fP
does it automatically.  This may be lethal in multi-threaded cases, since
\fIcurl_global_init(3)\fP is not thread-safe, and it may result in resource
problems because there is no corresponding cleanup.

You are strongly advised to not allow this automatic behaviour, by calling
\fIcurl_global_init(3)\fP yourself properly.  See the description in
\fBlibcurl\fP(3) of global environment requirements for details of how to use
this function.
.SH RETURN VALUE
If this function returns NULL, something went wrong and you cannot use the
other curl functions.
.SH EXAMPLE







|













|


















|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
.\" **************************************************************************
.\" *                                  _   _ ____  _
.\" *  Project                     ___| | | |  _ \| |
.\" *                             / __| | | | |_) | |
.\" *                            | (__| |_| |  _ <| |___
.\" *                             \___|\___/|_| \_\_____|
.\" *
.\" * Copyright (C) 1998 - 2021, 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 https://curl.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.
.\" *
.\" **************************************************************************
.TH curl_easy_init 3 "December 31, 2020" "libcurl 7.75.0" "libcurl Manual"

.SH NAME
curl_easy_init - Start a libcurl easy session
.SH SYNOPSIS
.B #include <curl/curl.h>

.BI "CURL *curl_easy_init( );"
.SH DESCRIPTION
This function must be the first function to call, and it returns a CURL easy
handle that you must use as input to other functions in the easy
interface. This call \fBMUST\fP have a corresponding call to
\fIcurl_easy_cleanup(3)\fP when the operation is complete.

If you did not already call \fIcurl_global_init(3)\fP, \fIcurl_easy_init(3)\fP
does it automatically.  This may be lethal in multi-threaded cases, since
\fIcurl_global_init(3)\fP is not thread-safe, and it may result in resource
problems because there is no corresponding cleanup.

You are strongly advised to not allow this automatic behavior, by calling
\fIcurl_global_init(3)\fP yourself properly.  See the description in
\fBlibcurl\fP(3) of global environment requirements for details of how to use
this function.
.SH RETURN VALUE
If this function returns NULL, something went wrong and you cannot use the
other curl functions.
.SH EXAMPLE
Changes to jni/curl/docs/libcurl/curl_easy_option_by_id.3.
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
.\" * 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.
.\" *
.\" **************************************************************************
.TH curl_easy_option_by_id 3 "November 04, 2020" "libcurl 7.74.0" "libcurl Manual"

.SH NAME
curl_easy_option_by_id - find an easy setopt option by id
.SH SYNOPSIS
.nf
#include <curl/curl.h>








|







15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
.\" * 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.
.\" *
.\" **************************************************************************
.TH curl_easy_option_by_id 3 "November 04, 2020" "libcurl 7.75.0" "libcurl Manual"

.SH NAME
curl_easy_option_by_id - find an easy setopt option by id
.SH SYNOPSIS
.nf
#include <curl/curl.h>

Changes to jni/curl/docs/libcurl/curl_easy_option_by_name.3.
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
.\" * 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.
.\" *
.\" **************************************************************************
.TH curl_easy_option_by_name 3 "November 04, 2020" "libcurl 7.74.0" "libcurl Manual"

.SH NAME
curl_easy_option_by_name - find an easy setopt option by name
.SH SYNOPSIS
.nf
#include <curl/curl.h>








|







15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
.\" * 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.
.\" *
.\" **************************************************************************
.TH curl_easy_option_by_name 3 "November 04, 2020" "libcurl 7.75.0" "libcurl Manual"

.SH NAME
curl_easy_option_by_name - find an easy setopt option by name
.SH SYNOPSIS
.nf
#include <curl/curl.h>

Changes to jni/curl/docs/libcurl/curl_easy_option_next.3.
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
.\" * 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.
.\" *
.\" **************************************************************************
.TH curl_easy_option_next 3 "November 04, 2020" "libcurl 7.74.0" "libcurl Manual"

.SH NAME
curl_easy_option_next - iterate over easy setopt options
.SH SYNOPSIS
.nf
#include <curl/curl.h>








|







15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
.\" * 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.
.\" *
.\" **************************************************************************
.TH curl_easy_option_next 3 "November 04, 2020" "libcurl 7.75.0" "libcurl Manual"

.SH NAME
curl_easy_option_next - iterate over easy setopt options
.SH SYNOPSIS
.nf
#include <curl/curl.h>

Changes to jni/curl/docs/libcurl/curl_easy_pause.3.
15
16
17
18
19
20
21
22
23
24
25
26

27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50

51



52
53
54
55
56
57
58
.\" * 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.
.\" *
.\" **************************************************************************
.TH curl_easy_pause 3 "November 05, 2020" "libcurl 7.74.0" "libcurl Manual"

.SH NAME
curl_easy_pause - pause and unpause a connection
.SH SYNOPSIS

.B #include <curl/curl.h>

.BI "CURLcode curl_easy_pause(CURL *"handle ", int "bitmask " );"

.SH DESCRIPTION
Using this function, you can explicitly mark a running connection to get
paused, and you can unpause a connection that was previously paused.

A connection can be paused by using this function or by letting the read or
the write callbacks return the proper magic return code
(\fICURL_READFUNC_PAUSE\fP and \fICURL_WRITEFUNC_PAUSE\fP). A write callback
that returns pause signals to the library that it couldn't take care of any
data at all, and that data will then be delivered again to the callback when
the writing is later unpaused.

While it may feel tempting, take care and notice that you cannot call this
function from another thread. To unpause, you may for example call it from the
progress callback (\fICURLOPT_PROGRESSFUNCTION(3)\fP), which gets called at
least once per second, even if the connection is paused.

When this function is called to unpause reading, the chance is high that you
will get your write callback called before this function returns.

The \fBhandle\fP argument is of course identifying the handle that operates on

the connection you want to pause or unpause.




The \fBbitmask\fP argument is a set of bits that sets the new state of the
connection. The following bits can be used:
.IP CURLPAUSE_RECV
Pause receiving data. There will be no data received on this connection until
this function is called again without this bit set. Thus, the write callback
(\fICURLOPT_WRITEFUNCTION(3)\fP) won't be called.







|




>


|
|









|






|


|
>
|
>
>
>







15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
.\" * 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.
.\" *
.\" **************************************************************************
.TH curl_easy_pause 3 "December 22, 2020" "libcurl 7.75.0" "libcurl Manual"

.SH NAME
curl_easy_pause - pause and unpause a connection
.SH SYNOPSIS
.nf
.B #include <curl/curl.h>

.BI "CURLcode curl_easy_pause(CURL *"handle ", int "bitmask ");"
.fi
.SH DESCRIPTION
Using this function, you can explicitly mark a running connection to get
paused, and you can unpause a connection that was previously paused.

A connection can be paused by using this function or by letting the read or
the write callbacks return the proper magic return code
(\fICURL_READFUNC_PAUSE\fP and \fICURL_WRITEFUNC_PAUSE\fP). A write callback
that returns pause signals to the library that it couldn't take care of any
data at all, and that data will then be delivered again to the callback when
the transfer is unpaused.

While it may feel tempting, take care and notice that you cannot call this
function from another thread. To unpause, you may for example call it from the
progress callback (\fICURLOPT_PROGRESSFUNCTION(3)\fP), which gets called at
least once per second, even if the connection is paused.

When this function is called to unpause receiving, the chance is high that you
will get your write callback called before this function returns.

The \fBhandle\fP argument identifies the transfer you want to pause or
unpause.

A paused transfer is excluded from low speed cancels via the
\fICURLOPT_LOW_SPEED_LIMIT(3)\fP option and unpausing a transfer will reset
the time period required for the low speed limit to be met.

The \fBbitmask\fP argument is a set of bits that sets the new state of the
connection. The following bits can be used:
.IP CURLPAUSE_RECV
Pause receiving data. There will be no data received on this connection until
this function is called again without this bit set. Thus, the write callback
(\fICURLOPT_WRITEFUNCTION(3)\fP) won't be called.
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85



86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
CURLE_OK (zero) means that the option was set properly, and a non-zero return
code means something wrong occurred after the new state was set.  See the
\fIlibcurl-errors(3)\fP man page for the full list with descriptions.
.SH LIMITATIONS
The pausing of transfers does not work with protocols that work without
network connectivity, like FILE://. Trying to pause such a transfer, in any
direction, will cause problems in the worst case or an error in the best case.
.SH AVAILABILITY
This function was added in libcurl 7.18.0. Before this version, there was no
explicit support for pausing transfers.
.SH "USAGE WITH THE MULTI-SOCKET INTERFACE"
Before libcurl 7.32.0, when a specific handle was unpaused with this function,
there was no particular forced rechecking or similar of the socket's state,
which made the continuation of the transfer get delayed until next
multi-socket call invoke or even longer. Alternatively, the user could
forcibly call for example \fIcurl_multi_socket_all(3)\fP - with a rather hefty
performance penalty.




Starting in libcurl 7.32.0, unpausing a transfer will schedule a timeout
trigger for that handle 1 millisecond into the future, so that a
curl_multi_socket_action( ... CURL_SOCKET_TIMEOUT) can be used immediately
afterwards to get the transfer going again as desired.
.SH "MEMORY USE"
When pausing a read by returning the magic return code from a write callback,
the read data is already in libcurl's internal buffers so it'll have to keep
it in an allocated buffer until the reading is again unpaused using this
function.

If the downloaded data is compressed and is asked to get uncompressed
automatically on download, libcurl will continue to uncompress the entire
downloaded chunk and it will cache the data uncompressed. This has the side-
effect that if you download something that is compressed a lot, it can result
in a very large data amount needing to be allocated to save the data during
the pause. This said, you should probably consider not using paused reading if
you allow libcurl to uncompress data automatically.
.SH "SEE ALSO"
.BR curl_easy_cleanup "(3), " curl_easy_reset "(3)"







|
|
|
|
|
|
|
|
|
<

>
>
>
|
<
<
<



|







|
|


73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88

89
90
91
92
93



94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
CURLE_OK (zero) means that the option was set properly, and a non-zero return
code means something wrong occurred after the new state was set.  See the
\fIlibcurl-errors(3)\fP man page for the full list with descriptions.
.SH LIMITATIONS
The pausing of transfers does not work with protocols that work without
network connectivity, like FILE://. Trying to pause such a transfer, in any
direction, will cause problems in the worst case or an error in the best case.
.SH MULTIPLEXED
When a connection is used multiplexed, like for HTTP/2, and one of the
transfers over the connection is paused and the others continue flowing,
libcurl might end up buffering contents for the paused transfer. It has to do
this because it needs to drain the socket for the other transfers and the
already announced window size for the paused transfer will allow the server to
continue sending data up to that window size amount. By default, libcurl
announces a 32 megabyte window size, which thus can make libcurl end up
buffering 32 megabyte of data for a paused stream.


When such a paused stream is unpaused again, any buffered data will be
delivered first.
.SH AVAILABILITY
Added in libcurl 7.18.0.



.SH "MEMORY USE"
When pausing a read by returning the magic return code from a write callback,
the read data is already in libcurl's internal buffers so it'll have to keep
it in an allocated buffer until the receiving is again unpaused using this
function.

If the downloaded data is compressed and is asked to get uncompressed
automatically on download, libcurl will continue to uncompress the entire
downloaded chunk and it will cache the data uncompressed. This has the side-
effect that if you download something that is compressed a lot, it can result
in a very large data amount needing to be allocated to save the data during
the pause. This said, you should probably consider not using paused receiving
if you allow libcurl to uncompress data automatically.
.SH "SEE ALSO"
.BR curl_easy_cleanup "(3), " curl_easy_reset "(3)"
Changes to jni/curl/docs/libcurl/curl_easy_perform.3.
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
.\" * 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.
.\" *
.\" **************************************************************************
.TH curl_easy_perform 3 "November 04, 2020" "libcurl 7.74.0" "libcurl Manual"

.SH NAME
curl_easy_perform - perform a blocking file transfer
.SH SYNOPSIS
.B #include <curl/curl.h>
.sp
.BI "CURLcode curl_easy_perform(CURL *" easy_handle ");"







|







15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
.\" * 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.
.\" *
.\" **************************************************************************
.TH curl_easy_perform 3 "November 04, 2020" "libcurl 7.75.0" "libcurl Manual"

.SH NAME
curl_easy_perform - perform a blocking file transfer
.SH SYNOPSIS
.B #include <curl/curl.h>
.sp
.BI "CURLcode curl_easy_perform(CURL *" easy_handle ");"
Changes to jni/curl/docs/libcurl/curl_easy_recv.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH curl_easy_recv 3 "November 05, 2020" "libcurl 7.74.0" "libcurl Manual"

.SH NAME
curl_easy_recv - receives raw data on an "easy" connection
.SH SYNOPSIS
.B #include <curl/easy.h>
.sp
.BI "CURLcode curl_easy_recv( CURL *" curl ", void *" buffer ","







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH curl_easy_recv 3 "November 05, 2020" "libcurl 7.75.0" "libcurl Manual"

.SH NAME
curl_easy_recv - receives raw data on an "easy" connection
.SH SYNOPSIS
.B #include <curl/easy.h>
.sp
.BI "CURLcode curl_easy_recv( CURL *" curl ", void *" buffer ","
Changes to jni/curl/docs/libcurl/curl_easy_reset.3.
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
.\" * 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.
.\" *
.\" **************************************************************************
.TH curl_easy_reset 3 "November 04, 2020" "libcurl 7.74.0" "libcurl Manual"

.SH NAME
curl_easy_reset - reset all options of a libcurl session handle
.SH SYNOPSIS
.B #include <curl/curl.h>

.BI "void curl_easy_reset(CURL *"handle ");"







|







15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
.\" * 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.
.\" *
.\" **************************************************************************
.TH curl_easy_reset 3 "November 04, 2020" "libcurl 7.75.0" "libcurl Manual"

.SH NAME
curl_easy_reset - reset all options of a libcurl session handle
.SH SYNOPSIS
.B #include <curl/curl.h>

.BI "void curl_easy_reset(CURL *"handle ");"
Changes to jni/curl/docs/libcurl/curl_easy_send.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH curl_easy_send 3 "November 05, 2020" "libcurl 7.74.0" "libcurl Manual"

.SH NAME
curl_easy_send - sends raw data over an "easy" connection
.SH SYNOPSIS
.B #include <curl/easy.h>
.sp
.BI "CURLcode curl_easy_send( CURL *" curl ", const void *" buffer ","







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH curl_easy_send 3 "November 05, 2020" "libcurl 7.75.0" "libcurl Manual"

.SH NAME
curl_easy_send - sends raw data over an "easy" connection
.SH SYNOPSIS
.B #include <curl/easy.h>
.sp
.BI "CURLcode curl_easy_send( CURL *" curl ", const void *" buffer ","
Changes to jni/curl/docs/libcurl/curl_easy_setopt.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH curl_easy_setopt 3 "November 09, 2020" "libcurl 7.74.0" "libcurl Manual"

.SH NAME
curl_easy_setopt \- set options for a curl easy handle
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLoption option, parameter);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH curl_easy_setopt 3 "July 03, 2020" "libcurl 7.75.0" "libcurl Manual"

.SH NAME
curl_easy_setopt \- set options for a curl easy handle
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLoption option, parameter);
420
421
422
423
424
425
426


427
428
429
430
431
432
433
RTSP stream URI. See \fICURLOPT_RTSP_STREAM_URI(3)\fP
.IP CURLOPT_RTSP_TRANSPORT
RTSP Transport: header. See \fICURLOPT_RTSP_TRANSPORT(3)\fP
.IP CURLOPT_RTSP_CLIENT_CSEQ
Client CSEQ number. See \fICURLOPT_RTSP_CLIENT_CSEQ(3)\fP
.IP CURLOPT_RTSP_SERVER_CSEQ
CSEQ number for RTSP Server->Client request. See \fICURLOPT_RTSP_SERVER_CSEQ(3)\fP


.SH PROTOCOL OPTIONS
.IP CURLOPT_TRANSFERTEXT
Use text transfer. See \fICURLOPT_TRANSFERTEXT(3)\fP
.IP CURLOPT_PROXY_TRANSFER_MODE
Add transfer mode to URL over proxy. See \fICURLOPT_PROXY_TRANSFER_MODE(3)\fP
.IP CURLOPT_CRLF
Convert newlines. See \fICURLOPT_CRLF(3)\fP







>
>







420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
RTSP stream URI. See \fICURLOPT_RTSP_STREAM_URI(3)\fP
.IP CURLOPT_RTSP_TRANSPORT
RTSP Transport: header. See \fICURLOPT_RTSP_TRANSPORT(3)\fP
.IP CURLOPT_RTSP_CLIENT_CSEQ
Client CSEQ number. See \fICURLOPT_RTSP_CLIENT_CSEQ(3)\fP
.IP CURLOPT_RTSP_SERVER_CSEQ
CSEQ number for RTSP Server->Client request. See \fICURLOPT_RTSP_SERVER_CSEQ(3)\fP
.IP CURLOPT_AWS_SIGV4
AWS HTTP V4 Signature. See \fICURLOPT_AWS_SIGV4(3)\fP
.SH PROTOCOL OPTIONS
.IP CURLOPT_TRANSFERTEXT
Use text transfer. See \fICURLOPT_TRANSFERTEXT(3)\fP
.IP CURLOPT_PROXY_TRANSFER_MODE
Add transfer mode to URL over proxy. See \fICURLOPT_PROXY_TRANSFER_MODE(3)\fP
.IP CURLOPT_CRLF
Convert newlines. See \fICURLOPT_CRLF(3)\fP
Changes to jni/curl/docs/libcurl/curl_easy_strerror.3.
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
.\" * 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.
.\" *
.\" **************************************************************************
.TH curl_easy_strerror 3 "November 04, 2020" "libcurl 7.74.0" "libcurl Manual"

.SH NAME
curl_easy_strerror - return string describing error code
.SH SYNOPSIS
#include <curl/curl.h>

const char *curl_easy_strerror(CURLcode errornum);







|







15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
.\" * 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.
.\" *
.\" **************************************************************************
.TH curl_easy_strerror 3 "November 04, 2020" "libcurl 7.75.0" "libcurl Manual"

.SH NAME
curl_easy_strerror - return string describing error code
.SH SYNOPSIS
#include <curl/curl.h>

const char *curl_easy_strerror(CURLcode errornum);
Changes to jni/curl/docs/libcurl/curl_easy_unescape.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH curl_easy_unescape 3 "November 04, 2020" "libcurl 7.74.0" "libcurl Manual"

.SH NAME
curl_easy_unescape - URL decodes the given string
.SH SYNOPSIS
.B #include <curl/curl.h>
.sp
.BI "char *curl_easy_unescape( CURL *" curl ", const char *" url







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH curl_easy_unescape 3 "November 04, 2020" "libcurl 7.75.0" "libcurl Manual"

.SH NAME
curl_easy_unescape - URL decodes the given string
.SH SYNOPSIS
.B #include <curl/curl.h>
.sp
.BI "char *curl_easy_unescape( CURL *" curl ", const char *" url
Changes to jni/curl/docs/libcurl/curl_easy_upkeep.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH curl_easy_upkeep 3 "November 05, 2020" "libcurl 7.74.0" "libcurl Manual"

.SH NAME
curl_easy_upkeep - Perform any connection upkeep checks.
.SH SYNOPSIS
.B #include <curl/curl.h>

.BI "CURLcode curl_easy_upkeep(CURL *" handle ");"







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH curl_easy_upkeep 3 "November 05, 2020" "libcurl 7.75.0" "libcurl Manual"

.SH NAME
curl_easy_upkeep - Perform any connection upkeep checks.
.SH SYNOPSIS
.B #include <curl/curl.h>

.BI "CURLcode curl_easy_upkeep(CURL *" handle ");"
Changes to jni/curl/docs/libcurl/curl_escape.3.
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
.\" * 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.
.\" *
.\" **************************************************************************
.TH curl_escape 3 "November 04, 2020" "libcurl 7.74.0" "libcurl Manual"

.SH NAME
curl_escape - URL encodes the given string
.SH SYNOPSIS
.B #include <curl/curl.h>
.sp
.BI "char *curl_escape( const char *" url ", int "length " );"







|







15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
.\" * 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.
.\" *
.\" **************************************************************************
.TH curl_escape 3 "November 04, 2020" "libcurl 7.75.0" "libcurl Manual"

.SH NAME
curl_escape - URL encodes the given string
.SH SYNOPSIS
.B #include <curl/curl.h>
.sp
.BI "char *curl_escape( const char *" url ", int "length " );"
Changes to jni/curl/docs/libcurl/curl_formadd.3.
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
.\" * 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.
.\" *
.\" **************************************************************************
.TH curl_formadd 3 "November 04, 2020" "libcurl 7.74.0" "libcurl Manual"

.SH NAME
curl_formadd - add a section to a multipart/formdata HTTP POST
.SH SYNOPSIS
.B #include <curl/curl.h>
.sp
.BI "CURLFORMcode curl_formadd(struct curl_httppost ** " firstitem,







|







15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
.\" * 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.
.\" *
.\" **************************************************************************
.TH curl_formadd 3 "November 04, 2020" "libcurl 7.75.0" "libcurl Manual"

.SH NAME
curl_formadd - add a section to a multipart/formdata HTTP POST
.SH SYNOPSIS
.B #include <curl/curl.h>
.sp
.BI "CURLFORMcode curl_formadd(struct curl_httppost ** " firstitem,
Changes to jni/curl/docs/libcurl/curl_formfree.3.
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
.\" * 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.
.\" *
.\" **************************************************************************
.TH curl_formfree 3 "November 05, 2020" "libcurl 7.74.0" "libcurl Manual"

.SH NAME
curl_formfree - free a previously build multipart/formdata HTTP POST chain
.SH SYNOPSIS
.B #include <curl/curl.h>
.sp
.BI "void curl_formfree(struct curl_httppost *" form);







|







15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
.\" * 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.
.\" *
.\" **************************************************************************
.TH curl_formfree 3 "November 05, 2020" "libcurl 7.75.0" "libcurl Manual"

.SH NAME
curl_formfree - free a previously build multipart/formdata HTTP POST chain
.SH SYNOPSIS
.B #include <curl/curl.h>
.sp
.BI "void curl_formfree(struct curl_httppost *" form);
Changes to jni/curl/docs/libcurl/curl_formget.3.
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
.\" * 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.
.\" *
.\" **************************************************************************
.TH curl_formget 3 "November 05, 2020" "libcurl 7.74.0" "libcurl Manual"

.SH NAME
curl_formget - serialize a previously built multipart/formdata HTTP POST chain
.SH SYNOPSIS
.nf
.B #include <curl/curl.h>








|







15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
.\" * 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.
.\" *
.\" **************************************************************************
.TH curl_formget 3 "November 05, 2020" "libcurl 7.75.0" "libcurl Manual"

.SH NAME
curl_formget - serialize a previously built multipart/formdata HTTP POST chain
.SH SYNOPSIS
.nf
.B #include <curl/curl.h>

Changes to jni/curl/docs/libcurl/curl_free.3.
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
.\" * 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.
.\" *
.\" **************************************************************************
.TH curl_free 3 "November 05, 2020" "libcurl 7.74.0" "libcurl Manual"

.SH NAME
curl_free - reclaim memory that has been obtained through a libcurl call
.SH SYNOPSIS
.B #include <curl/curl.h>
.sp
.BI "void curl_free( char *" ptr " );"







|







15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
.\" * 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.
.\" *
.\" **************************************************************************
.TH curl_free 3 "November 05, 2020" "libcurl 7.75.0" "libcurl Manual"

.SH NAME
curl_free - reclaim memory that has been obtained through a libcurl call
.SH SYNOPSIS
.B #include <curl/curl.h>
.sp
.BI "void curl_free( char *" ptr " );"
Changes to jni/curl/docs/libcurl/curl_getdate.3.
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
.\" * 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.
.\" *
.\" **************************************************************************
.TH curl_getdate 3 "November 05, 2020" "libcurl 7.74.0" "libcurl Manual"

.SH NAME
curl_getdate - Convert a date string to number of seconds
.SH SYNOPSIS
.B #include <curl/curl.h>
.sp
.BI "time_t curl_getdate(char *" datestring ", time_t *"now " );"







|







15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
.\" * 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.
.\" *
.\" **************************************************************************
.TH curl_getdate 3 "November 05, 2020" "libcurl 7.75.0" "libcurl Manual"

.SH NAME
curl_getdate - Convert a date string to number of seconds
.SH SYNOPSIS
.B #include <curl/curl.h>
.sp
.BI "time_t curl_getdate(char *" datestring ", time_t *"now " );"
Changes to jni/curl/docs/libcurl/curl_getenv.3.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
.\" **************************************************************************
.\" *                                  _   _ ____  _
.\" *  Project                     ___| | | |  _ \| |
.\" *                             / __| | | | |_) | |
.\" *                            | (__| |_| |  _ <| |___
.\" *                             \___|\___/|_| \_\_____|
.\" *
.\" * Copyright (C) 1998 - 2020, 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 https://curl.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.
.\" *
.\" **************************************************************************
.TH curl_getenv 3 "November 04, 2020" "libcurl 7.74.0" "libcurl Manual"

.SH NAME
curl_getenv - return value for environment name
.SH SYNOPSIS
.B #include <curl/curl.h>
.sp
.BI "char *curl_getenv(const char *" name ");"
.ad
.SH DESCRIPTION
curl_getenv() is a portable wrapper for the getenv() function, meant to
emulate its behaviour and provide an identical interface for all operating
systems libcurl builds on (including win32).

You must \fIcurl_free(3)\fP the returned string when you're done with it.
.SH AVAILABILITY
This function will be removed from the public libcurl API in a near future. It
will instead be made "available" by source code access only, and then as
curlx_getenv().







|













|










|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
.\" **************************************************************************
.\" *                                  _   _ ____  _
.\" *  Project                     ___| | | |  _ \| |
.\" *                             / __| | | | |_) | |
.\" *                            | (__| |_| |  _ <| |___
.\" *                             \___|\___/|_| \_\_____|
.\" *
.\" * Copyright (C) 1998 - 2021, 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 https://curl.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.
.\" *
.\" **************************************************************************
.TH curl_getenv 3 "December 31, 2020" "libcurl 7.75.0" "libcurl Manual"

.SH NAME
curl_getenv - return value for environment name
.SH SYNOPSIS
.B #include <curl/curl.h>
.sp
.BI "char *curl_getenv(const char *" name ");"
.ad
.SH DESCRIPTION
curl_getenv() is a portable wrapper for the getenv() function, meant to
emulate its behavior and provide an identical interface for all operating
systems libcurl builds on (including win32).

You must \fIcurl_free(3)\fP the returned string when you're done with it.
.SH AVAILABILITY
This function will be removed from the public libcurl API in a near future. It
will instead be made "available" by source code access only, and then as
curlx_getenv().
Changes to jni/curl/docs/libcurl/curl_global_cleanup.3.
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
.\" * 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.
.\" *
.\" **************************************************************************
.TH curl_global_cleanup 3 "November 05, 2020" "libcurl 7.74.0" "libcurl Manual"

.SH NAME
curl_global_cleanup - global libcurl cleanup
.SH SYNOPSIS
.B #include <curl/curl.h>
.sp
.BI "void curl_global_cleanup(void);"







|







15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
.\" * 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.
.\" *
.\" **************************************************************************
.TH curl_global_cleanup 3 "November 05, 2020" "libcurl 7.75.0" "libcurl Manual"

.SH NAME
curl_global_cleanup - global libcurl cleanup
.SH SYNOPSIS
.B #include <curl/curl.h>
.sp
.BI "void curl_global_cleanup(void);"
Changes to jni/curl/docs/libcurl/curl_global_init.3.
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
.\" * 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.
.\" *
.\" **************************************************************************
.TH curl_global_init 3 "November 04, 2020" "libcurl 7.74.0" "libcurl Manual"

.SH NAME
curl_global_init - Global libcurl initialisation
.SH SYNOPSIS
.B #include <curl/curl.h>
.sp
.BI "CURLcode curl_global_init(long " flags ");"







|







15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
.\" * 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.
.\" *
.\" **************************************************************************
.TH curl_global_init 3 "November 04, 2020" "libcurl 7.75.0" "libcurl Manual"

.SH NAME
curl_global_init - Global libcurl initialisation
.SH SYNOPSIS
.B #include <curl/curl.h>
.sp
.BI "CURLcode curl_global_init(long " flags ");"
Changes to jni/curl/docs/libcurl/curl_global_init_mem.3.
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
.\" * 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.
.\" *
.\" **************************************************************************
.TH curl_global_init_mem 3 "November 05, 2020" "libcurl 7.74.0" "libcurl Manual"

.SH NAME
curl_global_init_mem - Global libcurl initialisation with memory callbacks
.SH SYNOPSIS
.B #include <curl/curl.h>
.nf
.B "CURLcode curl_global_init_mem(long " flags,







|







15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
.\" * 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.
.\" *
.\" **************************************************************************
.TH curl_global_init_mem 3 "November 05, 2020" "libcurl 7.75.0" "libcurl Manual"

.SH NAME
curl_global_init_mem - Global libcurl initialisation with memory callbacks
.SH SYNOPSIS
.B #include <curl/curl.h>
.nf
.B "CURLcode curl_global_init_mem(long " flags,
Changes to jni/curl/docs/libcurl/curl_global_sslset.3.
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
.\" * 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.
.\" *
.\" **************************************************************************
.TH curl_global_sslset 3 "November 04, 2020" "libcurl 7.74.0" "libcurl Manual"

.SH NAME
curl_global_sslset - Select SSL backend to use with libcurl
.SH SYNOPSIS
.B #include <curl/curl.h>
.nf








|







15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
.\" * 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.
.\" *
.\" **************************************************************************
.TH curl_global_sslset 3 "November 04, 2020" "libcurl 7.75.0" "libcurl Manual"

.SH NAME
curl_global_sslset - Select SSL backend to use with libcurl
.SH SYNOPSIS
.B #include <curl/curl.h>
.nf

Changes to jni/curl/docs/libcurl/curl_mime_addpart.3.
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
.\" * 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.
.\" *
.\" **************************************************************************
.TH curl_mime_addpart 3 "November 05, 2020" "libcurl 7.74.0" "libcurl Manual"

.SH NAME
curl_mime_addpart - append a new empty part to a mime structure
.SH SYNOPSIS
.B #include <curl/curl.h>
.sp
.BI "curl_mimepart * curl_mime_addpart(curl_mime * " mime ");"







|







15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
.\" * 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.
.\" *
.\" **************************************************************************
.TH curl_mime_addpart 3 "November 05, 2020" "libcurl 7.75.0" "libcurl Manual"

.SH NAME
curl_mime_addpart - append a new empty part to a mime structure
.SH SYNOPSIS
.B #include <curl/curl.h>
.sp
.BI "curl_mimepart * curl_mime_addpart(curl_mime * " mime ");"
Changes to jni/curl/docs/libcurl/curl_mime_data.3.
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
.\" * 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.
.\" *
.\" **************************************************************************
.TH curl_mime_data 3 "November 04, 2020" "libcurl 7.74.0" "libcurl Manual"

.SH NAME
curl_mime_data - set a mime part's body data from memory
.SH SYNOPSIS
.B #include <curl/curl.h>
.sp
.BI "CURLcode curl_mime_data(curl_mimepart * " part ", const char * " data







|







15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
.\" * 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.
.\" *
.\" **************************************************************************
.TH curl_mime_data 3 "November 04, 2020" "libcurl 7.75.0" "libcurl Manual"

.SH NAME
curl_mime_data - set a mime part's body data from memory
.SH SYNOPSIS
.B #include <curl/curl.h>
.sp
.BI "CURLcode curl_mime_data(curl_mimepart * " part ", const char * " data
Changes to jni/curl/docs/libcurl/curl_mime_data_cb.3.
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
.\" * 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.
.\" *
.\" **************************************************************************
.TH curl_mime_data_cb 3 "November 05, 2020" "libcurl 7.74.0" "libcurl Manual"

.SH NAME
curl_mime_data_cb - set a callback-based data source for a mime part's body
.SH SYNOPSIS
.B #include <curl/curl.h>
.sp
size_t readfunc(char *buffer, size_t size, size_t nitems, void *arg);







|







15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
.\" * 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.
.\" *
.\" **************************************************************************
.TH curl_mime_data_cb 3 "November 05, 2020" "libcurl 7.75.0" "libcurl Manual"

.SH NAME
curl_mime_data_cb - set a callback-based data source for a mime part's body
.SH SYNOPSIS
.B #include <curl/curl.h>
.sp
size_t readfunc(char *buffer, size_t size, size_t nitems, void *arg);
Changes to jni/curl/docs/libcurl/curl_mime_encoder.3.
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
.\" * 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.
.\" *
.\" **************************************************************************
.TH curl_mime_encoder 3 "November 04, 2020" "libcurl 7.74.0" "libcurl Manual"

.SH NAME
curl_mime_encoder - set a mime part's encoder and content transfer encoding
.SH SYNOPSIS
.B #include <curl/curl.h>
.sp
.BI "CURLcode curl_mime_encoder(curl_mimepart * " part ,







|







15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
.\" * 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.
.\" *
.\" **************************************************************************
.TH curl_mime_encoder 3 "November 04, 2020" "libcurl 7.75.0" "libcurl Manual"

.SH NAME
curl_mime_encoder - set a mime part's encoder and content transfer encoding
.SH SYNOPSIS
.B #include <curl/curl.h>
.sp
.BI "CURLcode curl_mime_encoder(curl_mimepart * " part ,
Changes to jni/curl/docs/libcurl/curl_mime_filedata.3.
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
.\" * 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.
.\" *
.\" **************************************************************************
.TH curl_mime_filedata 3 "November 04, 2020" "libcurl 7.74.0" "libcurl Manual"

.SH NAME
curl_mime_filedata - set a mime part's body data from a file contents
.SH SYNOPSIS
.B #include <curl/curl.h>
.sp
.BI "CURLcode curl_mime_filedata(curl_mimepart * " part ,







|







15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
.\" * 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.
.\" *
.\" **************************************************************************
.TH curl_mime_filedata 3 "November 04, 2020" "libcurl 7.75.0" "libcurl Manual"

.SH NAME
curl_mime_filedata - set a mime part's body data from a file contents
.SH SYNOPSIS
.B #include <curl/curl.h>
.sp
.BI "CURLcode curl_mime_filedata(curl_mimepart * " part ,
Changes to jni/curl/docs/libcurl/curl_mime_filename.3.
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
.\" * 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.
.\" *
.\" **************************************************************************
.TH curl_mime_filename 3 "November 04, 2020" "libcurl 7.74.0" "libcurl Manual"

.SH NAME
curl_mime_filename - set a mime part's remote file name
.SH SYNOPSIS
.B #include <curl/curl.h>
.sp
.BI "CURLcode curl_mime_filename(curl_mimepart * " part ,







|







15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
.\" * 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.
.\" *
.\" **************************************************************************
.TH curl_mime_filename 3 "November 04, 2020" "libcurl 7.75.0" "libcurl Manual"

.SH NAME
curl_mime_filename - set a mime part's remote file name
.SH SYNOPSIS
.B #include <curl/curl.h>
.sp
.BI "CURLcode curl_mime_filename(curl_mimepart * " part ,
Changes to jni/curl/docs/libcurl/curl_mime_free.3.
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
.\" * 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.
.\" *
.\" **************************************************************************
.TH curl_mime_free 3 "November 05, 2020" "libcurl 7.74.0" "libcurl Manual"

.SH NAME
curl_mime_free - free a previously built mime structure
.SH SYNOPSIS
.B #include <curl/curl.h>
.sp
.BI "void curl_mime_free(curl_mime *" mime);







|







15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
.\" * 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.
.\" *
.\" **************************************************************************
.TH curl_mime_free 3 "November 05, 2020" "libcurl 7.75.0" "libcurl Manual"

.SH NAME
curl_mime_free - free a previously built mime structure
.SH SYNOPSIS
.B #include <curl/curl.h>
.sp
.BI "void curl_mime_free(curl_mime *" mime);
Changes to jni/curl/docs/libcurl/curl_mime_headers.3.
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
.\" * 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.
.\" *
.\" **************************************************************************
.TH curl_mime_headers 3 "November 04, 2020" "libcurl 7.74.0" "libcurl Manual"

.SH NAME
curl_mime_headers - set a mime part's custom headers
.SH SYNOPSIS
.B #include <curl/curl.h>
.sp
.BI "CURLcode curl_mime_headers(curl_mimepart * " part ,







|







15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
.\" * 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.
.\" *
.\" **************************************************************************
.TH curl_mime_headers 3 "November 04, 2020" "libcurl 7.75.0" "libcurl Manual"

.SH NAME
curl_mime_headers - set a mime part's custom headers
.SH SYNOPSIS
.B #include <curl/curl.h>
.sp
.BI "CURLcode curl_mime_headers(curl_mimepart * " part ,
Changes to jni/curl/docs/libcurl/curl_mime_init.3.
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
.\" * 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.
.\" *
.\" **************************************************************************
.TH curl_mime_init 3 "November 04, 2020" "libcurl 7.74.0" "libcurl Manual"

.SH NAME
curl_mime_init - create a mime handle
.SH SYNOPSIS
.B #include <curl/curl.h>
.sp
.BI "curl_mime * curl_mime_init(CURL * " easy_handle ");"







|







15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
.\" * 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.
.\" *
.\" **************************************************************************
.TH curl_mime_init 3 "November 04, 2020" "libcurl 7.75.0" "libcurl Manual"

.SH NAME
curl_mime_init - create a mime handle
.SH SYNOPSIS
.B #include <curl/curl.h>
.sp
.BI "curl_mime * curl_mime_init(CURL * " easy_handle ");"
Changes to jni/curl/docs/libcurl/curl_mime_name.3.
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
.\" * 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.
.\" *
.\" **************************************************************************
.TH curl_mime_name 3 "November 04, 2020" "libcurl 7.74.0" "libcurl Manual"

.SH NAME
curl_mime_name - set a mime part's name
.SH SYNOPSIS
.B #include <curl/curl.h>
.sp
.BI "CURLcode curl_mime_name(curl_mimepart * " part ", const char * " name ");"







|







15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
.\" * 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.
.\" *
.\" **************************************************************************
.TH curl_mime_name 3 "November 04, 2020" "libcurl 7.75.0" "libcurl Manual"

.SH NAME
curl_mime_name - set a mime part's name
.SH SYNOPSIS
.B #include <curl/curl.h>
.sp
.BI "CURLcode curl_mime_name(curl_mimepart * " part ", const char * " name ");"
Changes to jni/curl/docs/libcurl/curl_mime_subparts.3.
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
.\" * 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.
.\" *
.\" **************************************************************************
.TH curl_mime_subparts 3 "November 05, 2020" "libcurl 7.74.0" "libcurl Manual"

.SH NAME
curl_mime_subparts - set subparts of a multipart mime part
.SH SYNOPSIS
.B #include <curl/curl.h>
.sp
.BI "CURLcode curl_mime_subparts(curl_mimepart * " part ,







|







15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
.\" * 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.
.\" *
.\" **************************************************************************
.TH curl_mime_subparts 3 "November 05, 2020" "libcurl 7.75.0" "libcurl Manual"

.SH NAME
curl_mime_subparts - set subparts of a multipart mime part
.SH SYNOPSIS
.B #include <curl/curl.h>
.sp
.BI "CURLcode curl_mime_subparts(curl_mimepart * " part ,
Changes to jni/curl/docs/libcurl/curl_mime_type.3.
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
.\" * 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.
.\" *
.\" **************************************************************************
.TH curl_mime_type 3 "November 04, 2020" "libcurl 7.74.0" "libcurl Manual"

.SH NAME
curl_mime_type - set a mime part's content type
.SH SYNOPSIS
.B #include <curl/curl.h>
.sp
.BI "CURLcode curl_mime_type(curl_mimepart * " part ,







|







15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
.\" * 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.
.\" *
.\" **************************************************************************
.TH curl_mime_type 3 "November 04, 2020" "libcurl 7.75.0" "libcurl Manual"

.SH NAME
curl_mime_type - set a mime part's content type
.SH SYNOPSIS
.B #include <curl/curl.h>
.sp
.BI "CURLcode curl_mime_type(curl_mimepart * " part ,
Changes to jni/curl/docs/libcurl/curl_mprintf.3.
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
.\" * 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.
.\" *
.\" **************************************************************************
.TH curl_printf 3 "November 05, 2020" "libcurl 7.74.0" "libcurl Manual"

.SH NAME
curl_maprintf, curl_mfprintf, curl_mprintf, curl_msnprintf, curl_msprintf
curl_mvaprintf, curl_mvfprintf, curl_mvprintf, curl_mvsnprintf,
curl_mvsprintf - formatted output conversion
.SH SYNOPSIS
.B #include <curl/mprintf.h>







|







15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
.\" * 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.
.\" *
.\" **************************************************************************
.TH curl_printf 3 "November 05, 2020" "libcurl 7.75.0" "libcurl Manual"

.SH NAME
curl_maprintf, curl_mfprintf, curl_mprintf, curl_msnprintf, curl_msprintf
curl_mvaprintf, curl_mvfprintf, curl_mvprintf, curl_mvsnprintf,
curl_mvsprintf - formatted output conversion
.SH SYNOPSIS
.B #include <curl/mprintf.h>
Changes to jni/curl/docs/libcurl/curl_multi_add_handle.3.
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
.\" * 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.
.\" *
.\" **************************************************************************
.TH curl_multi_add_handle 3 "November 05, 2020" "libcurl 7.74.0" "libcurl Manual"

.SH NAME
curl_multi_add_handle - add an easy handle to a multi session
.SH SYNOPSIS
#include <curl/curl.h>

CURLMcode curl_multi_add_handle(CURLM *multi_handle, CURL *easy_handle);







|







15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
.\" * 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.
.\" *
.\" **************************************************************************
.TH curl_multi_add_handle 3 "November 05, 2020" "libcurl 7.75.0" "libcurl Manual"

.SH NAME
curl_multi_add_handle - add an easy handle to a multi session
.SH SYNOPSIS
#include <curl/curl.h>

CURLMcode curl_multi_add_handle(CURLM *multi_handle, CURL *easy_handle);
Changes to jni/curl/docs/libcurl/curl_multi_assign.3.
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
.\" * 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.
.\" *
.\" **************************************************************************
.TH curl_multi_assign 3 "November 04, 2020" "libcurl 7.74.0" "libcurl Manual"

.SH NAME
curl_multi_assign \- set data to associate with an internal socket
.SH SYNOPSIS
#include <curl/curl.h>

CURLMcode curl_multi_assign(CURLM *multi_handle, curl_socket_t sockfd,







|







15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
.\" * 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.
.\" *
.\" **************************************************************************
.TH curl_multi_assign 3 "November 04, 2020" "libcurl 7.75.0" "libcurl Manual"

.SH NAME
curl_multi_assign \- set data to associate with an internal socket
.SH SYNOPSIS
#include <curl/curl.h>

CURLMcode curl_multi_assign(CURLM *multi_handle, curl_socket_t sockfd,
Changes to jni/curl/docs/libcurl/curl_multi_cleanup.3.
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
.\" * 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.
.\" *
.\" **************************************************************************
.TH curl_multi_cleanup 3 "November 05, 2020" "libcurl 7.74.0" "libcurl Manual"

.SH NAME
curl_multi_cleanup - close down a multi session
.SH SYNOPSIS
.B #include <curl/curl.h>
.sp
.BI "CURLMcode curl_multi_cleanup( CURLM *multi_handle );"







|







15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
.\" * 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.
.\" *
.\" **************************************************************************
.TH curl_multi_cleanup 3 "November 05, 2020" "libcurl 7.75.0" "libcurl Manual"

.SH NAME
curl_multi_cleanup - close down a multi session
.SH SYNOPSIS
.B #include <curl/curl.h>
.sp
.BI "CURLMcode curl_multi_cleanup( CURLM *multi_handle );"
Changes to jni/curl/docs/libcurl/curl_multi_fdset.3.
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
.\" * 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.
.\" *
.\" **************************************************************************
.TH curl_multi_fdset 3 "November 05, 2020" "libcurl 7.74.0" "libcurl Manual"

.SH NAME
curl_multi_fdset - extracts file descriptor information from a multi handle
.SH SYNOPSIS
.nf
#include <curl/curl.h>








|







15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
.\" * 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.
.\" *
.\" **************************************************************************
.TH curl_multi_fdset 3 "November 05, 2020" "libcurl 7.75.0" "libcurl Manual"

.SH NAME
curl_multi_fdset - extracts file descriptor information from a multi handle
.SH SYNOPSIS
.nf
#include <curl/curl.h>

Changes to jni/curl/docs/libcurl/curl_multi_info_read.3.
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
.\" * 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.
.\" *
.\" **************************************************************************
.TH curl_multi_info_read 3 "November 04, 2020" "libcurl 7.74.0" "libcurl Manual"

.SH NAME
curl_multi_info_read - read multi stack informationals
.SH SYNOPSIS
#include <curl/curl.h>

CURLMsg *curl_multi_info_read( CURLM *multi_handle,







|







15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
.\" * 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.
.\" *
.\" **************************************************************************
.TH curl_multi_info_read 3 "November 04, 2020" "libcurl 7.75.0" "libcurl Manual"

.SH NAME
curl_multi_info_read - read multi stack informationals
.SH SYNOPSIS
#include <curl/curl.h>

CURLMsg *curl_multi_info_read( CURLM *multi_handle,
Changes to jni/curl/docs/libcurl/curl_multi_init.3.
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
.\" * 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.
.\" *
.\" **************************************************************************
.TH curl_multi_init 3 "November 04, 2020" "libcurl 7.74.0" "libcurl Manual"

.SH NAME
curl_multi_init - create a multi handle
.SH SYNOPSIS
.B #include <curl/curl.h>
.sp
.BI "CURLM *curl_multi_init( );"







|







15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
.\" * 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.
.\" *
.\" **************************************************************************
.TH curl_multi_init 3 "November 04, 2020" "libcurl 7.75.0" "libcurl Manual"

.SH NAME
curl_multi_init - create a multi handle
.SH SYNOPSIS
.B #include <curl/curl.h>
.sp
.BI "CURLM *curl_multi_init( );"
Changes to jni/curl/docs/libcurl/curl_multi_perform.3.
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
.\" * 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.
.\" *
.\" **************************************************************************
.TH curl_multi_perform 3 "November 04, 2020" "libcurl 7.74.0" "libcurl Manual"

.SH NAME
curl_multi_perform - reads/writes available data from each easy handle
.SH SYNOPSIS
#include <curl/curl.h>

CURLMcode curl_multi_perform(CURLM *multi_handle, int *running_handles);







|







15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
.\" * 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.
.\" *
.\" **************************************************************************
.TH curl_multi_perform 3 "November 04, 2020" "libcurl 7.75.0" "libcurl Manual"

.SH NAME
curl_multi_perform - reads/writes available data from each easy handle
.SH SYNOPSIS
#include <curl/curl.h>

CURLMcode curl_multi_perform(CURLM *multi_handle, int *running_handles);
Changes to jni/curl/docs/libcurl/curl_multi_poll.3.
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
.\" * 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.
.\" *
.\" **************************************************************************
.TH curl_multi_poll 3 "November 05, 2020" "libcurl 7.74.0" "libcurl Manual"

.SH NAME
curl_multi_poll - polls on all easy handles in a multi handle
.SH SYNOPSIS
.nf
#include <curl/curl.h>








|







15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
.\" * 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.
.\" *
.\" **************************************************************************
.TH curl_multi_poll 3 "November 05, 2020" "libcurl 7.75.0" "libcurl Manual"

.SH NAME
curl_multi_poll - polls on all easy handles in a multi handle
.SH SYNOPSIS
.nf
#include <curl/curl.h>

Changes to jni/curl/docs/libcurl/curl_multi_remove_handle.3.
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
.\" * 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.
.\" *
.\" **************************************************************************
.TH curl_multi_remove_handle 3 "November 05, 2020" "libcurl 7.74.0" "libcurl Manual"

.SH NAME
curl_multi_remove_handle - remove an easy handle from a multi session
.SH SYNOPSIS
#include <curl/curl.h>

CURLMcode curl_multi_remove_handle(CURLM *multi_handle, CURL *easy_handle);







|







15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
.\" * 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.
.\" *
.\" **************************************************************************
.TH curl_multi_remove_handle 3 "November 05, 2020" "libcurl 7.75.0" "libcurl Manual"

.SH NAME
curl_multi_remove_handle - remove an easy handle from a multi session
.SH SYNOPSIS
#include <curl/curl.h>

CURLMcode curl_multi_remove_handle(CURLM *multi_handle, CURL *easy_handle);
Changes to jni/curl/docs/libcurl/curl_multi_setopt.3.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
.\" **************************************************************************
.\" *                                  _   _ ____  _
.\" *  Project                     ___| | | |  _ \| |
.\" *                             / __| | | | |_) | |
.\" *                            | (__| |_| |  _ <| |___
.\" *                             \___|\___/|_| \_\_____|
.\" *
.\" * Copyright (C) 1998 - 2020, 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 https://curl.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.
.\" *
.\" **************************************************************************
.TH curl_multi_setopt 3 "November 05, 2020" "libcurl 7.74.0" "libcurl Manual"

.SH NAME
curl_multi_setopt \- set options for a curl multi handle
.SH SYNOPSIS
#include <curl/curl.h>

CURLMcode curl_multi_setopt(CURLM * multi_handle, CURLMoption option, param);
.SH DESCRIPTION
\fIcurl_multi_setopt(3)\fP is used to tell a libcurl multi handle how to
behave. By using the appropriate options to \fIcurl_multi_setopt(3)\fP, you
can change libcurl's behaviour when using that multi handle.  All options are
set with the \fIoption\fP followed by the parameter \fIparam\fP. That
parameter can be a \fBlong\fP, a \fBfunction pointer\fP, an \fBobject
pointer\fP or a \fBcurl_off_t\fP type, depending on what the specific option
expects. Read this manual carefully as bad input values may cause libcurl to
behave badly!  You can only set one option in each function call.

.SH OPTIONS







|













|










|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
.\" **************************************************************************
.\" *                                  _   _ ____  _
.\" *  Project                     ___| | | |  _ \| |
.\" *                             / __| | | | |_) | |
.\" *                            | (__| |_| |  _ <| |___
.\" *                             \___|\___/|_| \_\_____|
.\" *
.\" * Copyright (C) 1998 - 2021, 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 https://curl.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.
.\" *
.\" **************************************************************************
.TH curl_multi_setopt 3 "December 31, 2020" "libcurl 7.75.0" "libcurl Manual"

.SH NAME
curl_multi_setopt \- set options for a curl multi handle
.SH SYNOPSIS
#include <curl/curl.h>

CURLMcode curl_multi_setopt(CURLM * multi_handle, CURLMoption option, param);
.SH DESCRIPTION
\fIcurl_multi_setopt(3)\fP is used to tell a libcurl multi handle how to
behave. By using the appropriate options to \fIcurl_multi_setopt(3)\fP, you
can change libcurl's behavior when using that multi handle.  All options are
set with the \fIoption\fP followed by the parameter \fIparam\fP. That
parameter can be a \fBlong\fP, a \fBfunction pointer\fP, an \fBobject
pointer\fP or a \fBcurl_off_t\fP type, depending on what the specific option
expects. Read this manual carefully as bad input values may cause libcurl to
behave badly!  You can only set one option in each function call.

.SH OPTIONS
Changes to jni/curl/docs/libcurl/curl_multi_socket.3.
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
.\" * 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.
.\" *
.\" **************************************************************************
.TH curl_multi_socket 3 "November 05, 2020" "libcurl 7.74.0" "libcurl Manual"

.SH NAME
curl_multi_socket \- reads/writes available data
.SH SYNOPSIS
.nf
#include <curl/curl.h>
CURLMcode curl_multi_socket(CURLM * multi_handle, curl_socket_t sockfd,







|







15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
.\" * 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.
.\" *
.\" **************************************************************************
.TH curl_multi_socket 3 "November 05, 2020" "libcurl 7.75.0" "libcurl Manual"

.SH NAME
curl_multi_socket \- reads/writes available data
.SH SYNOPSIS
.nf
#include <curl/curl.h>
CURLMcode curl_multi_socket(CURLM * multi_handle, curl_socket_t sockfd,
Changes to jni/curl/docs/libcurl/curl_multi_socket_action.3.
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
.\" * 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.
.\" *
.\" **************************************************************************
.TH curl_multi_socket_action 3 "November 05, 2020" "libcurl 7.74.0" "libcurl Manual"

.SH NAME
curl_multi_socket_action \- reads/writes available data given an action
.SH SYNOPSIS
.nf
#include <curl/curl.h>








|







15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
.\" * 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.
.\" *
.\" **************************************************************************
.TH curl_multi_socket_action 3 "November 05, 2020" "libcurl 7.75.0" "libcurl Manual"

.SH NAME
curl_multi_socket_action \- reads/writes available data given an action
.SH SYNOPSIS
.nf
#include <curl/curl.h>

Changes to jni/curl/docs/libcurl/curl_multi_strerror.3.
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
.\" * 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.
.\" *
.\" **************************************************************************
.TH curl_multi_strerror 3 "November 04, 2020" "libcurl 7.74.0" "libcurl Manual"

.SH NAME
curl_multi_strerror - return string describing error code
.SH SYNOPSIS
.nf
.B #include <curl/curl.h>
.BI "const char *curl_multi_strerror(CURLMcode " errornum ");"







|







15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
.\" * 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.
.\" *
.\" **************************************************************************
.TH curl_multi_strerror 3 "November 04, 2020" "libcurl 7.75.0" "libcurl Manual"

.SH NAME
curl_multi_strerror - return string describing error code
.SH SYNOPSIS
.nf
.B #include <curl/curl.h>
.BI "const char *curl_multi_strerror(CURLMcode " errornum ");"
Changes to jni/curl/docs/libcurl/curl_multi_timeout.3.
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
.\" * 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.
.\" *
.\" **************************************************************************
.TH curl_multi_timeout 3 "November 04, 2020" "libcurl 7.74.0" "libcurl Manual"

.SH NAME
curl_multi_timeout \- how long to wait for action before proceeding
.SH SYNOPSIS
#include <curl/curl.h>

CURLMcode curl_multi_timeout(CURLM *multi_handle, long *timeout);







|







15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
.\" * 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.
.\" *
.\" **************************************************************************
.TH curl_multi_timeout 3 "November 04, 2020" "libcurl 7.75.0" "libcurl Manual"

.SH NAME
curl_multi_timeout \- how long to wait for action before proceeding
.SH SYNOPSIS
#include <curl/curl.h>

CURLMcode curl_multi_timeout(CURLM *multi_handle, long *timeout);
Changes to jni/curl/docs/libcurl/curl_multi_wait.3.
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
.\" * 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.
.\" *
.\" **************************************************************************
.TH curl_multi_wait 3 "November 05, 2020" "libcurl 7.74.0" "libcurl Manual"

.SH NAME
curl_multi_wait - polls on all easy handles in a multi handle
.SH SYNOPSIS
.nf
#include <curl/curl.h>








|







15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
.\" * 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.
.\" *
.\" **************************************************************************
.TH curl_multi_wait 3 "November 05, 2020" "libcurl 7.75.0" "libcurl Manual"

.SH NAME
curl_multi_wait - polls on all easy handles in a multi handle
.SH SYNOPSIS
.nf
#include <curl/curl.h>

Changes to jni/curl/docs/libcurl/curl_multi_wakeup.3.
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
.\" * 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.
.\" *
.\" **************************************************************************
.TH curl_multi_wakeup 3 "November 05, 2020" "libcurl 7.74.0" "libcurl Manual"

.SH NAME
curl_multi_wakeup - wakes up a sleeping curl_multi_poll call
.SH SYNOPSIS
#include <curl/curl.h>

CURLMcode curl_multi_wakeup(CURLM *multi_handle);







|







15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
.\" * 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.
.\" *
.\" **************************************************************************
.TH curl_multi_wakeup 3 "November 05, 2020" "libcurl 7.75.0" "libcurl Manual"

.SH NAME
curl_multi_wakeup - wakes up a sleeping curl_multi_poll call
.SH SYNOPSIS
#include <curl/curl.h>

CURLMcode curl_multi_wakeup(CURLM *multi_handle);
Changes to jni/curl/docs/libcurl/curl_share_cleanup.3.
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
.\" * 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.
.\" *
.\" **************************************************************************
.TH curl_share_cleanup 3 "November 05, 2020" "libcurl 7.74.0" "libcurl Manual"

.SH NAME
curl_share_cleanup - Clean up a shared object
.SH SYNOPSIS
.B #include <curl/curl.h>
.sp
.BI "CURLSHcode curl_share_cleanup(CURLSH *" share_handle ");"







|







15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
.\" * 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.
.\" *
.\" **************************************************************************
.TH curl_share_cleanup 3 "November 05, 2020" "libcurl 7.75.0" "libcurl Manual"

.SH NAME
curl_share_cleanup - Clean up a shared object
.SH SYNOPSIS
.B #include <curl/curl.h>
.sp
.BI "CURLSHcode curl_share_cleanup(CURLSH *" share_handle ");"
Changes to jni/curl/docs/libcurl/curl_share_init.3.
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
.\" * 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.
.\" *
.\" **************************************************************************
.TH curl_share_init 3 "November 04, 2020" "libcurl 7.74.0" "libcurl Manual"

.SH NAME
curl_share_init - Create a shared object
.SH SYNOPSIS
.B #include <curl/curl.h>
.sp
.BI "CURLSH *curl_share_init( );"







|







15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
.\" * 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.
.\" *
.\" **************************************************************************
.TH curl_share_init 3 "November 04, 2020" "libcurl 7.75.0" "libcurl Manual"

.SH NAME
curl_share_init - Create a shared object
.SH SYNOPSIS
.B #include <curl/curl.h>
.sp
.BI "CURLSH *curl_share_init( );"
Changes to jni/curl/docs/libcurl/curl_share_setopt.3.
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
.\" * 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.
.\" *
.\" **************************************************************************
.TH curl_share_setopt 3 "November 04, 2020" "libcurl 7.74.0" "libcurl Manual"

.SH NAME
curl_share_setopt - Set options for a shared object
.SH SYNOPSIS
.B #include <curl/curl.h>
.sp
CURLSHcode curl_share_setopt(CURLSH *share, CURLSHoption option, parameter);







|







15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
.\" * 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.
.\" *
.\" **************************************************************************
.TH curl_share_setopt 3 "November 04, 2020" "libcurl 7.75.0" "libcurl Manual"

.SH NAME
curl_share_setopt - Set options for a shared object
.SH SYNOPSIS
.B #include <curl/curl.h>
.sp
CURLSHcode curl_share_setopt(CURLSH *share, CURLSHoption option, parameter);
Changes to jni/curl/docs/libcurl/curl_share_strerror.3.
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
.\" * 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.
.\" *
.\" **************************************************************************
.TH curl_share_strerror 3 "November 04, 2020" "libcurl 7.74.0" "libcurl Manual"

.SH NAME
curl_share_strerror - return string describing error code
.SH SYNOPSIS
.nf
.B #include <curl/curl.h>
.BI "const char *curl_share_strerror(CURLSHcode " errornum ");"







|







15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
.\" * 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.
.\" *
.\" **************************************************************************
.TH curl_share_strerror 3 "November 04, 2020" "libcurl 7.75.0" "libcurl Manual"

.SH NAME
curl_share_strerror - return string describing error code
.SH SYNOPSIS
.nf
.B #include <curl/curl.h>
.BI "const char *curl_share_strerror(CURLSHcode " errornum ");"
Changes to jni/curl/docs/libcurl/curl_slist_append.3.
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
.\" * 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.
.\" *
.\" **************************************************************************
.TH curl_slist_append 3 "November 05, 2020" "libcurl 7.74.0" "libcurl Manual"

.SH NAME
curl_slist_append - add a string to an slist
.SH SYNOPSIS
.B #include <curl/curl.h>
.sp
.BI "struct curl_slist *curl_slist_append(struct curl_slist *" list,







|







15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
.\" * 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.
.\" *
.\" **************************************************************************
.TH curl_slist_append 3 "November 05, 2020" "libcurl 7.75.0" "libcurl Manual"

.SH NAME
curl_slist_append - add a string to an slist
.SH SYNOPSIS
.B #include <curl/curl.h>
.sp
.BI "struct curl_slist *curl_slist_append(struct curl_slist *" list,
Changes to jni/curl/docs/libcurl/curl_slist_free_all.3.
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
.\" * 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.
.\" *
.\" **************************************************************************
.TH curl_slist_free_all 3 "November 05, 2020" "libcurl 7.74.0" "libcurl Manual"

.SH NAME
curl_slist_free_all - free an entire curl_slist list
.SH SYNOPSIS
.B #include <curl/curl.h>
.sp
.BI "void curl_slist_free_all(struct curl_slist *" list);







|







15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
.\" * 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.
.\" *
.\" **************************************************************************
.TH curl_slist_free_all 3 "November 05, 2020" "libcurl 7.75.0" "libcurl Manual"

.SH NAME
curl_slist_free_all - free an entire curl_slist list
.SH SYNOPSIS
.B #include <curl/curl.h>
.sp
.BI "void curl_slist_free_all(struct curl_slist *" list);
Changes to jni/curl/docs/libcurl/curl_strequal.3.
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
.\" * 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.
.\" *
.\" **************************************************************************
.TH curl_strequal 3 "November 05, 2020" "libcurl 7.74.0" "libcurl Manual"

.SH NAME
curl_strequal, curl_strnequal - case insensitive string comparisons
.SH SYNOPSIS
.B #include <curl/curl.h>
.sp
.BI "int curl_strequal(char *" str1 ", char *" str2 ");"







|







15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
.\" * 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.
.\" *
.\" **************************************************************************
.TH curl_strequal 3 "November 05, 2020" "libcurl 7.75.0" "libcurl Manual"

.SH NAME
curl_strequal, curl_strnequal - case insensitive string comparisons
.SH SYNOPSIS
.B #include <curl/curl.h>
.sp
.BI "int curl_strequal(char *" str1 ", char *" str2 ");"
Changes to jni/curl/docs/libcurl/curl_unescape.3.
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
.\" * 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.
.\" *
.\" **************************************************************************
.TH curl_unescape 3 "November 04, 2020" "libcurl 7.74.0" "libcurl Manual"

.SH NAME
curl_unescape - URL decodes the given string
.SH SYNOPSIS
.B #include <curl/curl.h>
.sp
.BI "char *curl_unescape( const char *" url ", int "length " );"







|







15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
.\" * 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.
.\" *
.\" **************************************************************************
.TH curl_unescape 3 "November 04, 2020" "libcurl 7.75.0" "libcurl Manual"

.SH NAME
curl_unescape - URL decodes the given string
.SH SYNOPSIS
.B #include <curl/curl.h>
.sp
.BI "char *curl_unescape( const char *" url ", int "length " );"
Changes to jni/curl/docs/libcurl/curl_url.3.
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
.\" * 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.
.\" *
.\" **************************************************************************
.TH curl_url 3 "November 05, 2020" "libcurl 7.74.0" "libcurl Manual"

.SH NAME
curl_url - returns a new CURLU handle
.SH SYNOPSIS
.B #include <curl/curl.h>

CURLU *curl_url();







|







15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
.\" * 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.
.\" *
.\" **************************************************************************
.TH curl_url 3 "November 05, 2020" "libcurl 7.75.0" "libcurl Manual"

.SH NAME
curl_url - returns a new CURLU handle
.SH SYNOPSIS
.B #include <curl/curl.h>

CURLU *curl_url();
Changes to jni/curl/docs/libcurl/curl_url_cleanup.3.
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
.\" * 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.
.\" *
.\" **************************************************************************
.TH curl_url_cleanup 3 "November 05, 2020" "libcurl 7.74.0" "libcurl Manual"

.SH NAME
curl_url_cleanup - free a CURLU handle
.SH SYNOPSIS
.B #include <curl/curl.h>

void curl_url_cleanup(CURLU *handle);







|







15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
.\" * 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.
.\" *
.\" **************************************************************************
.TH curl_url_cleanup 3 "November 05, 2020" "libcurl 7.75.0" "libcurl Manual"

.SH NAME
curl_url_cleanup - free a CURLU handle
.SH SYNOPSIS
.B #include <curl/curl.h>

void curl_url_cleanup(CURLU *handle);
Changes to jni/curl/docs/libcurl/curl_url_dup.3.
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
.\" * 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.
.\" *
.\" **************************************************************************
.TH curl_url_dup 3 "November 05, 2020" "libcurl 7.74.0" "libcurl Manual"

.SH NAME
curl_url_dup - duplicate a CURLU handle
.SH SYNOPSIS
.B #include <curl/curl.h>

CURLU *curl_url_dup(CURLU *inhandle);







|







15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
.\" * 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.
.\" *
.\" **************************************************************************
.TH curl_url_dup 3 "November 05, 2020" "libcurl 7.75.0" "libcurl Manual"

.SH NAME
curl_url_dup - duplicate a CURLU handle
.SH SYNOPSIS
.B #include <curl/curl.h>

CURLU *curl_url_dup(CURLU *inhandle);
Changes to jni/curl/docs/libcurl/curl_url_get.3.
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
.\" * 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.
.\" *
.\" **************************************************************************
.TH curl_url_get 3 "November 05, 2020" "libcurl 7.74.0" "libcurl Manual"

.SH NAME
curl_url_get - extract a part from a URL
.SH SYNOPSIS
.B #include <curl/curl.h>

.nf







|







15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
.\" * 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.
.\" *
.\" **************************************************************************
.TH curl_url_get 3 "November 05, 2020" "libcurl 7.75.0" "libcurl Manual"

.SH NAME
curl_url_get - extract a part from a URL
.SH SYNOPSIS
.B #include <curl/curl.h>

.nf
Changes to jni/curl/docs/libcurl/curl_url_set.3.
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
.\" * 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.
.\" *
.\" **************************************************************************
.TH curl_url_set 3 "November 04, 2020" "libcurl 7.74.0" "libcurl Manual"

.SH NAME
curl_url_set - set a URL part
.SH SYNOPSIS
.B #include <curl/curl.h>

CURLUcode curl_url_set(CURLU *url,







|







15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
.\" * 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.
.\" *
.\" **************************************************************************
.TH curl_url_set 3 "November 04, 2020" "libcurl 7.75.0" "libcurl Manual"

.SH NAME
curl_url_set - set a URL part
.SH SYNOPSIS
.B #include <curl/curl.h>

CURLUcode curl_url_set(CURLU *url,
Changes to jni/curl/docs/libcurl/curl_version.3.
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
.\" * 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.
.\" *
.\" **************************************************************************
.TH curl_version 3 "November 04, 2020" "libcurl 7.74.0" "libcurl Manual"

.SH NAME
curl_version - returns the libcurl version string
.SH SYNOPSIS
.B #include <curl/curl.h>
.sp
.BI "char *curl_version( );"







|







15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
.\" * 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.
.\" *
.\" **************************************************************************
.TH curl_version 3 "November 04, 2020" "libcurl 7.75.0" "libcurl Manual"

.SH NAME
curl_version - returns the libcurl version string
.SH SYNOPSIS
.B #include <curl/curl.h>
.sp
.BI "char *curl_version( );"
Changes to jni/curl/docs/libcurl/curl_version_info.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH curl_version_info 3 "November 04, 2020" "libcurl 7.74.0" "libcurl Manual"

.SH NAME
curl_version_info - returns run-time libcurl version info
.SH SYNOPSIS
.B #include <curl/curl.h>
.sp
.BI "curl_version_info_data *curl_version_info( CURLversion "age ");"







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH curl_version_info 3 "November 04, 2020" "libcurl 7.75.0" "libcurl Manual"

.SH NAME
curl_version_info - returns run-time libcurl version info
.SH SYNOPSIS
.B #include <curl/curl.h>
.sp
.BI "curl_version_info_data *curl_version_info( CURLversion "age ");"
Changes to jni/curl/docs/libcurl/libcurl-easy.3.
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
.\" * 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.
.\" *
.\" **************************************************************************
.TH libcurl 3 "November 04, 2020" "libcurl 7.74.0" "libcurl easy interface"

.SH NAME
libcurl-easy \- easy interface overview
.SH DESCRIPTION
When using libcurl's "easy" interface you init your session and get a handle
(often referred to as an "easy handle"), which you use as input to the easy
interface functions you use. Use \fIcurl_easy_init(3)\fP to get the handle.







|







15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
.\" * 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.
.\" *
.\" **************************************************************************
.TH libcurl 3 "November 04, 2020" "libcurl 7.75.0" "libcurl easy interface"

.SH NAME
libcurl-easy \- easy interface overview
.SH DESCRIPTION
When using libcurl's "easy" interface you init your session and get a handle
(often referred to as an "easy handle"), which you use as input to the easy
interface functions you use. Use \fIcurl_easy_init(3)\fP to get the handle.
Changes to jni/curl/docs/libcurl/libcurl-env.3.
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
.\" * 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.
.\" *
.\" **************************************************************************
.TH libcurl-env 3 "November 04, 2020" "libcurl 7.74.0" "libcurl environment variables"

.SH NAME
libcurl-env \- environment variables libcurl understands
.SH DESCRIPTION
libcurl reads and understands a set of environment variables that if set will
control and change behaviors. This is the full list of variables to set and
description of what they do. Also note that curl, the command line tool,







|







15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
.\" * 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.
.\" *
.\" **************************************************************************
.TH libcurl-env 3 "November 04, 2020" "libcurl 7.75.0" "libcurl environment variables"

.SH NAME
libcurl-env \- environment variables libcurl understands
.SH DESCRIPTION
libcurl reads and understands a set of environment variables that if set will
control and change behaviors. This is the full list of variables to set and
description of what they do. Also note that curl, the command line tool,
Changes to jni/curl/docs/libcurl/libcurl-errors.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH libcurl-errors 3 "November 04, 2020" "libcurl 7.74.0" "libcurl errors"

.SH NAME
libcurl-errors \- error codes in libcurl
.SH DESCRIPTION
This man page includes most, if not all, available error codes in libcurl.
Why they occur and possibly what you can do to fix the problem are also included.
.SH "CURLcode"







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH libcurl-errors 3 "November 04, 2020" "libcurl 7.75.0" "libcurl errors"

.SH NAME
libcurl-errors \- error codes in libcurl
.SH DESCRIPTION
This man page includes most, if not all, available error codes in libcurl.
Why they occur and possibly what you can do to fix the problem are also included.
.SH "CURLcode"
Changes to jni/curl/docs/libcurl/libcurl-multi.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH libcurl-multi 3 "November 04, 2020" "libcurl 7.74.0" "libcurl multi interface"

.SH NAME
libcurl-multi \- how to use the multi interface
.SH DESCRIPTION
This is an overview on how to use the libcurl multi interface in your C
programs. There are specific man pages for each function mentioned in
here. There's also the \fIlibcurl-tutorial(3)\fP man page for a complete







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH libcurl-multi 3 "November 04, 2020" "libcurl 7.75.0" "libcurl multi interface"

.SH NAME
libcurl-multi \- how to use the multi interface
.SH DESCRIPTION
This is an overview on how to use the libcurl multi interface in your C
programs. There are specific man pages for each function mentioned in
here. There's also the \fIlibcurl-tutorial(3)\fP man page for a complete
Changes to jni/curl/docs/libcurl/libcurl-security.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH libcurl-security 3 "November 04, 2020" "libcurl 7.74.0" "libcurl security"

.SH NAME
libcurl-security \- security considerations when using libcurl
.SH "Security"
The libcurl project takes security seriously.  The library is written with
caution and precautions are taken to mitigate many kinds of risks encountered
while operating with potentially malicious servers on the Internet. It is a







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH libcurl-security 3 "November 04, 2020" "libcurl 7.75.0" "libcurl security"

.SH NAME
libcurl-security \- security considerations when using libcurl
.SH "Security"
The libcurl project takes security seriously.  The library is written with
caution and precautions are taken to mitigate many kinds of risks encountered
while operating with potentially malicious servers on the Internet. It is a
Changes to jni/curl/docs/libcurl/libcurl-share.3.
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
.\" * 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.
.\" *
.\" **************************************************************************
.TH libcurl-share 3 "November 05, 2020" "libcurl 7.74.0" "libcurl share interface"

.SH NAME
libcurl-share \- how to use the share interface
.SH DESCRIPTION
This is an overview on how to use the libcurl share interface in your C
programs. There are specific man pages for each function mentioned in
here.







|







15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
.\" * 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.
.\" *
.\" **************************************************************************
.TH libcurl-share 3 "November 05, 2020" "libcurl 7.75.0" "libcurl share interface"

.SH NAME
libcurl-share \- how to use the share interface
.SH DESCRIPTION
This is an overview on how to use the libcurl share interface in your C
programs. There are specific man pages for each function mentioned in
here.
Changes to jni/curl/docs/libcurl/libcurl-symbols.3.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
.\" **************************************************************************
.\" *                                  _   _ ____  _
.\" *  Project                     ___| | | |  _ \| |
.\" *                             / __| | | | |_) | |
.\" *                            | (__| |_| |  _ <| |___
.\" *                             \___|\___/|_| \_\_____|
.\" *
.\" * Copyright (C) 1998 - 2020, 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 https://curl.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.
.\" *
.\" **************************************************************************
.TH libcurl-symbols 3 "Dec  9, 2020" "libcurl 7.41.0" "libcurl symbols"
.SH NAME
libcurl-symbols \- libcurl symbol version information
.SH "libcurl symbols"
This man page details version information for public symbols provided in the
libcurl header files. This lists the first version in which the symbol was
introduced and for some symbols two additional information pieces:








|













|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
.\" **************************************************************************
.\" *                                  _   _ ____  _
.\" *  Project                     ___| | | |  _ \| |
.\" *                             / __| | | | |_) | |
.\" *                            | (__| |_| |  _ <| |___
.\" *                             \___|\___/|_| \_\_____|
.\" *
.\" * Copyright (C) 1998 - 2021, 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 https://curl.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.
.\" *
.\" **************************************************************************
.TH libcurl-symbols 3 "Feb  3, 2021" "libcurl 7.41.0" "libcurl symbols"
.SH NAME
libcurl-symbols \- libcurl symbol version information
.SH "libcurl symbols"
This man page details version information for public symbols provided in the
libcurl header files. This lists the first version in which the symbol was
introduced and for some symbols two additional information pieces:

66
67
68
69
70
71
72


73
74
75
76
77
78
79
Introduced in 7.10.6
.IP CURLAUTH_NTLM
Introduced in 7.10.6
.IP CURLAUTH_NTLM_WB
Introduced in 7.22.0
.IP CURLAUTH_ONLY
Introduced in 7.21.3


.IP CURLCLOSEPOLICY_CALLBACK
Introduced in 7.7
.IP CURLCLOSEPOLICY_LEAST_RECENTLY_USED
Introduced in 7.7
.IP CURLCLOSEPOLICY_LEAST_TRAFFIC
Introduced in 7.7
.IP CURLCLOSEPOLICY_NONE







>
>







66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
Introduced in 7.10.6
.IP CURLAUTH_NTLM
Introduced in 7.10.6
.IP CURLAUTH_NTLM_WB
Introduced in 7.22.0
.IP CURLAUTH_ONLY
Introduced in 7.21.3
.IP CURLAUTH_AWS_SIGV4
Introduced in 7.75.0
.IP CURLCLOSEPOLICY_CALLBACK
Introduced in 7.7
.IP CURLCLOSEPOLICY_LEAST_RECENTLY_USED
Introduced in 7.7
.IP CURLCLOSEPOLICY_LEAST_TRAFFIC
Introduced in 7.7
.IP CURLCLOSEPOLICY_NONE
1431
1432
1433
1434
1435
1436
1437


1438
1439
1440
1441
1442
1443
1444
Introduced in 7.1
.IP CURLOPT_USERNAME
Introduced in 7.19.1
.IP CURLOPT_USERPWD
Introduced in 7.1
.IP CURLOPT_USE_SSL
Introduced in 7.17.0


.IP CURLOPT_VERBOSE
Introduced in 7.1
.IP CURLOPT_WILDCARDMATCH
Introduced in 7.21.0
.IP CURLOPT_WRITEDATA
Introduced in 7.9.7
.IP CURLOPT_WRITEFUNCTION







>
>







1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
Introduced in 7.1
.IP CURLOPT_USERNAME
Introduced in 7.19.1
.IP CURLOPT_USERPWD
Introduced in 7.1
.IP CURLOPT_USE_SSL
Introduced in 7.17.0
.IP CURLOPT_AWS_SIGV4
Introduced in 7.75.0
.IP CURLOPT_VERBOSE
Introduced in 7.1
.IP CURLOPT_WILDCARDMATCH
Introduced in 7.21.0
.IP CURLOPT_WRITEDATA
Introduced in 7.9.7
.IP CURLOPT_WRITEFUNCTION
1497
1498
1499
1500
1501
1502
1503


1504
1505
1506
1507
1508
1509
1510
Introduced in 7.19.4
.IP CURLPROTO_FTP
Introduced in 7.19.4
.IP CURLPROTO_FTPS
Introduced in 7.19.4
.IP CURLPROTO_GOPHER
Introduced in 7.21.2


.IP CURLPROTO_HTTP
Introduced in 7.19.4
.IP CURLPROTO_HTTPS
Introduced in 7.19.4
.IP CURLPROTO_IMAP
Introduced in 7.20.0
.IP CURLPROTO_IMAPS







>
>







1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
Introduced in 7.19.4
.IP CURLPROTO_FTP
Introduced in 7.19.4
.IP CURLPROTO_FTPS
Introduced in 7.19.4
.IP CURLPROTO_GOPHER
Introduced in 7.21.2
.IP CURLPROTO_GOPHERS
Introduced in 7.75.0
.IP CURLPROTO_HTTP
Introduced in 7.19.4
.IP CURLPROTO_HTTPS
Introduced in 7.19.4
.IP CURLPROTO_IMAP
Introduced in 7.20.0
.IP CURLPROTO_IMAPS
1832
1833
1834
1835
1836
1837
1838


1839
1840
1841
1842
1843
1844
1845
Introduced in 7.72.0
.IP CURLVERSION_FIFTH
Introduced in 7.57.0
.IP CURLVERSION_FIRST
Introduced in 7.10
.IP CURLVERSION_FOURTH
Introduced in 7.16.1


.IP CURLVERSION_NOW
Introduced in 7.10
.IP CURLVERSION_SECOND
Introduced in 7.11.1
.IP CURLVERSION_SEVENTH
Introduced in 7.70.0
.IP CURLVERSION_SIXTH







>
>







1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
Introduced in 7.72.0
.IP CURLVERSION_FIFTH
Introduced in 7.57.0
.IP CURLVERSION_FIRST
Introduced in 7.10
.IP CURLVERSION_FOURTH
Introduced in 7.16.1
.IP CURLVERSION_NINTH
Introduced in 7.75.0
.IP CURLVERSION_NOW
Introduced in 7.10
.IP CURLVERSION_SECOND
Introduced in 7.11.1
.IP CURLVERSION_SEVENTH
Introduced in 7.70.0
.IP CURLVERSION_SIXTH
Changes to jni/curl/docs/libcurl/libcurl-thread.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH libcurl-thread 3 "November 04, 2020" "libcurl 7.74.0" "libcurl thread safety"

.SH NAME
libcurl-thread \- libcurl thread safety
.SH "Multi-threading with libcurl"
libcurl is thread safe but has no internal thread synchronization. You may have
to provide your own locking should you meet any of the thread safety exceptions
below.







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH libcurl-thread 3 "November 04, 2020" "libcurl 7.75.0" "libcurl thread safety"

.SH NAME
libcurl-thread \- libcurl thread safety
.SH "Multi-threading with libcurl"
libcurl is thread safe but has no internal thread synchronization. You may have
to provide your own locking should you meet any of the thread safety exceptions
below.
Changes to jni/curl/docs/libcurl/libcurl-tutorial.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH libcurl-tutorial 3 "November 05, 2020" "libcurl 7.74.0" "libcurl programming"

.SH NAME
libcurl-tutorial \- libcurl programming tutorial
.SH "Objective"
This document attempts to describe the general principles and some basic
approaches to consider when programming with libcurl. The text will focus
mainly on the C interface but might apply fairly well on other interfaces as







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH libcurl-tutorial 3 "November 05, 2020" "libcurl 7.75.0" "libcurl programming"

.SH NAME
libcurl-tutorial \- libcurl programming tutorial
.SH "Objective"
This document attempts to describe the general principles and some basic
approaches to consider when programming with libcurl. The text will focus
mainly on the C interface but might apply fairly well on other interfaces as
Changes to jni/curl/docs/libcurl/libcurl-url.3.
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
.\" * 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.
.\" *
.\" **************************************************************************
.TH libcurl 3 "November 05, 2020" "libcurl 7.74.0" "libcurl url interface"

.SH NAME
libcurl-url \- URL interface overview
.SH DESCRIPTION
The URL interface provides a set of functions for parsing and generating URLs.
.SH INCLUDE
You still only include <curl/curl.h> in your code. Note that the URL API was







|







15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
.\" * 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.
.\" *
.\" **************************************************************************
.TH libcurl 3 "November 05, 2020" "libcurl 7.75.0" "libcurl url interface"

.SH NAME
libcurl-url \- URL interface overview
.SH DESCRIPTION
The URL interface provides a set of functions for parsing and generating URLs.
.SH INCLUDE
You still only include <curl/curl.h> in your code. Note that the URL API was
Changes to jni/curl/docs/libcurl/libcurl.3.
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
.\" * 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.
.\" *
.\" **************************************************************************
.TH libcurl 3 "November 04, 2020" "libcurl 7.74.0" "libcurl overview"

.SH NAME
libcurl \- client-side URL transfers
.SH DESCRIPTION
This is a short overview on how to use libcurl in your C programs. There are
specific man pages for each function mentioned in here. There are also the
\fIlibcurl-easy(3)\fP man page, the \fIlibcurl-multi(3)\fP man page, the







|







15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
.\" * 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.
.\" *
.\" **************************************************************************
.TH libcurl 3 "November 04, 2020" "libcurl 7.75.0" "libcurl overview"

.SH NAME
libcurl \- client-side URL transfers
.SH DESCRIPTION
This is a short overview on how to use libcurl in your C programs. There are
specific man pages for each function mentioned in here. There are also the
\fIlibcurl-easy(3)\fP man page, the \fIlibcurl-multi(3)\fP man page, the
jni/curl/docs/libcurl/mksymbolsmanpage.pl became executable.
Changes to jni/curl/docs/libcurl/opts/CURLINFO_ACTIVESOCKET.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLINFO_ACTIVESOCKET 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_getinfo options"

.SH NAME
CURLINFO_ACTIVESOCKET \- get the active socket
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_ACTIVESOCKET,







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLINFO_ACTIVESOCKET 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_getinfo options"

.SH NAME
CURLINFO_ACTIVESOCKET \- get the active socket
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_ACTIVESOCKET,
Changes to jni/curl/docs/libcurl/opts/CURLINFO_APPCONNECT_TIME.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLINFO_APPCONNECT_TIME 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_getinfo options"

.SH NAME
CURLINFO_APPCONNECT_TIME \- get the time until the SSL/SSH handshake is completed
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_APPCONNECT_TIME, double *timep);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLINFO_APPCONNECT_TIME 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_getinfo options"

.SH NAME
CURLINFO_APPCONNECT_TIME \- get the time until the SSL/SSH handshake is completed
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_APPCONNECT_TIME, double *timep);
Changes to jni/curl/docs/libcurl/opts/CURLINFO_APPCONNECT_TIME_T.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLINFO_APPCONNECT_TIME_T 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_getinfo options"

.SH NAME
CURLINFO_APPCONNECT_TIME_T \- get the time until the SSL/SSH handshake is completed
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_APPCONNECT_TIME_T, curl_off_t *timep);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLINFO_APPCONNECT_TIME_T 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_getinfo options"

.SH NAME
CURLINFO_APPCONNECT_TIME_T \- get the time until the SSL/SSH handshake is completed
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_APPCONNECT_TIME_T, curl_off_t *timep);
Changes to jni/curl/docs/libcurl/opts/CURLINFO_CERTINFO.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLINFO_CERTINFO 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_getinfo options"

.SH NAME
CURLINFO_CERTINFO \- get the TLS certificate chain
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_CERTINFO,







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLINFO_CERTINFO 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_getinfo options"

.SH NAME
CURLINFO_CERTINFO \- get the TLS certificate chain
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_CERTINFO,
Changes to jni/curl/docs/libcurl/opts/CURLINFO_CONDITION_UNMET.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLINFO_CONDITION_UNMET 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_getinfo options"

.SH NAME
CURLINFO_CONDITION_UNMET \- get info on unmet time conditional or 304 HTTP response.
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_CONDITION_UNMET, long *unmet);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLINFO_CONDITION_UNMET 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_getinfo options"

.SH NAME
CURLINFO_CONDITION_UNMET \- get info on unmet time conditional or 304 HTTP response.
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_CONDITION_UNMET, long *unmet);
Changes to jni/curl/docs/libcurl/opts/CURLINFO_CONNECT_TIME.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLINFO_CONNECT_TIME 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_getinfo options"

.SH NAME
CURLINFO_CONNECT_TIME \- get the time until connect
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_CONNECT_TIME, double *timep);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLINFO_CONNECT_TIME 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_getinfo options"

.SH NAME
CURLINFO_CONNECT_TIME \- get the time until connect
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_CONNECT_TIME, double *timep);
Changes to jni/curl/docs/libcurl/opts/CURLINFO_CONNECT_TIME_T.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLINFO_CONNECT_TIME_T 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_getinfo options"

.SH NAME
CURLINFO_CONNECT_TIME_T \- get the time until connect
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_CONNECT_TIME_T, curl_off_t *timep);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLINFO_CONNECT_TIME_T 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_getinfo options"

.SH NAME
CURLINFO_CONNECT_TIME_T \- get the time until connect
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_CONNECT_TIME_T, curl_off_t *timep);
Changes to jni/curl/docs/libcurl/opts/CURLINFO_CONTENT_LENGTH_DOWNLOAD.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLINFO_CONTENT_LENGTH_DOWNLOAD 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_getinfo options"

.SH NAME
CURLINFO_CONTENT_LENGTH_DOWNLOAD \- get content-length of download
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_CONTENT_LENGTH_DOWNLOAD,







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLINFO_CONTENT_LENGTH_DOWNLOAD 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_getinfo options"

.SH NAME
CURLINFO_CONTENT_LENGTH_DOWNLOAD \- get content-length of download
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_CONTENT_LENGTH_DOWNLOAD,
Changes to jni/curl/docs/libcurl/opts/CURLINFO_CONTENT_LENGTH_DOWNLOAD_T.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLINFO_CONTENT_LENGTH_DOWNLOAD_T 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_getinfo options"

.SH NAME
CURLINFO_CONTENT_LENGTH_DOWNLOAD_T \- get content-length of download
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_CONTENT_LENGTH_DOWNLOAD_T,







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLINFO_CONTENT_LENGTH_DOWNLOAD_T 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_getinfo options"

.SH NAME
CURLINFO_CONTENT_LENGTH_DOWNLOAD_T \- get content-length of download
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_CONTENT_LENGTH_DOWNLOAD_T,
Changes to jni/curl/docs/libcurl/opts/CURLINFO_CONTENT_LENGTH_UPLOAD.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLINFO_CONTENT_LENGTH_UPLOAD 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_getinfo options"

.SH NAME
CURLINFO_CONTENT_LENGTH_UPLOAD \- get the specified size of the upload
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_CONTENT_LENGTH_UPLOAD,







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLINFO_CONTENT_LENGTH_UPLOAD 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_getinfo options"

.SH NAME
CURLINFO_CONTENT_LENGTH_UPLOAD \- get the specified size of the upload
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_CONTENT_LENGTH_UPLOAD,
Changes to jni/curl/docs/libcurl/opts/CURLINFO_CONTENT_LENGTH_UPLOAD_T.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLINFO_CONTENT_LENGTH_UPLOAD_T 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_getinfo options"

.SH NAME
CURLINFO_CONTENT_LENGTH_UPLOAD_T \- get the specified size of the upload
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_CONTENT_LENGTH_UPLOAD_T,







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLINFO_CONTENT_LENGTH_UPLOAD_T 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_getinfo options"

.SH NAME
CURLINFO_CONTENT_LENGTH_UPLOAD_T \- get the specified size of the upload
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_CONTENT_LENGTH_UPLOAD_T,
Changes to jni/curl/docs/libcurl/opts/CURLINFO_CONTENT_TYPE.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLINFO_CONTENT_TYPE 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_getinfo options"

.SH NAME
CURLINFO_CONTENT_TYPE \- get Content-Type
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_CONTENT_TYPE, char **ct);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLINFO_CONTENT_TYPE 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_getinfo options"

.SH NAME
CURLINFO_CONTENT_TYPE \- get Content-Type
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_CONTENT_TYPE, char **ct);
Changes to jni/curl/docs/libcurl/opts/CURLINFO_COOKIELIST.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLINFO_COOKIELIST 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_getinfo options"

.SH NAME
CURLINFO_COOKIELIST \- get all known cookies
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_COOKIELIST,







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLINFO_COOKIELIST 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_getinfo options"

.SH NAME
CURLINFO_COOKIELIST \- get all known cookies
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_COOKIELIST,
Changes to jni/curl/docs/libcurl/opts/CURLINFO_EFFECTIVE_METHOD.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLINFO_EFFECTIVE_METHOD 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_getinfo options"

.SH NAME
CURLINFO_EFFECTIVE_METHOD \- get the last used HTTP method
.SH SYNOPSIS
.nf
#include <curl/curl.h>








|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLINFO_EFFECTIVE_METHOD 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_getinfo options"

.SH NAME
CURLINFO_EFFECTIVE_METHOD \- get the last used HTTP method
.SH SYNOPSIS
.nf
#include <curl/curl.h>

Changes to jni/curl/docs/libcurl/opts/CURLINFO_EFFECTIVE_URL.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLINFO_EFFECTIVE_URL 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_getinfo options"

.SH NAME
CURLINFO_EFFECTIVE_URL \- get the last used URL
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_EFFECTIVE_URL, char **urlp);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLINFO_EFFECTIVE_URL 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_getinfo options"

.SH NAME
CURLINFO_EFFECTIVE_URL \- get the last used URL
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_EFFECTIVE_URL, char **urlp);
Changes to jni/curl/docs/libcurl/opts/CURLINFO_FILETIME.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLINFO_FILETIME 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_getinfo options"

.SH NAME
CURLINFO_FILETIME \- get the remote time of the retrieved document
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_FILETIME, long *timep);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLINFO_FILETIME 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_getinfo options"

.SH NAME
CURLINFO_FILETIME \- get the remote time of the retrieved document
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_FILETIME, long *timep);
Changes to jni/curl/docs/libcurl/opts/CURLINFO_FILETIME_T.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLINFO_FILETIME 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_getinfo options"

.SH NAME
CURLINFO_FILETIME_T \- get the remote time of the retrieved document
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_FILETIME_T, curl_off_t *timep);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLINFO_FILETIME 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_getinfo options"

.SH NAME
CURLINFO_FILETIME_T \- get the remote time of the retrieved document
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_FILETIME_T, curl_off_t *timep);
Changes to jni/curl/docs/libcurl/opts/CURLINFO_FTP_ENTRY_PATH.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLINFO_FTP_ENTRY_PATH 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_getinfo options"

.SH NAME
CURLINFO_FTP_ENTRY_PATH \- get entry path in FTP server
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_FTP_ENTRY_PATH, char **path);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLINFO_FTP_ENTRY_PATH 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_getinfo options"

.SH NAME
CURLINFO_FTP_ENTRY_PATH \- get entry path in FTP server
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_FTP_ENTRY_PATH, char **path);
Changes to jni/curl/docs/libcurl/opts/CURLINFO_HEADER_SIZE.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLINFO_HEADER_SIZE 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_getinfo options"

.SH NAME
CURLINFO_HEADER_SIZE \- get size of retrieved headers
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_HEADER_SIZE, long *sizep);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLINFO_HEADER_SIZE 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_getinfo options"

.SH NAME
CURLINFO_HEADER_SIZE \- get size of retrieved headers
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_HEADER_SIZE, long *sizep);
Changes to jni/curl/docs/libcurl/opts/CURLINFO_HTTPAUTH_AVAIL.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLINFO_HTTPAUTH_AVAIL 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_getinfo options"

.SH NAME
CURLINFO_HTTPAUTH_AVAIL \- get available HTTP authentication methods
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_HTTPAUTH_AVAIL, long *authp);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLINFO_HTTPAUTH_AVAIL 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_getinfo options"

.SH NAME
CURLINFO_HTTPAUTH_AVAIL \- get available HTTP authentication methods
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_HTTPAUTH_AVAIL, long *authp);
Changes to jni/curl/docs/libcurl/opts/CURLINFO_HTTP_CONNECTCODE.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLINFO_HTTP_CONNECTCODE 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_getinfo options"

.SH NAME
CURLINFO_HTTP_CONNECTCODE \- get the CONNECT response code
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_HTTP_CONNECTCODE, long *p);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLINFO_HTTP_CONNECTCODE 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_getinfo options"

.SH NAME
CURLINFO_HTTP_CONNECTCODE \- get the CONNECT response code
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_HTTP_CONNECTCODE, long *p);
Changes to jni/curl/docs/libcurl/opts/CURLINFO_HTTP_VERSION.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLINFO_HTTP_VERSION 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_getinfo options"

.SH NAME
CURLINFO_HTTP_VERSION \- get the http version used in the connection
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_HTTP_VERSION, long *p);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLINFO_HTTP_VERSION 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_getinfo options"

.SH NAME
CURLINFO_HTTP_VERSION \- get the http version used in the connection
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_HTTP_VERSION, long *p);
Changes to jni/curl/docs/libcurl/opts/CURLINFO_LASTSOCKET.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLINFO_LASTSOCKET 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_getinfo options"

.SH NAME
CURLINFO_LASTSOCKET \- get the last socket used
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_LASTSOCKET, long *socket);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLINFO_LASTSOCKET 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_getinfo options"

.SH NAME
CURLINFO_LASTSOCKET \- get the last socket used
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_LASTSOCKET, long *socket);
Changes to jni/curl/docs/libcurl/opts/CURLINFO_LOCAL_IP.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLINFO_LOCAL_IP 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_getinfo options"

.SH NAME
CURLINFO_LOCAL_IP \- get local IP address of last connection
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_LOCAL_IP, char **ip);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLINFO_LOCAL_IP 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_getinfo options"

.SH NAME
CURLINFO_LOCAL_IP \- get local IP address of last connection
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_LOCAL_IP, char **ip);
Changes to jni/curl/docs/libcurl/opts/CURLINFO_LOCAL_PORT.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLINFO_LOCAL_PORT 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_getinfo options"

.SH NAME
CURLINFO_LOCAL_PORT \- get the latest local port number
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_LOCAL_PORT, long *portp);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLINFO_LOCAL_PORT 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_getinfo options"

.SH NAME
CURLINFO_LOCAL_PORT \- get the latest local port number
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_LOCAL_PORT, long *portp);
Changes to jni/curl/docs/libcurl/opts/CURLINFO_NAMELOOKUP_TIME.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLINFO_NAMELOOKUP_TIME 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_getinfo options"

.SH NAME
CURLINFO_NAMELOOKUP_TIME \- get the name lookup time
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_NAMELOOKUP_TIME, double *timep);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLINFO_NAMELOOKUP_TIME 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_getinfo options"

.SH NAME
CURLINFO_NAMELOOKUP_TIME \- get the name lookup time
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_NAMELOOKUP_TIME, double *timep);
Changes to jni/curl/docs/libcurl/opts/CURLINFO_NAMELOOKUP_TIME_T.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLINFO_NAMELOOKUP_TIME_T 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_getinfo options"

.SH NAME
CURLINFO_NAMELOOKUP_TIME_T \- get the name lookup time in microseconds
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_NAMELOOKUP_TIME_T, curl_off_t *timep);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLINFO_NAMELOOKUP_TIME_T 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_getinfo options"

.SH NAME
CURLINFO_NAMELOOKUP_TIME_T \- get the name lookup time in microseconds
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_NAMELOOKUP_TIME_T, curl_off_t *timep);
Changes to jni/curl/docs/libcurl/opts/CURLINFO_NUM_CONNECTS.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLINFO_NUM_CONNECTS 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_getinfo options"

.SH NAME
CURLINFO_NUM_CONNECTS \- get number of created connections
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_NUM_CONNECTS, long *nump);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLINFO_NUM_CONNECTS 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_getinfo options"

.SH NAME
CURLINFO_NUM_CONNECTS \- get number of created connections
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_NUM_CONNECTS, long *nump);
Changes to jni/curl/docs/libcurl/opts/CURLINFO_OS_ERRNO.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLINFO_OS_ERRNO 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_getinfo options"

.SH NAME
CURLINFO_OS_ERRNO \- get errno number from last connect failure
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_OS_ERRNO, long *errnop);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLINFO_OS_ERRNO 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_getinfo options"

.SH NAME
CURLINFO_OS_ERRNO \- get errno number from last connect failure
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_OS_ERRNO, long *errnop);
Changes to jni/curl/docs/libcurl/opts/CURLINFO_PRETRANSFER_TIME.3.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33

34
35
36
37
38
39
40
41
42
43
.\" **************************************************************************
.\" *                                  _   _ ____  _
.\" *  Project                     ___| | | |  _ \| |
.\" *                             / __| | | | |_) | |
.\" *                            | (__| |_| |  _ <| |___
.\" *                             \___|\___/|_| \_\_____|
.\" *
.\" * Copyright (C) 1998 - 2019, 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 https://curl.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.
.\" *
.\" **************************************************************************
.\"
.TH CURLINFO_PRETRANSFER_TIME 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_getinfo options"

.SH NAME
CURLINFO_PRETRANSFER_TIME \- get the time until the file transfer start
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_PRETRANSFER_TIME, double *timep);
.SH DESCRIPTION
Pass a pointer to a double to receive the time, in seconds, it took from the
start until the file transfer is just about to begin. This includes all

pre-transfer commands and negotiations that are specific to the particular
protocol(s) involved. It does \fInot\fP involve the sending of the protocol-
specific request that triggers a transfer.

When a redirect is followed, the time from each request is added together.

See also the TIMES overview in the \fIcurl_easy_getinfo(3)\fP man page.
.SH PROTOCOLS
All
.SH EXAMPLE







|














|









|
>
|
|
|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
.\" **************************************************************************
.\" *                                  _   _ ____  _
.\" *  Project                     ___| | | |  _ \| |
.\" *                             / __| | | | |_) | |
.\" *                            | (__| |_| |  _ <| |___
.\" *                             \___|\___/|_| \_\_____|
.\" *
.\" * Copyright (C) 1998 - 2021, 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 https://curl.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.
.\" *
.\" **************************************************************************
.\"
.TH CURLINFO_PRETRANSFER_TIME 3 "January 14, 2021" "libcurl 7.75.0" "curl_easy_getinfo options"

.SH NAME
CURLINFO_PRETRANSFER_TIME \- get the time until the file transfer start
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_PRETRANSFER_TIME, double *timep);
.SH DESCRIPTION
Pass a pointer to a double to receive the time, in seconds, it took from the
start until the file transfer is just about to begin.

This time-stamp includes all pre-transfer commands and negotiations that are
specific to the particular protocol(s) involved. It includes the sending of
the protocol- specific protocol instructions that triggers a transfer.

When a redirect is followed, the time from each request is added together.

See also the TIMES overview in the \fIcurl_easy_getinfo(3)\fP man page.
.SH PROTOCOLS
All
.SH EXAMPLE
Changes to jni/curl/docs/libcurl/opts/CURLINFO_PRETRANSFER_TIME_T.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLINFO_PRETRANSFER_TIME_T 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_getinfo options"

.SH NAME
CURLINFO_PRETRANSFER_TIME_T \- get the time until the file transfer start
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_PRETRANSFER_TIME_T, curl_off_t *timep);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLINFO_PRETRANSFER_TIME_T 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_getinfo options"

.SH NAME
CURLINFO_PRETRANSFER_TIME_T \- get the time until the file transfer start
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_PRETRANSFER_TIME_T, curl_off_t *timep);
Changes to jni/curl/docs/libcurl/opts/CURLINFO_PRIMARY_IP.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLINFO_PRIMARY_IP 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_getinfo options"

.SH NAME
CURLINFO_PRIMARY_IP \- get IP address of last connection
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_PRIMARY_IP, char **ip);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLINFO_PRIMARY_IP 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_getinfo options"

.SH NAME
CURLINFO_PRIMARY_IP \- get IP address of last connection
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_PRIMARY_IP, char **ip);
Changes to jni/curl/docs/libcurl/opts/CURLINFO_PRIMARY_PORT.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLINFO_PRIMARY_PORT 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_getinfo options"

.SH NAME
CURLINFO_PRIMARY_PORT \- get the latest destination port number
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_PRIMARY_PORT, long *portp);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLINFO_PRIMARY_PORT 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_getinfo options"

.SH NAME
CURLINFO_PRIMARY_PORT \- get the latest destination port number
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_PRIMARY_PORT, long *portp);
Changes to jni/curl/docs/libcurl/opts/CURLINFO_PRIVATE.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLINFO_PRIVATE 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_getinfo options"

.SH NAME
CURLINFO_PRIVATE \- get the private pointer
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_PRIVATE, char **private);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLINFO_PRIVATE 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_getinfo options"

.SH NAME
CURLINFO_PRIVATE \- get the private pointer
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_PRIVATE, char **private);
Changes to jni/curl/docs/libcurl/opts/CURLINFO_PROTOCOL.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLINFO_PROTOCOL 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_getinfo options"

.SH NAME
CURLINFO_PROTOCOL \- get the protocol used in the connection
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_PROTOCOL, long *p);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLINFO_PROTOCOL 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_getinfo options"

.SH NAME
CURLINFO_PROTOCOL \- get the protocol used in the connection
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_PROTOCOL, long *p);
Changes to jni/curl/docs/libcurl/opts/CURLINFO_PROXYAUTH_AVAIL.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLINFO_PROXYAUTH_AVAIL 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_getinfo options"

.SH NAME
CURLINFO_PROXYAUTH_AVAIL \- get available HTTP proxy authentication methods
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_PROXYAUTH_AVAIL, long *authp);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLINFO_PROXYAUTH_AVAIL 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_getinfo options"

.SH NAME
CURLINFO_PROXYAUTH_AVAIL \- get available HTTP proxy authentication methods
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_PROXYAUTH_AVAIL, long *authp);
Changes to jni/curl/docs/libcurl/opts/CURLINFO_PROXY_ERROR.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLINFO_PROXY_ERROR 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_getinfo options"

.SH NAME
CURLINFO_PROXY_ERROR \- get the detailed (SOCKS) proxy error
.SH SYNOPSIS
.nf
#include <curl/curl.h>








|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLINFO_PROXY_ERROR 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_getinfo options"

.SH NAME
CURLINFO_PROXY_ERROR \- get the detailed (SOCKS) proxy error
.SH SYNOPSIS
.nf
#include <curl/curl.h>

Changes to jni/curl/docs/libcurl/opts/CURLINFO_PROXY_SSL_VERIFYRESULT.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLINFO_PROXY_SSL_VERIFYRESULT 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_getinfo options"

.SH NAME
CURLINFO_PROXY_SSL_VERIFYRESULT \- get the result of the proxy certificate verification
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_PROXY_SSL_VERIFYRESULT, long *result);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLINFO_PROXY_SSL_VERIFYRESULT 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_getinfo options"

.SH NAME
CURLINFO_PROXY_SSL_VERIFYRESULT \- get the result of the proxy certificate verification
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_PROXY_SSL_VERIFYRESULT, long *result);
Changes to jni/curl/docs/libcurl/opts/CURLINFO_REDIRECT_COUNT.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLINFO_REDIRECT_COUNT 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_getinfo options"

.SH NAME
CURLINFO_REDIRECT_COUNT \- get the number of redirects
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_REDIRECT_COUNT, long *countp);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLINFO_REDIRECT_COUNT 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_getinfo options"

.SH NAME
CURLINFO_REDIRECT_COUNT \- get the number of redirects
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_REDIRECT_COUNT, long *countp);
Changes to jni/curl/docs/libcurl/opts/CURLINFO_REDIRECT_TIME.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLINFO_REDIRECT_TIME 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_getinfo options"

.SH NAME
CURLINFO_REDIRECT_TIME \- get the time for all redirection steps
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_REDIRECT_TIME, double *timep);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLINFO_REDIRECT_TIME 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_getinfo options"

.SH NAME
CURLINFO_REDIRECT_TIME \- get the time for all redirection steps
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_REDIRECT_TIME, double *timep);
Changes to jni/curl/docs/libcurl/opts/CURLINFO_REDIRECT_TIME_T.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLINFO_REDIRECT_TIME_T 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_getinfo options"

.SH NAME
CURLINFO_REDIRECT_TIME_T \- get the time for all redirection steps
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_REDIRECT_TIME_T, curl_off_t *timep);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLINFO_REDIRECT_TIME_T 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_getinfo options"

.SH NAME
CURLINFO_REDIRECT_TIME_T \- get the time for all redirection steps
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_REDIRECT_TIME_T, curl_off_t *timep);
Changes to jni/curl/docs/libcurl/opts/CURLINFO_REDIRECT_URL.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLINFO_REDIRECT_URL 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_getinfo options"

.SH NAME
CURLINFO_REDIRECT_URL \- get the URL a redirect would go to
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_REDIRECT_URL, char **urlp);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLINFO_REDIRECT_URL 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_getinfo options"

.SH NAME
CURLINFO_REDIRECT_URL \- get the URL a redirect would go to
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_REDIRECT_URL, char **urlp);
Changes to jni/curl/docs/libcurl/opts/CURLINFO_REQUEST_SIZE.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLINFO_REQUEST_SIZE 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_getinfo options"

.SH NAME
CURLINFO_REQUEST_SIZE \- get size of sent request
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_REQUEST_SIZE, long *sizep);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLINFO_REQUEST_SIZE 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_getinfo options"

.SH NAME
CURLINFO_REQUEST_SIZE \- get size of sent request
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_REQUEST_SIZE, long *sizep);
Changes to jni/curl/docs/libcurl/opts/CURLINFO_RESPONSE_CODE.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLINFO_RESPONSE_CODE 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_getinfo options"

.SH NAME
CURLINFO_RESPONSE_CODE \- get the last response code
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_RESPONSE_CODE, long *codep);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLINFO_RESPONSE_CODE 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_getinfo options"

.SH NAME
CURLINFO_RESPONSE_CODE \- get the last response code
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_RESPONSE_CODE, long *codep);
Changes to jni/curl/docs/libcurl/opts/CURLINFO_RETRY_AFTER.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLINFO_RETRY_AFTER 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_getinfo options"

.SH NAME
CURLINFO_RETRY_AFTER \- returns the Retry-After retry delay
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_RETRY_AFTER, curl_off_t *retry);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLINFO_RETRY_AFTER 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_getinfo options"

.SH NAME
CURLINFO_RETRY_AFTER \- returns the Retry-After retry delay
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_RETRY_AFTER, curl_off_t *retry);
Changes to jni/curl/docs/libcurl/opts/CURLINFO_RTSP_CLIENT_CSEQ.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLINFO_RTSP_CLIENT_CSEQ 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_getinfo options"

.SH NAME
CURLINFO_RTSP_CLIENT_CSEQ \- get the next RTSP client CSeq
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_RTSP_CLIENT_CSEQ, long *cseq);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLINFO_RTSP_CLIENT_CSEQ 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_getinfo options"

.SH NAME
CURLINFO_RTSP_CLIENT_CSEQ \- get the next RTSP client CSeq
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_RTSP_CLIENT_CSEQ, long *cseq);
Changes to jni/curl/docs/libcurl/opts/CURLINFO_RTSP_CSEQ_RECV.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLINFO_RTSP_CSEQ_RECV 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_getinfo options"

.SH NAME
CURLINFO_RTSP_CSEQ_RECV \- get the recently received CSeq
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_RTSP_CSEQ_RECV, long *cseq);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLINFO_RTSP_CSEQ_RECV 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_getinfo options"

.SH NAME
CURLINFO_RTSP_CSEQ_RECV \- get the recently received CSeq
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_RTSP_CSEQ_RECV, long *cseq);
Changes to jni/curl/docs/libcurl/opts/CURLINFO_RTSP_SERVER_CSEQ.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLINFO_RTSP_SERVER_CSEQ 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_getinfo options"

.SH NAME
CURLINFO_RTSP_SERVER_CSEQ \- get the next RTSP server CSeq
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_RTSP_SERVER_CSEQ, long *cseq);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLINFO_RTSP_SERVER_CSEQ 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_getinfo options"

.SH NAME
CURLINFO_RTSP_SERVER_CSEQ \- get the next RTSP server CSeq
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_RTSP_SERVER_CSEQ, long *cseq);
Changes to jni/curl/docs/libcurl/opts/CURLINFO_RTSP_SESSION_ID.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLINFO_RTSP_SESSION_ID 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_getinfo options"

.SH NAME
CURLINFO_RTSP_SESSION_ID \- get RTSP session ID
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_RTSP_SESSION_ID, char **id);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLINFO_RTSP_SESSION_ID 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_getinfo options"

.SH NAME
CURLINFO_RTSP_SESSION_ID \- get RTSP session ID
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_RTSP_SESSION_ID, char **id);
Changes to jni/curl/docs/libcurl/opts/CURLINFO_SCHEME.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLINFO_SCHEME 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_getinfo options"

.SH NAME
CURLINFO_SCHEME \- get the URL scheme (sometimes called protocol) used in the connection
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_SCHEME, char **scheme);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLINFO_SCHEME 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_getinfo options"

.SH NAME
CURLINFO_SCHEME \- get the URL scheme (sometimes called protocol) used in the connection
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_SCHEME, char **scheme);
Changes to jni/curl/docs/libcurl/opts/CURLINFO_SIZE_DOWNLOAD.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLINFO_SIZE_DOWNLOAD 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_getinfo options"

.SH NAME
CURLINFO_SIZE_DOWNLOAD \- get the number of downloaded bytes
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_SIZE_DOWNLOAD, double *dlp);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLINFO_SIZE_DOWNLOAD 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_getinfo options"

.SH NAME
CURLINFO_SIZE_DOWNLOAD \- get the number of downloaded bytes
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_SIZE_DOWNLOAD, double *dlp);
Changes to jni/curl/docs/libcurl/opts/CURLINFO_SIZE_DOWNLOAD_T.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLINFO_SIZE_DOWNLOAD_T 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_getinfo options"

.SH NAME
CURLINFO_SIZE_DOWNLOAD_T \- get the number of downloaded bytes
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_SIZE_DOWNLOAD_T, curl_off_t *dlp);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLINFO_SIZE_DOWNLOAD_T 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_getinfo options"

.SH NAME
CURLINFO_SIZE_DOWNLOAD_T \- get the number of downloaded bytes
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_SIZE_DOWNLOAD_T, curl_off_t *dlp);
Changes to jni/curl/docs/libcurl/opts/CURLINFO_SIZE_UPLOAD.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLINFO_SIZE_UPLOAD 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_getinfo options"

.SH NAME
CURLINFO_SIZE_UPLOAD \- get the number of uploaded bytes
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_SIZE_UPLOAD, double *uploadp);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLINFO_SIZE_UPLOAD 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_getinfo options"

.SH NAME
CURLINFO_SIZE_UPLOAD \- get the number of uploaded bytes
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_SIZE_UPLOAD, double *uploadp);
Changes to jni/curl/docs/libcurl/opts/CURLINFO_SIZE_UPLOAD_T.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLINFO_SIZE_UPLOAD_T 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_getinfo options"

.SH NAME
CURLINFO_SIZE_UPLOAD_T \- get the number of uploaded bytes
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_SIZE_UPLOAD_T, curl_off_t *uploadp);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLINFO_SIZE_UPLOAD_T 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_getinfo options"

.SH NAME
CURLINFO_SIZE_UPLOAD_T \- get the number of uploaded bytes
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_SIZE_UPLOAD_T, curl_off_t *uploadp);
Changes to jni/curl/docs/libcurl/opts/CURLINFO_SPEED_DOWNLOAD.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLINFO_SPEED_DOWNLOAD 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_getinfo options"

.SH NAME
CURLINFO_SPEED_DOWNLOAD \- get download speed
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_SPEED_DOWNLOAD, double *speed);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLINFO_SPEED_DOWNLOAD 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_getinfo options"

.SH NAME
CURLINFO_SPEED_DOWNLOAD \- get download speed
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_SPEED_DOWNLOAD, double *speed);
Changes to jni/curl/docs/libcurl/opts/CURLINFO_SPEED_DOWNLOAD_T.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLINFO_SPEED_DOWNLOAD_T 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_getinfo options"

.SH NAME
CURLINFO_SPEED_DOWNLOAD_T \- get download speed
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_SPEED_DOWNLOAD_T, curl_off_t *speed);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLINFO_SPEED_DOWNLOAD_T 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_getinfo options"

.SH NAME
CURLINFO_SPEED_DOWNLOAD_T \- get download speed
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_SPEED_DOWNLOAD_T, curl_off_t *speed);
Changes to jni/curl/docs/libcurl/opts/CURLINFO_SPEED_UPLOAD.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLINFO_SPEED_UPLOAD 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_getinfo options"

.SH NAME
CURLINFO_SPEED_UPLOAD \- get upload speed
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_SPEED_UPLOAD, double *speed);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLINFO_SPEED_UPLOAD 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_getinfo options"

.SH NAME
CURLINFO_SPEED_UPLOAD \- get upload speed
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_SPEED_UPLOAD, double *speed);
Changes to jni/curl/docs/libcurl/opts/CURLINFO_SPEED_UPLOAD_T.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLINFO_SPEED_UPLOAD_T 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_getinfo options"

.SH NAME
CURLINFO_SPEED_UPLOAD_T \- get upload speed
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_SPEED_UPLOAD_T, curl_off_t *speed);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLINFO_SPEED_UPLOAD_T 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_getinfo options"

.SH NAME
CURLINFO_SPEED_UPLOAD_T \- get upload speed
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_SPEED_UPLOAD_T, curl_off_t *speed);
Changes to jni/curl/docs/libcurl/opts/CURLINFO_SSL_ENGINES.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLINFO_SSL_ENGINES 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_getinfo options"

.SH NAME
CURLINFO_SSL_ENGINES \- get an slist of OpenSSL crypto-engines
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_SSL_ENGINES,







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLINFO_SSL_ENGINES 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_getinfo options"

.SH NAME
CURLINFO_SSL_ENGINES \- get an slist of OpenSSL crypto-engines
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_SSL_ENGINES,
Changes to jni/curl/docs/libcurl/opts/CURLINFO_SSL_VERIFYRESULT.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLINFO_SSL_VERIFYRESULT 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_getinfo options"

.SH NAME
CURLINFO_SSL_VERIFYRESULT \- get the result of the certificate verification
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_SSL_VERIFYRESULT, long *result);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLINFO_SSL_VERIFYRESULT 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_getinfo options"

.SH NAME
CURLINFO_SSL_VERIFYRESULT \- get the result of the certificate verification
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_SSL_VERIFYRESULT, long *result);
Changes to jni/curl/docs/libcurl/opts/CURLINFO_STARTTRANSFER_TIME.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLINFO_STARTTRANSFER_TIME 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_getinfo options"

.SH NAME
CURLINFO_STARTTRANSFER_TIME \- get the time until the first byte is received
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_STARTTRANSFER_TIME, double *timep);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLINFO_STARTTRANSFER_TIME 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_getinfo options"

.SH NAME
CURLINFO_STARTTRANSFER_TIME \- get the time until the first byte is received
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_STARTTRANSFER_TIME, double *timep);
Changes to jni/curl/docs/libcurl/opts/CURLINFO_STARTTRANSFER_TIME_T.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLINFO_STARTTRANSFER_TIME_T 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_getinfo options"

.SH NAME
CURLINFO_STARTTRANSFER_TIME_T \- get the time until the first byte is received
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_STARTTRANSFER_TIME_T, curl_off_t *timep);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLINFO_STARTTRANSFER_TIME_T 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_getinfo options"

.SH NAME
CURLINFO_STARTTRANSFER_TIME_T \- get the time until the first byte is received
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_STARTTRANSFER_TIME_T, curl_off_t *timep);
Changes to jni/curl/docs/libcurl/opts/CURLINFO_TLS_SESSION.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLINFO_TLS_SESSION 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_getinfo options"

.SH NAME
CURLINFO_TLS_SESSION \- get TLS session info
.SH SYNOPSIS
.nf
#include <curl/curl.h>








|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLINFO_TLS_SESSION 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_getinfo options"

.SH NAME
CURLINFO_TLS_SESSION \- get TLS session info
.SH SYNOPSIS
.nf
#include <curl/curl.h>

Changes to jni/curl/docs/libcurl/opts/CURLINFO_TLS_SSL_PTR.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLINFO_TLS_SSL_PTR 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_getinfo options"

.SH NAME
CURLINFO_TLS_SESSION, CURLINFO_TLS_SSL_PTR \- get TLS session info
.SH SYNOPSIS
.nf
#include <curl/curl.h>








|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLINFO_TLS_SSL_PTR 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_getinfo options"

.SH NAME
CURLINFO_TLS_SESSION, CURLINFO_TLS_SSL_PTR \- get TLS session info
.SH SYNOPSIS
.nf
#include <curl/curl.h>

Changes to jni/curl/docs/libcurl/opts/CURLINFO_TOTAL_TIME.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLINFO_TOTAL_TIME 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_getinfo options"

.SH NAME
CURLINFO_TOTAL_TIME \- get total time of previous transfer
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_TOTAL_TIME, double *timep);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLINFO_TOTAL_TIME 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_getinfo options"

.SH NAME
CURLINFO_TOTAL_TIME \- get total time of previous transfer
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_TOTAL_TIME, double *timep);
Changes to jni/curl/docs/libcurl/opts/CURLINFO_TOTAL_TIME_T.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLINFO_TOTAL_TIME_T 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_getinfo options"

.SH NAME
CURLINFO_TOTAL_TIME_T \- get total time of previous transfer in microseconds
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_TOTAL_TIME_T, curl_off_t *timep);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLINFO_TOTAL_TIME_T 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_getinfo options"

.SH NAME
CURLINFO_TOTAL_TIME_T \- get total time of previous transfer in microseconds
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_TOTAL_TIME_T, curl_off_t *timep);
Changes to jni/curl/docs/libcurl/opts/CURLMOPT_CHUNK_LENGTH_PENALTY_SIZE.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLMOPT_CHUNK_LENGTH_PENALTY_SIZE 3 "November 04, 2020" "libcurl 7.74.0" "curl_multi_setopt options"

.SH NAME
CURLMOPT_CHUNK_LENGTH_PENALTY_SIZE \- chunk length threshold for pipelining
.SH SYNOPSIS
#include <curl/curl.h>

CURLMcode curl_multi_setopt(CURLM *handle, CURLMOPT_CHUNK_LENGTH_PENALTY_SIZE, long size);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLMOPT_CHUNK_LENGTH_PENALTY_SIZE 3 "November 04, 2020" "libcurl 7.75.0" "curl_multi_setopt options"

.SH NAME
CURLMOPT_CHUNK_LENGTH_PENALTY_SIZE \- chunk length threshold for pipelining
.SH SYNOPSIS
#include <curl/curl.h>

CURLMcode curl_multi_setopt(CURLM *handle, CURLMOPT_CHUNK_LENGTH_PENALTY_SIZE, long size);
Changes to jni/curl/docs/libcurl/opts/CURLMOPT_CONTENT_LENGTH_PENALTY_SIZE.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLMOPT_CONTENT_LENGTH_PENALTY_SIZE 3 "November 04, 2020" "libcurl 7.74.0" "curl_multi_setopt options"

.SH NAME
CURLMOPT_CONTENT_LENGTH_PENALTY_SIZE \- size threshold for pipelining penalty
.SH SYNOPSIS
#include <curl/curl.h>

CURLMcode curl_multi_setopt(CURLM *handle, CURLMOPT_CONTENT_LENGTH_PENALTY_SIZE, long size);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLMOPT_CONTENT_LENGTH_PENALTY_SIZE 3 "November 04, 2020" "libcurl 7.75.0" "curl_multi_setopt options"

.SH NAME
CURLMOPT_CONTENT_LENGTH_PENALTY_SIZE \- size threshold for pipelining penalty
.SH SYNOPSIS
#include <curl/curl.h>

CURLMcode curl_multi_setopt(CURLM *handle, CURLMOPT_CONTENT_LENGTH_PENALTY_SIZE, long size);
Changes to jni/curl/docs/libcurl/opts/CURLMOPT_MAXCONNECTS.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLMOPT_MAXCONNECTS 3 "November 04, 2020" "libcurl 7.74.0" "curl_multi_setopt options"

.SH NAME
CURLMOPT_MAXCONNECTS \- set size of connection cache
.SH SYNOPSIS
#include <curl/curl.h>

CURLMcode curl_multi_setopt(CURLM *handle, CURLMOPT_MAXCONNECTS, long max);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLMOPT_MAXCONNECTS 3 "November 04, 2020" "libcurl 7.75.0" "curl_multi_setopt options"

.SH NAME
CURLMOPT_MAXCONNECTS \- set size of connection cache
.SH SYNOPSIS
#include <curl/curl.h>

CURLMcode curl_multi_setopt(CURLM *handle, CURLMOPT_MAXCONNECTS, long max);
Changes to jni/curl/docs/libcurl/opts/CURLMOPT_MAX_CONCURRENT_STREAMS.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLMOPT_MAX_CONCURRENT_STREAMS 3 "November 04, 2020" "libcurl 7.74.0" "curl_multi_setopt options"

.SH NAME
CURLMOPT_MAX_CONCURRENT_STREAMS \- set max concurrent streams for http2
.SH SYNOPSIS
.nf
#include <curl/curl.h>








|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLMOPT_MAX_CONCURRENT_STREAMS 3 "November 04, 2020" "libcurl 7.75.0" "curl_multi_setopt options"

.SH NAME
CURLMOPT_MAX_CONCURRENT_STREAMS \- set max concurrent streams for http2
.SH SYNOPSIS
.nf
#include <curl/curl.h>

Changes to jni/curl/docs/libcurl/opts/CURLMOPT_MAX_HOST_CONNECTIONS.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLMOPT_MAX_HOST_CONNECTIONS 3 "November 04, 2020" "libcurl 7.74.0" "curl_multi_setopt options"

.SH NAME
CURLMOPT_MAX_HOST_CONNECTIONS \- set max number of connections to a single host
.SH SYNOPSIS
#include <curl/curl.h>

CURLMcode curl_multi_setopt(CURLM *handle, CURLMOPT_MAX_HOST_CONNECTIONS, long max);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLMOPT_MAX_HOST_CONNECTIONS 3 "November 04, 2020" "libcurl 7.75.0" "curl_multi_setopt options"

.SH NAME
CURLMOPT_MAX_HOST_CONNECTIONS \- set max number of connections to a single host
.SH SYNOPSIS
#include <curl/curl.h>

CURLMcode curl_multi_setopt(CURLM *handle, CURLMOPT_MAX_HOST_CONNECTIONS, long max);
Changes to jni/curl/docs/libcurl/opts/CURLMOPT_MAX_PIPELINE_LENGTH.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLMOPT_MAX_PIPELINE_LENGTH 3 "November 04, 2020" "libcurl 7.74.0" "curl_multi_setopt options"

.SH NAME
CURLMOPT_MAX_PIPELINE_LENGTH \- maximum number of requests in a pipeline
.SH SYNOPSIS
#include <curl/curl.h>

CURLMcode curl_multi_setopt(CURLM *handle, CURLMOPT_MAX_PIPELINE_LENGTH, long max);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLMOPT_MAX_PIPELINE_LENGTH 3 "November 04, 2020" "libcurl 7.75.0" "curl_multi_setopt options"

.SH NAME
CURLMOPT_MAX_PIPELINE_LENGTH \- maximum number of requests in a pipeline
.SH SYNOPSIS
#include <curl/curl.h>

CURLMcode curl_multi_setopt(CURLM *handle, CURLMOPT_MAX_PIPELINE_LENGTH, long max);
Changes to jni/curl/docs/libcurl/opts/CURLMOPT_MAX_TOTAL_CONNECTIONS.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLMOPT_MAX_TOTAL_CONNECTIONS 3 "November 04, 2020" "libcurl 7.74.0" "curl_multi_setopt options"

.SH NAME
CURLMOPT_MAX_TOTAL_CONNECTIONS \- max simultaneously open connections
.SH SYNOPSIS
#include <curl/curl.h>

CURLMcode curl_multi_setopt(CURLM *handle, CURLMOPT_MAX_TOTAL_CONNECTIONS, long amount);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLMOPT_MAX_TOTAL_CONNECTIONS 3 "November 04, 2020" "libcurl 7.75.0" "curl_multi_setopt options"

.SH NAME
CURLMOPT_MAX_TOTAL_CONNECTIONS \- max simultaneously open connections
.SH SYNOPSIS
#include <curl/curl.h>

CURLMcode curl_multi_setopt(CURLM *handle, CURLMOPT_MAX_TOTAL_CONNECTIONS, long amount);
Changes to jni/curl/docs/libcurl/opts/CURLMOPT_PIPELINING.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLMOPT_PIPELINING 3 "November 04, 2020" "libcurl 7.74.0" "curl_multi_setopt options"

.SH NAME
CURLMOPT_PIPELINING \- enable HTTP pipelining and multiplexing
.SH SYNOPSIS
#include <curl/curl.h>

CURLMcode curl_multi_setopt(CURLM *handle, CURLMOPT_PIPELINING, long bitmask);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLMOPT_PIPELINING 3 "November 04, 2020" "libcurl 7.75.0" "curl_multi_setopt options"

.SH NAME
CURLMOPT_PIPELINING \- enable HTTP pipelining and multiplexing
.SH SYNOPSIS
#include <curl/curl.h>

CURLMcode curl_multi_setopt(CURLM *handle, CURLMOPT_PIPELINING, long bitmask);
Changes to jni/curl/docs/libcurl/opts/CURLMOPT_PIPELINING_SERVER_BL.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLMOPT_PIPELINING_SERVER_BL 3 "November 04, 2020" "libcurl 7.74.0" "curl_multi_setopt options"

.SH NAME
CURLMOPT_PIPELINING_SERVER_BL \- pipelining server block list
.SH SYNOPSIS
#include <curl/curl.h>

CURLMcode curl_multi_setopt(CURLM *handle, CURLMOPT_PIPELINING_SERVER_BL, char **servers);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLMOPT_PIPELINING_SERVER_BL 3 "November 04, 2020" "libcurl 7.75.0" "curl_multi_setopt options"

.SH NAME
CURLMOPT_PIPELINING_SERVER_BL \- pipelining server block list
.SH SYNOPSIS
#include <curl/curl.h>

CURLMcode curl_multi_setopt(CURLM *handle, CURLMOPT_PIPELINING_SERVER_BL, char **servers);
Changes to jni/curl/docs/libcurl/opts/CURLMOPT_PIPELINING_SITE_BL.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLMOPT_PIPELINING_SITE_BL 3 "November 04, 2020" "libcurl 7.74.0" "curl_multi_setopt options"

.SH NAME
CURLMOPT_PIPELINING_SITE_BL \- pipelining host block list
.SH SYNOPSIS
#include <curl/curl.h>

CURLMcode curl_multi_setopt(CURLM *handle, CURLMOPT_PIPELINING_SITE_BL, char **hosts);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLMOPT_PIPELINING_SITE_BL 3 "November 04, 2020" "libcurl 7.75.0" "curl_multi_setopt options"

.SH NAME
CURLMOPT_PIPELINING_SITE_BL \- pipelining host block list
.SH SYNOPSIS
#include <curl/curl.h>

CURLMcode curl_multi_setopt(CURLM *handle, CURLMOPT_PIPELINING_SITE_BL, char **hosts);
Changes to jni/curl/docs/libcurl/opts/CURLMOPT_PUSHDATA.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLMOPT_PUSHDATA 3 "November 04, 2020" "libcurl 7.74.0" "curl_multi_setopt options"

.SH NAME
CURLMOPT_PUSHDATA \- pointer to pass to push callback
.SH SYNOPSIS
.nf
#include <curl/curl.h>








|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLMOPT_PUSHDATA 3 "November 04, 2020" "libcurl 7.75.0" "curl_multi_setopt options"

.SH NAME
CURLMOPT_PUSHDATA \- pointer to pass to push callback
.SH SYNOPSIS
.nf
#include <curl/curl.h>

Changes to jni/curl/docs/libcurl/opts/CURLMOPT_PUSHFUNCTION.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLMOPT_PUSHFUNCTION 3 "November 04, 2020" "libcurl 7.74.0" "curl_multi_setopt options"

.SH NAME
CURLMOPT_PUSHFUNCTION \- callback that approves or denies server pushes
.SH SYNOPSIS
.nf
#include <curl/curl.h>








|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLMOPT_PUSHFUNCTION 3 "November 04, 2020" "libcurl 7.75.0" "curl_multi_setopt options"

.SH NAME
CURLMOPT_PUSHFUNCTION \- callback that approves or denies server pushes
.SH SYNOPSIS
.nf
#include <curl/curl.h>

Changes to jni/curl/docs/libcurl/opts/CURLMOPT_SOCKETDATA.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLMOPT_SOCKETDATA 3 "November 04, 2020" "libcurl 7.74.0" "curl_multi_setopt options"

.SH NAME
CURLMOPT_SOCKETDATA \- custom pointer passed to the socket callback
.SH SYNOPSIS
.nf
#include <curl/curl.h>








|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLMOPT_SOCKETDATA 3 "November 04, 2020" "libcurl 7.75.0" "curl_multi_setopt options"

.SH NAME
CURLMOPT_SOCKETDATA \- custom pointer passed to the socket callback
.SH SYNOPSIS
.nf
#include <curl/curl.h>

Changes to jni/curl/docs/libcurl/opts/CURLMOPT_SOCKETFUNCTION.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLMOPT_SOCKETFUNCTION 3 "November 04, 2020" "libcurl 7.74.0" "curl_multi_setopt options"

.SH NAME
CURLMOPT_SOCKETFUNCTION \- callback informed about what to wait for
.SH SYNOPSIS
.nf
#include <curl/curl.h>








|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLMOPT_SOCKETFUNCTION 3 "November 04, 2020" "libcurl 7.75.0" "curl_multi_setopt options"

.SH NAME
CURLMOPT_SOCKETFUNCTION \- callback informed about what to wait for
.SH SYNOPSIS
.nf
#include <curl/curl.h>

Changes to jni/curl/docs/libcurl/opts/CURLMOPT_TIMERDATA.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLMOPT_TIMERDATA 3 "November 04, 2020" "libcurl 7.74.0" "curl_multi_setopt options"

.SH NAME
CURLMOPT_TIMERDATA \- custom pointer to pass to timer callback
.SH SYNOPSIS
.nf
#include <curl/curl.h>








|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLMOPT_TIMERDATA 3 "November 04, 2020" "libcurl 7.75.0" "curl_multi_setopt options"

.SH NAME
CURLMOPT_TIMERDATA \- custom pointer to pass to timer callback
.SH SYNOPSIS
.nf
#include <curl/curl.h>

Changes to jni/curl/docs/libcurl/opts/CURLMOPT_TIMERFUNCTION.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLMOPT_TIMERFUNCTION 3 "November 04, 2020" "libcurl 7.74.0" "curl_multi_setopt options"

.SH NAME
CURLMOPT_TIMERFUNCTION \- set callback to receive timeout values
.SH SYNOPSIS
.nf
#include <curl/curl.h>








|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLMOPT_TIMERFUNCTION 3 "November 04, 2020" "libcurl 7.75.0" "curl_multi_setopt options"

.SH NAME
CURLMOPT_TIMERFUNCTION \- set callback to receive timeout values
.SH SYNOPSIS
.nf
#include <curl/curl.h>

Changes to jni/curl/docs/libcurl/opts/CURLOPT_ABSTRACT_UNIX_SOCKET.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_ABSTRACT_UNIX_SOCKET 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_ABSTRACT_UNIX_SOCKET \- set an abstract Unix domain socket
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_ABSTRACT_UNIX_SOCKET, char *path);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_ABSTRACT_UNIX_SOCKET 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_ABSTRACT_UNIX_SOCKET \- set an abstract Unix domain socket
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_ABSTRACT_UNIX_SOCKET, char *path);
Changes to jni/curl/docs/libcurl/opts/CURLOPT_ACCEPTTIMEOUT_MS.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_ACCEPTTIMEOUT_MS 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_ACCEPTTIMEOUT_MS \- timeout waiting for FTP server to connect back
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_ACCEPTTIMEOUT_MS, long ms);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_ACCEPTTIMEOUT_MS 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_ACCEPTTIMEOUT_MS \- timeout waiting for FTP server to connect back
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_ACCEPTTIMEOUT_MS, long ms);
Changes to jni/curl/docs/libcurl/opts/CURLOPT_ACCEPT_ENCODING.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_ACCEPT_ENCODING 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_ACCEPT_ENCODING \- enables automatic decompression of HTTP downloads
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_ACCEPT_ENCODING, char *enc);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_ACCEPT_ENCODING 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_ACCEPT_ENCODING \- enables automatic decompression of HTTP downloads
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_ACCEPT_ENCODING, char *enc);
Changes to jni/curl/docs/libcurl/opts/CURLOPT_ADDRESS_SCOPE.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_ADDRESS_SCOPE 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_ADDRESS_SCOPE \- set scope id for IPv6 addresses
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_ADDRESS_SCOPE, long scope);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_ADDRESS_SCOPE 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_ADDRESS_SCOPE \- set scope id for IPv6 addresses
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_ADDRESS_SCOPE, long scope);
Changes to jni/curl/docs/libcurl/opts/CURLOPT_ALTSVC.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_ALTSVC 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_ALTSVC \- set alt-svc cache file name
.SH SYNOPSIS
.nf
#include <curl/curl.h>








|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_ALTSVC 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_ALTSVC \- set alt-svc cache file name
.SH SYNOPSIS
.nf
#include <curl/curl.h>

Changes to jni/curl/docs/libcurl/opts/CURLOPT_ALTSVC_CTRL.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_ALTSVC_CTRL 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_ALTSVC_CTRL \- control alt-svc behavior
.SH SYNOPSIS
.nf
#include <curl/curl.h>








|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_ALTSVC_CTRL 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_ALTSVC_CTRL \- control alt-svc behavior
.SH SYNOPSIS
.nf
#include <curl/curl.h>

Changes to jni/curl/docs/libcurl/opts/CURLOPT_APPEND.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_APPEND 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_APPEND \- enable appending to the remote file
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_APPEND, long append);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_APPEND 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_APPEND \- enable appending to the remote file
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_APPEND, long append);
Changes to jni/curl/docs/libcurl/opts/CURLOPT_AUTOREFERER.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_AUTOREFERER 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_AUTOREFERER \- automatically update the referer header
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_AUTOREFERER, long autorefer);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_AUTOREFERER 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_AUTOREFERER \- automatically update the referer header
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_AUTOREFERER, long autorefer);
Added jni/curl/docs/libcurl/opts/CURLOPT_AWS_SIGV4.3.




































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
.\" **************************************************************************
.\" *                                  _   _ ____  _
.\" *  Project                     ___| | | |  _ \| |
.\" *                             / __| | | | |_) | |
.\" *                            | (__| |_| |  _ <| |___
.\" *                             \___|\___/|_| \_\_____|
.\" *
.\" * Copyright (C) 1998 - 2020, 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 https://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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_AWS_SIGV4 3 "January 25, 2021" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_AWS_SIGV4 \- V4 signature
.SH SYNOPSIS
.nf
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_AWS_SIGV4, char *param);
.fi
.SH DESCRIPTION
Provides AWS V4 signature authentication on HTTP(S) header.
.PP
Pass a char * that is the collection of specific arguments are used for
creating outgoing authentication headers.
The format of the param option is:
.IP provider1[:provider2[:region[:service]]]
.IP provider1,\ provider2
The providers arguments are used for generating some authentication parameters
such as "Algorithm", "date", "request type" and "signed headers".
.IP region
The argument is a geographic area of a resources collection.
It is extracted from the host name specified in the URL if omitted.
.IP service
The argument is a function provided by a cloud.
It is extracted from the host name specified in the URL if omitted.
.PP
NOTE: This call set \fICURLOPT_HTTPAUTH(3)\fP to CURLAUTH_AWS_SIGV4.
Calling \fICURLOPT_HTTPAUTH(3)\fP with CURLAUTH_AWS_SIGV4 is the same
as calling this with "aws:amz" in parameter.
.PP
Example with "Test:Try", when curl will do the algorithm, it will generate
"TEST-HMAC-SHA256" for "Algorithm", "x-try-date" and "X-Try-Date" for "date",
"test4_request" for "request type",
"SignedHeaders=content-type;host;x-try-date" for "signed headers"
.PP
If you use just "test", instead of "test:try",
test will be use for every strings generated
.SH DEFAULT
By default, the value of this parameter is NULL.
Calling \fICURLOPT_HTTPAUTH(3)\fP with CURLAUTH_AWS_SIGV4 is the same
as calling this with "aws:amz" in parameter.
.SH PROTOCOLS
HTTP
.SH EXAMPLE
.nf
CURL *curl = curl_easy_init();

struct curl_slist *list = NULL;

if(curl) {
  curl_easy_setopt(curl, CURLOPT_URL,
                  "https://service.region.example.com/uri");
  curl_easy_setopt(c, CURLOPT_AWS_SIGV4, "provider1:provider2");

  /* service and region also could be set in CURLOPT_AWS_SIGV4 */
  /*
  curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/uri");
  curl_easy_setopt(c, CURLOPT_AWS_SIGV4,
                   "provider1:provider2:region:service");
  */

  curl_easy_setopt(c, CURLOPT_USERPWD, "MY_ACCESS_KEY:MY_SECRET_KEY");
  curl_easy_perform(curl);
}
.fi
.SH AVAILABILITY
Added in 7.75.0
.SH RETURN VALUE
Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
.SH NOTES
This option overrides the other auth types you might have set in CURL_HTTPAUTH
which should be highlighted as this makes this auth method special.
This method can't be combined with other auth types.
.SH "SEE ALSO"
.BR CURLOPT_HEADEROPT "(3), " CURLOPT_HTTPHEADER "(3), "
Changes to jni/curl/docs/libcurl/opts/CURLOPT_BUFFERSIZE.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_BUFFERSIZE 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_BUFFERSIZE \- set preferred receive buffer size
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_BUFFERSIZE, long size);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_BUFFERSIZE 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_BUFFERSIZE \- set preferred receive buffer size
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_BUFFERSIZE, long size);
Changes to jni/curl/docs/libcurl/opts/CURLOPT_CAINFO.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_CAINFO 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_CAINFO \- path to Certificate Authority (CA) bundle
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_CAINFO, char *path);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_CAINFO 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_CAINFO \- path to Certificate Authority (CA) bundle
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_CAINFO, char *path);
Changes to jni/curl/docs/libcurl/opts/CURLOPT_CAPATH.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_CAPATH 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_CAPATH \- specify directory holding CA certificates
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_CAPATH, char *capath);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_CAPATH 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_CAPATH \- specify directory holding CA certificates
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_CAPATH, char *capath);
Changes to jni/curl/docs/libcurl/opts/CURLOPT_CERTINFO.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_CERTINFO 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_CERTINFO \- request SSL certificate information
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_CERTINFO, long certinfo);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_CERTINFO 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_CERTINFO \- request SSL certificate information
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_CERTINFO, long certinfo);
Changes to jni/curl/docs/libcurl/opts/CURLOPT_CHUNK_BGN_FUNCTION.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_CHUNK_BGN_FUNCTION 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_CHUNK_BGN_FUNCTION \- callback before a transfer with FTP wildcardmatch
.SH SYNOPSIS
.nf
#include <curl/curl.h>








|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_CHUNK_BGN_FUNCTION 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_CHUNK_BGN_FUNCTION \- callback before a transfer with FTP wildcardmatch
.SH SYNOPSIS
.nf
#include <curl/curl.h>

Changes to jni/curl/docs/libcurl/opts/CURLOPT_CHUNK_DATA.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_CHUNK_DATA 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_CHUNK_DATA \- custom pointer to the FTP chunk callbacks
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_CHUNK_DATA, void *pointer);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_CHUNK_DATA 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_CHUNK_DATA \- custom pointer to the FTP chunk callbacks
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_CHUNK_DATA, void *pointer);
Changes to jni/curl/docs/libcurl/opts/CURLOPT_CHUNK_END_FUNCTION.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_CHUNK_END_FUNCTION 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_CHUNK_END_FUNCTION \- callback after a transfer with FTP wildcardmatch
.SH SYNOPSIS
.nf
#include <curl/curl.h>








|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_CHUNK_END_FUNCTION 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_CHUNK_END_FUNCTION \- callback after a transfer with FTP wildcardmatch
.SH SYNOPSIS
.nf
#include <curl/curl.h>

Changes to jni/curl/docs/libcurl/opts/CURLOPT_CLOSESOCKETDATA.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_CLOSESOCKETDATA 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_CLOSESOCKETDATA \- pointer passed to the socket close callback
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_CLOSESOCKETDATA, void *pointer);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_CLOSESOCKETDATA 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_CLOSESOCKETDATA \- pointer passed to the socket close callback
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_CLOSESOCKETDATA, void *pointer);
Changes to jni/curl/docs/libcurl/opts/CURLOPT_CLOSESOCKETFUNCTION.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_CLOSESOCKETFUNCTION 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_CLOSESOCKETFUNCTION \- callback to socket close replacement function
.SH SYNOPSIS
#include <curl/curl.h>

int closesocket_callback(void *clientp, curl_socket_t item);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_CLOSESOCKETFUNCTION 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_CLOSESOCKETFUNCTION \- callback to socket close replacement function
.SH SYNOPSIS
#include <curl/curl.h>

int closesocket_callback(void *clientp, curl_socket_t item);
Changes to jni/curl/docs/libcurl/opts/CURLOPT_CONNECTTIMEOUT.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_CONNECTTIMEOUT 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_CONNECTTIMEOUT \- timeout for the connect phase
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_CONNECTTIMEOUT, long timeout);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_CONNECTTIMEOUT 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_CONNECTTIMEOUT \- timeout for the connect phase
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_CONNECTTIMEOUT, long timeout);
Changes to jni/curl/docs/libcurl/opts/CURLOPT_CONNECTTIMEOUT_MS.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_CONNECTTIMEOUT_MS 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_CONNECTTIMEOUT_MS \- timeout for the connect phase
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_CONNECTTIMEOUT_MS, long timeout);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_CONNECTTIMEOUT_MS 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_CONNECTTIMEOUT_MS \- timeout for the connect phase
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_CONNECTTIMEOUT_MS, long timeout);
Changes to jni/curl/docs/libcurl/opts/CURLOPT_CONNECT_ONLY.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_CONNECT_ONLY 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_CONNECT_ONLY \- stop when connected to target server
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_CONNECT_ONLY, long only);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_CONNECT_ONLY 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_CONNECT_ONLY \- stop when connected to target server
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_CONNECT_ONLY, long only);
Changes to jni/curl/docs/libcurl/opts/CURLOPT_CONNECT_TO.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_CONNECT_TO 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_CONNECT_TO \- Connect to a specific host and port instead of the URL's host and port
.SH SYNOPSIS
.nf
#include <curl/curl.h>








|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_CONNECT_TO 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_CONNECT_TO \- Connect to a specific host and port instead of the URL's host and port
.SH SYNOPSIS
.nf
#include <curl/curl.h>

Changes to jni/curl/docs/libcurl/opts/CURLOPT_CONV_FROM_NETWORK_FUNCTION.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_CONV_FROM_NETWORK_FUNCTION 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_CONV_FROM_NETWORK_FUNCTION \- convert data from network to host encoding
.SH SYNOPSIS
.nf
#include <curl/curl.h>








|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_CONV_FROM_NETWORK_FUNCTION 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_CONV_FROM_NETWORK_FUNCTION \- convert data from network to host encoding
.SH SYNOPSIS
.nf
#include <curl/curl.h>

Changes to jni/curl/docs/libcurl/opts/CURLOPT_CONV_FROM_UTF8_FUNCTION.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_CONV_FROM_UTF8_FUNCTION 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_CONV_FROM_UTF8_FUNCTION \- convert data from UTF8 to host encoding
.SH SYNOPSIS
.nf
#include <curl/curl.h>








|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_CONV_FROM_UTF8_FUNCTION 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_CONV_FROM_UTF8_FUNCTION \- convert data from UTF8 to host encoding
.SH SYNOPSIS
.nf
#include <curl/curl.h>

Changes to jni/curl/docs/libcurl/opts/CURLOPT_CONV_TO_NETWORK_FUNCTION.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_CONV_TO_NETWORK_FUNCTION 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_CONV_TO_NETWORK_FUNCTION \- convert data to network from host encoding
.SH SYNOPSIS
.nf
#include <curl/curl.h>








|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_CONV_TO_NETWORK_FUNCTION 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_CONV_TO_NETWORK_FUNCTION \- convert data to network from host encoding
.SH SYNOPSIS
.nf
#include <curl/curl.h>

Changes to jni/curl/docs/libcurl/opts/CURLOPT_COOKIE.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_COOKIE 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_COOKIE \- set contents of HTTP Cookie header
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_COOKIE, char *cookie);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_COOKIE 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_COOKIE \- set contents of HTTP Cookie header
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_COOKIE, char *cookie);
Changes to jni/curl/docs/libcurl/opts/CURLOPT_COOKIEFILE.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_COOKIEFILE 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_COOKIEFILE \- file name to read cookies from
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_COOKIEFILE, char *filename);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_COOKIEFILE 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_COOKIEFILE \- file name to read cookies from
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_COOKIEFILE, char *filename);
Changes to jni/curl/docs/libcurl/opts/CURLOPT_COOKIEJAR.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_COOKIEJAR 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_COOKIEJAR \- file name to store cookies to
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_COOKIEJAR, char *filename);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_COOKIEJAR 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_COOKIEJAR \- file name to store cookies to
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_COOKIEJAR, char *filename);
Changes to jni/curl/docs/libcurl/opts/CURLOPT_COOKIELIST.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_COOKIELIST 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_COOKIELIST \- add to or manipulate cookies held in memory
.SH SYNOPSIS
.nf
#include <curl/curl.h>








|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_COOKIELIST 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_COOKIELIST \- add to or manipulate cookies held in memory
.SH SYNOPSIS
.nf
#include <curl/curl.h>

Changes to jni/curl/docs/libcurl/opts/CURLOPT_COOKIESESSION.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_COOKIESESSION 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_COOKIESESSION \- start a new cookie session
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_COOKIESESSION, long init);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_COOKIESESSION 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_COOKIESESSION \- start a new cookie session
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_COOKIESESSION, long init);
Changes to jni/curl/docs/libcurl/opts/CURLOPT_COPYPOSTFIELDS.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_COPYPOSTFIELDS 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_COPYPOSTFIELDS \- have libcurl copy data to POST
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_COPYPOSTFIELDS, char *data);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_COPYPOSTFIELDS 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_COPYPOSTFIELDS \- have libcurl copy data to POST
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_COPYPOSTFIELDS, char *data);
Changes to jni/curl/docs/libcurl/opts/CURLOPT_CRLF.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_CRLF 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_CRLF \- enable/disable CRLF conversion
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_CRLF, long conv);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_CRLF 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_CRLF \- enable/disable CRLF conversion
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_CRLF, long conv);
Changes to jni/curl/docs/libcurl/opts/CURLOPT_CRLFILE.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_CRLFILE 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_CRLFILE \- specify a Certificate Revocation List file
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_CRLFILE, char *file);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_CRLFILE 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_CRLFILE \- specify a Certificate Revocation List file
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_CRLFILE, char *file);
Changes to jni/curl/docs/libcurl/opts/CURLOPT_CURLU.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_CURLU 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_CURLU \- set URL with CURLU *
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_CURLU, void *pointer);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_CURLU 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_CURLU \- set URL with CURLU *
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_CURLU, void *pointer);
Changes to jni/curl/docs/libcurl/opts/CURLOPT_CUSTOMREQUEST.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_CUSTOMREQUEST 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_CUSTOMREQUEST \- custom string for request
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_CUSTOMREQUEST, char *request);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_CUSTOMREQUEST 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_CUSTOMREQUEST \- custom string for request
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_CUSTOMREQUEST, char *request);
Changes to jni/curl/docs/libcurl/opts/CURLOPT_DEBUGDATA.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_DEBUGDATA 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_DEBUGDATA \- custom pointer for debug callback
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_DEBUGDATA, void *pointer);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_DEBUGDATA 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_DEBUGDATA \- custom pointer for debug callback
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_DEBUGDATA, void *pointer);
Changes to jni/curl/docs/libcurl/opts/CURLOPT_DEBUGFUNCTION.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_DEBUGFUNCTION 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_DEBUGFUNCTION \- debug callback
.SH SYNOPSIS
.nf
#include <curl/curl.h>








|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_DEBUGFUNCTION 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_DEBUGFUNCTION \- debug callback
.SH SYNOPSIS
.nf
#include <curl/curl.h>

Changes to jni/curl/docs/libcurl/opts/CURLOPT_DEFAULT_PROTOCOL.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_DEFAULT_PROTOCOL 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_DEFAULT_PROTOCOL \- default protocol to use if the URL is missing a
scheme name
.SH SYNOPSIS
#include <curl/curl.h>








|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_DEFAULT_PROTOCOL 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_DEFAULT_PROTOCOL \- default protocol to use if the URL is missing a
scheme name
.SH SYNOPSIS
#include <curl/curl.h>

Changes to jni/curl/docs/libcurl/opts/CURLOPT_DIRLISTONLY.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_DIRLISTONLY 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_DIRLISTONLY \- ask for names only in a directory listing
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_DIRLISTONLY, long listonly);
.SH DESCRIPTION
For FTP and SFTP based URLs a parameter set to 1 tells the library to list the
names of files in a directory, rather than performing a full directory listing
that would normally include file sizes, dates etc.

For POP3 a parameter of 1 tells the library to list the email message or
messages on the POP3 server. This can be used to change the default behaviour
of libcurl, when combined with a URL that contains a message ID, to perform a
"scan listing" which can then be used to determine the size of an email.

Note: For FTP this causes a NLST command to be sent to the FTP server.  Beware
that some FTP servers list only files in their response to NLST; they might not
include subdirectories and symbolic links.








|













|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_DIRLISTONLY 3 "December 31, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_DIRLISTONLY \- ask for names only in a directory listing
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_DIRLISTONLY, long listonly);
.SH DESCRIPTION
For FTP and SFTP based URLs a parameter set to 1 tells the library to list the
names of files in a directory, rather than performing a full directory listing
that would normally include file sizes, dates etc.

For POP3 a parameter of 1 tells the library to list the email message or
messages on the POP3 server. This can be used to change the default behavior
of libcurl, when combined with a URL that contains a message ID, to perform a
"scan listing" which can then be used to determine the size of an email.

Note: For FTP this causes a NLST command to be sent to the FTP server.  Beware
that some FTP servers list only files in their response to NLST; they might not
include subdirectories and symbolic links.

Changes to jni/curl/docs/libcurl/opts/CURLOPT_DISALLOW_USERNAME_IN_URL.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_DISALLOW_USERNAME_IN_URL 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_DISALLOW_USERNAME_IN_URL \- disallow specifying username in the url
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_DISALLOW_USERNAME_IN_URL, long disallow);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_DISALLOW_USERNAME_IN_URL 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_DISALLOW_USERNAME_IN_URL \- disallow specifying username in the url
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_DISALLOW_USERNAME_IN_URL, long disallow);
Changes to jni/curl/docs/libcurl/opts/CURLOPT_DNS_CACHE_TIMEOUT.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_DNS_CACHE_TIMEOUT 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_DNS_CACHE_TIMEOUT \- set life-time for DNS cache entries
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_DNS_CACHE_TIMEOUT, long age);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_DNS_CACHE_TIMEOUT 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_DNS_CACHE_TIMEOUT \- set life-time for DNS cache entries
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_DNS_CACHE_TIMEOUT, long age);
Changes to jni/curl/docs/libcurl/opts/CURLOPT_DNS_INTERFACE.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_DNS_INTERFACE 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_DNS_INTERFACE \- set interface to speak DNS over
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_DNS_INTERFACE, char *ifname);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_DNS_INTERFACE 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_DNS_INTERFACE \- set interface to speak DNS over
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_DNS_INTERFACE, char *ifname);
Changes to jni/curl/docs/libcurl/opts/CURLOPT_DNS_LOCAL_IP4.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_DNS_LOCAL_IP4 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_DNS_LOCAL_IP4 \- IPv4 address to bind DNS resolves to
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_DNS_LOCAL_IP4, char *address);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_DNS_LOCAL_IP4 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_DNS_LOCAL_IP4 \- IPv4 address to bind DNS resolves to
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_DNS_LOCAL_IP4, char *address);
Changes to jni/curl/docs/libcurl/opts/CURLOPT_DNS_LOCAL_IP6.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_DNS_LOCAL_IP6 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_DNS_LOCAL_IP6 \- IPv6 address to bind DNS resolves to
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_DNS_LOCAL_IP6, char *address);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_DNS_LOCAL_IP6 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_DNS_LOCAL_IP6 \- IPv6 address to bind DNS resolves to
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_DNS_LOCAL_IP6, char *address);
Changes to jni/curl/docs/libcurl/opts/CURLOPT_DNS_SERVERS.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_DNS_SERVERS 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_DNS_SERVERS \- set preferred DNS servers
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_DNS_SERVERS, char *servers);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_DNS_SERVERS 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_DNS_SERVERS \- set preferred DNS servers
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_DNS_SERVERS, char *servers);
Changes to jni/curl/docs/libcurl/opts/CURLOPT_DNS_SHUFFLE_ADDRESSES.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_DNS_SHUFFLE_ADDRESSES 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_DNS_SHUFFLE_ADDRESSES \- Shuffle addresses when a hostname returns more than one
.SH SYNOPSIS
.nf
#include <curl/curl.h>








|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_DNS_SHUFFLE_ADDRESSES 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_DNS_SHUFFLE_ADDRESSES \- Shuffle addresses when a hostname returns more than one
.SH SYNOPSIS
.nf
#include <curl/curl.h>

Changes to jni/curl/docs/libcurl/opts/CURLOPT_DNS_USE_GLOBAL_CACHE.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_DNS_USE_GLOBAL_CACHE 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_DNS_USE_GLOBAL_CACHE \- enable/disable global DNS cache
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_DNS_USE_GLOBAL_CACHE,







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_DNS_USE_GLOBAL_CACHE 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_DNS_USE_GLOBAL_CACHE \- enable/disable global DNS cache
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_DNS_USE_GLOBAL_CACHE,
Changes to jni/curl/docs/libcurl/opts/CURLOPT_DOH_URL.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_DOH_URL 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_DOH_URL \- provide the DNS-over-HTTPS URL
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_DOH_URL, char *URL);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_DOH_URL 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_DOH_URL \- provide the DNS-over-HTTPS URL
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_DOH_URL, char *URL);
Changes to jni/curl/docs/libcurl/opts/CURLOPT_EGDSOCKET.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_EGDSOCKET 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_EGDSOCKET \- set EGD socket path
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_EGDSOCKET, char *path);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_EGDSOCKET 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_EGDSOCKET \- set EGD socket path
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_EGDSOCKET, char *path);
Changes to jni/curl/docs/libcurl/opts/CURLOPT_ERRORBUFFER.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_ERRORBUFFER 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_ERRORBUFFER \- set error buffer for error messages
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_ERRORBUFFER, char *buf);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_ERRORBUFFER 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_ERRORBUFFER \- set error buffer for error messages
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_ERRORBUFFER, char *buf);
Changes to jni/curl/docs/libcurl/opts/CURLOPT_EXPECT_100_TIMEOUT_MS.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_EXPECT_100_TIMEOUT_MS 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_EXPECT_100_TIMEOUT_MS \- timeout for Expect: 100-continue response
.SH SYNOPSIS
.nf
#include <curl/curl.h>








|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_EXPECT_100_TIMEOUT_MS 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_EXPECT_100_TIMEOUT_MS \- timeout for Expect: 100-continue response
.SH SYNOPSIS
.nf
#include <curl/curl.h>

Changes to jni/curl/docs/libcurl/opts/CURLOPT_FAILONERROR.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_FAILONERROR 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_FAILONERROR \- request failure on HTTP response >= 400
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_FAILONERROR, long fail);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_FAILONERROR 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_FAILONERROR \- request failure on HTTP response >= 400
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_FAILONERROR, long fail);
Changes to jni/curl/docs/libcurl/opts/CURLOPT_FILETIME.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_FILETIME 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_FILETIME \- get the modification time of the remote resource
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_FILETIME, long gettime);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_FILETIME 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_FILETIME \- get the modification time of the remote resource
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_FILETIME, long gettime);
Changes to jni/curl/docs/libcurl/opts/CURLOPT_FNMATCH_DATA.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_FNMATCH_DATA 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_FNMATCH_DATA \- custom pointer to fnmatch callback
.SH SYNOPSIS
.nf
#include <curl/curl.h>








|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_FNMATCH_DATA 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_FNMATCH_DATA \- custom pointer to fnmatch callback
.SH SYNOPSIS
.nf
#include <curl/curl.h>

Changes to jni/curl/docs/libcurl/opts/CURLOPT_FNMATCH_FUNCTION.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_FNMATCH_FUNCTION 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_FNMATCH_FUNCTION \- wildcard matching function callback
.SH SYNOPSIS
.nf
#include <curl/curl.h>








|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_FNMATCH_FUNCTION 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_FNMATCH_FUNCTION \- wildcard matching function callback
.SH SYNOPSIS
.nf
#include <curl/curl.h>

Changes to jni/curl/docs/libcurl/opts/CURLOPT_FOLLOWLOCATION.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_FOLLOWLOCATION 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_FOLLOWLOCATION \- follow HTTP 3xx redirects
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_FOLLOWLOCATION, long enable);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_FOLLOWLOCATION 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_FOLLOWLOCATION \- follow HTTP 3xx redirects
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_FOLLOWLOCATION, long enable);
Changes to jni/curl/docs/libcurl/opts/CURLOPT_FORBID_REUSE.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_FORBID_REUSE 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_FORBID_REUSE \- make connection get closed at once after use
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_FORBID_REUSE, long close);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_FORBID_REUSE 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_FORBID_REUSE \- make connection get closed at once after use
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_FORBID_REUSE, long close);
Changes to jni/curl/docs/libcurl/opts/CURLOPT_FRESH_CONNECT.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_FRESH_CONNECT 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_FRESH_CONNECT \- force a new connection to be used
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_FRESH_CONNECT, long fresh);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_FRESH_CONNECT 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_FRESH_CONNECT \- force a new connection to be used
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_FRESH_CONNECT, long fresh);
Changes to jni/curl/docs/libcurl/opts/CURLOPT_FTPPORT.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_FTPPORT 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_FTPPORT \- make FTP transfer active
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_FTPPORT, char *spec);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_FTPPORT 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_FTPPORT \- make FTP transfer active
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_FTPPORT, char *spec);
Changes to jni/curl/docs/libcurl/opts/CURLOPT_FTPSSLAUTH.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_FTPSSLAUTH 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_FTPSSLAUTH \- set order in which to attempt TLS vs SSL when using FTP
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_FTPSSLAUTH, long order);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_FTPSSLAUTH 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_FTPSSLAUTH \- set order in which to attempt TLS vs SSL when using FTP
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_FTPSSLAUTH, long order);
Changes to jni/curl/docs/libcurl/opts/CURLOPT_FTP_ACCOUNT.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_FTP_ACCOUNT 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_FTP_ACCOUNT \- set account info for FTP
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_FTP_ACCOUNT, char *account);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_FTP_ACCOUNT 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_FTP_ACCOUNT \- set account info for FTP
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_FTP_ACCOUNT, char *account);
Changes to jni/curl/docs/libcurl/opts/CURLOPT_FTP_ALTERNATIVE_TO_USER.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_FTP_ALTERNATIVE_TO_USER 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_FTP_ALTERNATIVE_TO_USER \- command to use instead of USER with FTP
.SH SYNOPSIS
.nf
#include <curl/curl.h>








|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_FTP_ALTERNATIVE_TO_USER 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_FTP_ALTERNATIVE_TO_USER \- command to use instead of USER with FTP
.SH SYNOPSIS
.nf
#include <curl/curl.h>

Changes to jni/curl/docs/libcurl/opts/CURLOPT_FTP_CREATE_MISSING_DIRS.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_FTP_CREATE_MISSING_DIRS 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_FTP_CREATE_MISSING_DIRS \- create missing dirs for FTP and SFTP
.SH SYNOPSIS
.nf
#include <curl/curl.h>








|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_FTP_CREATE_MISSING_DIRS 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_FTP_CREATE_MISSING_DIRS \- create missing dirs for FTP and SFTP
.SH SYNOPSIS
.nf
#include <curl/curl.h>

Changes to jni/curl/docs/libcurl/opts/CURLOPT_FTP_FILEMETHOD.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_FTP_FILEMETHOD 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_FTP_FILEMETHOD \- select directory traversing method for FTP
.SH SYNOPSIS
.nf
#include <curl/curl.h>








|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_FTP_FILEMETHOD 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_FTP_FILEMETHOD \- select directory traversing method for FTP
.SH SYNOPSIS
.nf
#include <curl/curl.h>

Changes to jni/curl/docs/libcurl/opts/CURLOPT_FTP_RESPONSE_TIMEOUT.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_FTP_RESPONSE_TIMEOUT 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_FTP_RESPONSE_TIMEOUT \- time allowed to wait for FTP response
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_FTP_RESPONSE_TIMEOUT, long timeout);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_FTP_RESPONSE_TIMEOUT 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_FTP_RESPONSE_TIMEOUT \- time allowed to wait for FTP response
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_FTP_RESPONSE_TIMEOUT, long timeout);
Changes to jni/curl/docs/libcurl/opts/CURLOPT_FTP_SKIP_PASV_IP.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_FTP_SKIP_PASV_IP 3 "November 24, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_FTP_SKIP_PASV_IP \- ignore the IP address in the PASV response
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_FTP_SKIP_PASV_IP, long skip);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_FTP_SKIP_PASV_IP 3 "November 24, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_FTP_SKIP_PASV_IP \- ignore the IP address in the PASV response
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_FTP_SKIP_PASV_IP, long skip);
Changes to jni/curl/docs/libcurl/opts/CURLOPT_FTP_SSL_CCC.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_FTP_SSL_CCC 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_FTP_SSL_CCC \- switch off SSL again with FTP after auth
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_FTP_SSL_CCC,







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_FTP_SSL_CCC 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_FTP_SSL_CCC \- switch off SSL again with FTP after auth
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_FTP_SSL_CCC,
Changes to jni/curl/docs/libcurl/opts/CURLOPT_FTP_USE_EPRT.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_FTP_USE_EPRT 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_FTP_USE_EPRT \- enable/disable use of EPRT with FTP
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_FTP_USE_EPRT, long enabled);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_FTP_USE_EPRT 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_FTP_USE_EPRT \- enable/disable use of EPRT with FTP
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_FTP_USE_EPRT, long enabled);
Changes to jni/curl/docs/libcurl/opts/CURLOPT_FTP_USE_EPSV.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_FTP_USE_EPSV 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_FTP_USE_EPSV \- enable/disable use of EPSV
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_FTP_USE_EPSV, long epsv);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_FTP_USE_EPSV 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_FTP_USE_EPSV \- enable/disable use of EPSV
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_FTP_USE_EPSV, long epsv);
Changes to jni/curl/docs/libcurl/opts/CURLOPT_FTP_USE_PRET.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_FTP_USE_PRET 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_FTP_USE_PRET \- enable the PRET command
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_FTP_USE_PRET, long enable);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_FTP_USE_PRET 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_FTP_USE_PRET \- enable the PRET command
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_FTP_USE_PRET, long enable);
Changes to jni/curl/docs/libcurl/opts/CURLOPT_GSSAPI_DELEGATION.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_GSSAPI_DELEGATION 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_GSSAPI_DELEGATION \- set allowed GSS-API delegation
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_GSSAPI_DELEGATION, long level);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_GSSAPI_DELEGATION 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_GSSAPI_DELEGATION \- set allowed GSS-API delegation
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_GSSAPI_DELEGATION, long level);
Changes to jni/curl/docs/libcurl/opts/CURLOPT_HAPPY_EYEBALLS_TIMEOUT_MS.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_HAPPY_EYEBALLS_TIMEOUT_MS 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_HAPPY_EYEBALLS_TIMEOUT_MS \- head start for ipv6 for happy eyeballs
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_HAPPY_EYEBALLS_TIMEOUT_MS, long timeout);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_HAPPY_EYEBALLS_TIMEOUT_MS 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_HAPPY_EYEBALLS_TIMEOUT_MS \- head start for ipv6 for happy eyeballs
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_HAPPY_EYEBALLS_TIMEOUT_MS, long timeout);
Changes to jni/curl/docs/libcurl/opts/CURLOPT_HAPROXYPROTOCOL.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_HAPROXYPROTOCOL 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_HAPROXYPROTOCOL \- send HAProxy PROXY protocol v1 header
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_HAPROXYPROTOCOL,







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_HAPROXYPROTOCOL 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_HAPROXYPROTOCOL \- send HAProxy PROXY protocol v1 header
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_HAPROXYPROTOCOL,
Changes to jni/curl/docs/libcurl/opts/CURLOPT_HEADER.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_HEADER 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_HEADER \- pass headers to the data stream
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_HEADER, long onoff);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_HEADER 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_HEADER \- pass headers to the data stream
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_HEADER, long onoff);
Changes to jni/curl/docs/libcurl/opts/CURLOPT_HEADERDATA.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_HEADERDATA 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_HEADERDATA \- pointer to pass to header callback
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_HEADERDATA, void *pointer);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_HEADERDATA 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_HEADERDATA \- pointer to pass to header callback
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_HEADERDATA, void *pointer);
Changes to jni/curl/docs/libcurl/opts/CURLOPT_HEADERFUNCTION.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_HEADERFUNCTION 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_HEADERFUNCTION \- callback that receives header data
.SH SYNOPSIS
#include <curl/curl.h>

size_t header_callback(char *buffer,







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_HEADERFUNCTION 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_HEADERFUNCTION \- callback that receives header data
.SH SYNOPSIS
#include <curl/curl.h>

size_t header_callback(char *buffer,
Changes to jni/curl/docs/libcurl/opts/CURLOPT_HEADEROPT.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_HEADEROPT 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_HEADEROPT \- set how to send HTTP headers
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_HEADEROPT, long bitmask);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_HEADEROPT 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_HEADEROPT \- set how to send HTTP headers
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_HEADEROPT, long bitmask);
Changes to jni/curl/docs/libcurl/opts/CURLOPT_HSTS.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_HSTS 3 "November 13, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_HSTS \- set HSTS cache file name
.SH SYNOPSIS
.nf
#include <curl/curl.h>








|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_HSTS 3 "November 13, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_HSTS \- set HSTS cache file name
.SH SYNOPSIS
.nf
#include <curl/curl.h>

Changes to jni/curl/docs/libcurl/opts/CURLOPT_HSTSREADDATA.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_HSTSREADDATA 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_HSTSREADDATA \- pointer passed to the HSTS read callback
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_HSTSREADDATA, void *pointer);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_HSTSREADDATA 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_HSTSREADDATA \- pointer passed to the HSTS read callback
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_HSTSREADDATA, void *pointer);
Changes to jni/curl/docs/libcurl/opts/CURLOPT_HSTSREADFUNCTION.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_HSTSREADFUNCTION 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_HSTSREADFUNCTION \- read callback for HSTS hosts
.SH SYNOPSIS
#include <curl/curl.h>

CURLSTScode hstsread(CURL *easy, struct curl_hstsentry *sts, void *userp);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_HSTSREADFUNCTION 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_HSTSREADFUNCTION \- read callback for HSTS hosts
.SH SYNOPSIS
#include <curl/curl.h>

CURLSTScode hstsread(CURL *easy, struct curl_hstsentry *sts, void *userp);
Changes to jni/curl/docs/libcurl/opts/CURLOPT_HSTSWRITEDATA.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_HSTSWRITEDATA 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_HSTSWRITEDATA \- pointer passed to the HSTS write callback
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_HSTSWRITEDATA, void *pointer);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_HSTSWRITEDATA 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_HSTSWRITEDATA \- pointer passed to the HSTS write callback
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_HSTSWRITEDATA, void *pointer);
Changes to jni/curl/docs/libcurl/opts/CURLOPT_HSTSWRITEFUNCTION.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_HSTSWRITEFUNCTION 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_HSTSWRITEFUNCTION \- write callback for HSTS hosts
.SH SYNOPSIS
#include <curl/curl.h>

CURLSTScode hstswrite(CURL *easy, struct curl_hstsentry *sts,







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_HSTSWRITEFUNCTION 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_HSTSWRITEFUNCTION \- write callback for HSTS hosts
.SH SYNOPSIS
#include <curl/curl.h>

CURLSTScode hstswrite(CURL *easy, struct curl_hstsentry *sts,
Changes to jni/curl/docs/libcurl/opts/CURLOPT_HSTS_CTRL.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_HSTS_CTRL 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_HSTS_CTRL \- control HSTS behavior
.SH SYNOPSIS
.nf
#include <curl/curl.h>








|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_HSTS_CTRL 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_HSTS_CTRL \- control HSTS behavior
.SH SYNOPSIS
.nf
#include <curl/curl.h>

Changes to jni/curl/docs/libcurl/opts/CURLOPT_HTTP09_ALLOWED.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_HTTP09_ALLOWED 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_HTTP09 \- allow HTTP/0.9 response
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_HTTP09_ALLOWED, long allowed);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_HTTP09_ALLOWED 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_HTTP09 \- allow HTTP/0.9 response
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_HTTP09_ALLOWED, long allowed);
Changes to jni/curl/docs/libcurl/opts/CURLOPT_HTTP200ALIASES.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_HTTP200ALIASES 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_HTTP200ALIASES \- specify alternative matches for HTTP 200 OK
.SH SYNOPSIS
.nf
#include <curl/curl.h>








|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_HTTP200ALIASES 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_HTTP200ALIASES \- specify alternative matches for HTTP 200 OK
.SH SYNOPSIS
.nf
#include <curl/curl.h>

Changes to jni/curl/docs/libcurl/opts/CURLOPT_HTTPAUTH.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_HTTPAUTH 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_HTTPAUTH \- set HTTP server authentication methods to try
.SH SYNOPSIS
.nf
#include <curl/curl.h>








|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_HTTPAUTH 3 "July 03, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_HTTPAUTH \- set HTTP server authentication methods to try
.SH SYNOPSIS
.nf
#include <curl/curl.h>

95
96
97
98
99
100
101



102
103
104
105
106
107
108
This is a convenience macro that sets all bits except Basic and thus makes
libcurl pick any it finds suitable. libcurl will automatically select the one
it finds most secure.
.IP CURLAUTH_ONLY
This is a meta symbol. OR this value together with a single specific auth
value to force libcurl to probe for un-restricted auth and if not, only that
single auth algorithm is acceptable.



.SH DEFAULT
CURLAUTH_BASIC
.SH PROTOCOLS
HTTP
.SH EXAMPLE
.nf
CURL *curl = curl_easy_init();







>
>
>







95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
This is a convenience macro that sets all bits except Basic and thus makes
libcurl pick any it finds suitable. libcurl will automatically select the one
it finds most secure.
.IP CURLAUTH_ONLY
This is a meta symbol. OR this value together with a single specific auth
value to force libcurl to probe for un-restricted auth and if not, only that
single auth algorithm is acceptable.
.IP CURLAUTH_AWS_SIGV4
provides AWS V4 signature authentication on HTTPS header
see \fICURLOPT_AWS_SIGV4(3)\fP.
.SH DEFAULT
CURLAUTH_BASIC
.SH PROTOCOLS
HTTP
.SH EXAMPLE
.nf
CURL *curl = curl_easy_init();
121
122
123
124
125
126
127


128
129
130
131
132
133
CURLAUTH_DIGEST_IE was added in 7.19.3

CURLAUTH_ONLY was added in 7.21.3

CURLAUTH_NTLM_WB was added in 7.22.0

CURLAUTH_BEARER was added in 7.61.0


.SH RETURN VALUE
Returns CURLE_OK if the option is supported, CURLE_UNKNOWN_OPTION if not, or
CURLE_NOT_BUILT_IN if the bitmask specified no supported authentication
methods.
.SH "SEE ALSO"
.BR CURLOPT_PROXYAUTH "(3), " CURLOPT_USERPWD "(3), "







>
>






124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
CURLAUTH_DIGEST_IE was added in 7.19.3

CURLAUTH_ONLY was added in 7.21.3

CURLAUTH_NTLM_WB was added in 7.22.0

CURLAUTH_BEARER was added in 7.61.0

CURLAUTH_AWS_SIGV4 was added in 7.74.0
.SH RETURN VALUE
Returns CURLE_OK if the option is supported, CURLE_UNKNOWN_OPTION if not, or
CURLE_NOT_BUILT_IN if the bitmask specified no supported authentication
methods.
.SH "SEE ALSO"
.BR CURLOPT_PROXYAUTH "(3), " CURLOPT_USERPWD "(3), "
Changes to jni/curl/docs/libcurl/opts/CURLOPT_HTTPGET.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_HTTPGET 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_HTTPGET \- ask for an HTTP GET request
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_HTTPGET, long useget);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_HTTPGET 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_HTTPGET \- ask for an HTTP GET request
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_HTTPGET, long useget);
Changes to jni/curl/docs/libcurl/opts/CURLOPT_HTTPHEADER.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_HTTPHEADER 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_HTTPHEADER \- set custom HTTP headers
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_HTTPHEADER, struct curl_slist *headers);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_HTTPHEADER 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_HTTPHEADER \- set custom HTTP headers
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_HTTPHEADER, struct curl_slist *headers);
Changes to jni/curl/docs/libcurl/opts/CURLOPT_HTTPPOST.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_HTTPPOST 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_HTTPPOST \- specify the multipart formpost content
.SH SYNOPSIS
.nf
#include <curl/curl.h>








|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_HTTPPOST 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_HTTPPOST \- specify the multipart formpost content
.SH SYNOPSIS
.nf
#include <curl/curl.h>

Changes to jni/curl/docs/libcurl/opts/CURLOPT_HTTPPROXYTUNNEL.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_HTTPPROXYTUNNEL 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_HTTPPROXYTUNNEL \- tunnel through HTTP proxy
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_HTTPPROXYTUNNEL, long tunnel);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_HTTPPROXYTUNNEL 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_HTTPPROXYTUNNEL \- tunnel through HTTP proxy
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_HTTPPROXYTUNNEL, long tunnel);
Changes to jni/curl/docs/libcurl/opts/CURLOPT_HTTP_CONTENT_DECODING.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_HTTP_CONTENT_DECODING 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_HTTP_CONTENT_DECODING \- enable/disable HTTP content decoding
.SH SYNOPSIS
.nf
#include <curl/curl.h>








|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_HTTP_CONTENT_DECODING 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_HTTP_CONTENT_DECODING \- enable/disable HTTP content decoding
.SH SYNOPSIS
.nf
#include <curl/curl.h>

Changes to jni/curl/docs/libcurl/opts/CURLOPT_HTTP_TRANSFER_DECODING.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_HTTP_TRANSFER_DECODING 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_HTTP_TRANSFER_DECODING \- enable/disable HTTP transfer decoding
.SH SYNOPSIS
.nf
#include <curl/curl.h>








|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_HTTP_TRANSFER_DECODING 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_HTTP_TRANSFER_DECODING \- enable/disable HTTP transfer decoding
.SH SYNOPSIS
.nf
#include <curl/curl.h>

Changes to jni/curl/docs/libcurl/opts/CURLOPT_HTTP_VERSION.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_HTTP_VERSION 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_HTTP_VERSION \- specify HTTP protocol version to use
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_HTTP_VERSION, long version);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_HTTP_VERSION 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_HTTP_VERSION \- specify HTTP protocol version to use
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_HTTP_VERSION, long version);
Changes to jni/curl/docs/libcurl/opts/CURLOPT_IGNORE_CONTENT_LENGTH.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_IGNORE_CONTENT_LENGTH 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_IGNORE_CONTENT_LENGTH \- ignore content length
.SH SYNOPSIS
.nf
#include <curl/curl.h>








|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_IGNORE_CONTENT_LENGTH 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_IGNORE_CONTENT_LENGTH \- ignore content length
.SH SYNOPSIS
.nf
#include <curl/curl.h>

Changes to jni/curl/docs/libcurl/opts/CURLOPT_INFILESIZE.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_INFILESIZE 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_INFILESIZE \- set size of the input file to send off
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_INFILESIZE, long filesize);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_INFILESIZE 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_INFILESIZE \- set size of the input file to send off
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_INFILESIZE, long filesize);
Changes to jni/curl/docs/libcurl/opts/CURLOPT_INFILESIZE_LARGE.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_INFILESIZE_LARGE 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_INFILESIZE_LARGE \- set size of the input file to send off
.SH SYNOPSIS
.nf
#include <curl/curl.h>








|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_INFILESIZE_LARGE 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_INFILESIZE_LARGE \- set size of the input file to send off
.SH SYNOPSIS
.nf
#include <curl/curl.h>

Changes to jni/curl/docs/libcurl/opts/CURLOPT_INTERFACE.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_INTERFACE 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_INTERFACE \- source interface for outgoing traffic
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_INTERFACE, char *interface);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_INTERFACE 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_INTERFACE \- source interface for outgoing traffic
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_INTERFACE, char *interface);
Changes to jni/curl/docs/libcurl/opts/CURLOPT_INTERLEAVEDATA.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_INTERLEAVEDATA 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_INTERLEAVEDATA \- custom pointer passed to RTSP interleave callback
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_INTERLEAVEDATA, void *pointer);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_INTERLEAVEDATA 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_INTERLEAVEDATA \- custom pointer passed to RTSP interleave callback
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_INTERLEAVEDATA, void *pointer);
Changes to jni/curl/docs/libcurl/opts/CURLOPT_INTERLEAVEFUNCTION.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_INTERLEAVEFUNCTION 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_INTERLEAVEFUNCTION \- callback function for RTSP interleaved data
.SH SYNOPSIS
.nf
#include <curl/curl.h>








|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_INTERLEAVEFUNCTION 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_INTERLEAVEFUNCTION \- callback function for RTSP interleaved data
.SH SYNOPSIS
.nf
#include <curl/curl.h>

Changes to jni/curl/docs/libcurl/opts/CURLOPT_IOCTLDATA.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_IOCTLDATA 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_IOCTLDATA \- custom pointer passed to I/O callback
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_IOCTLDATA, void *pointer);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_IOCTLDATA 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_IOCTLDATA \- custom pointer passed to I/O callback
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_IOCTLDATA, void *pointer);
Changes to jni/curl/docs/libcurl/opts/CURLOPT_IOCTLFUNCTION.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_IOCTLFUNCTION 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_IOCTLFUNCTION \- callback for I/O operations
.SH SYNOPSIS
.nf
#include <curl/curl.h>








|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_IOCTLFUNCTION 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_IOCTLFUNCTION \- callback for I/O operations
.SH SYNOPSIS
.nf
#include <curl/curl.h>

Changes to jni/curl/docs/libcurl/opts/CURLOPT_IPRESOLVE.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_IPRESOLVE 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_IPRESOLVE \- specify which IP protocol version to use
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_IPRESOLVE, long resolve);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_IPRESOLVE 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_IPRESOLVE \- specify which IP protocol version to use
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_IPRESOLVE, long resolve);
Changes to jni/curl/docs/libcurl/opts/CURLOPT_ISSUERCERT.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_ISSUERCERT 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_ISSUERCERT \- issuer SSL certificate filename
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_ISSUERCERT, char *file);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_ISSUERCERT 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_ISSUERCERT \- issuer SSL certificate filename
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_ISSUERCERT, char *file);
Changes to jni/curl/docs/libcurl/opts/CURLOPT_ISSUERCERT_BLOB.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_ISSUERCERT_BLOB 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_ISSUERCERT_BLOB \- issuer SSL certificate from memory blob
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_ISSUERCERT_BLOB, struct curl_blob *stblob);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_ISSUERCERT_BLOB 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_ISSUERCERT_BLOB \- issuer SSL certificate from memory blob
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_ISSUERCERT_BLOB, struct curl_blob *stblob);
Changes to jni/curl/docs/libcurl/opts/CURLOPT_KEEP_SENDING_ON_ERROR.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_KEEP_SENDING_ON_ERROR 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_KEEP_SENDING_ON_ERROR \- keep sending on early HTTP response >= 300
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_KEEP_SENDING_ON_ERROR,







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_KEEP_SENDING_ON_ERROR 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_KEEP_SENDING_ON_ERROR \- keep sending on early HTTP response >= 300
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_KEEP_SENDING_ON_ERROR,
Changes to jni/curl/docs/libcurl/opts/CURLOPT_KEYPASSWD.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_KEYPASSWD 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_KEYPASSWD \- set passphrase to private key
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_KEYPASSWD, char *pwd);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_KEYPASSWD 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_KEYPASSWD \- set passphrase to private key
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_KEYPASSWD, char *pwd);
Changes to jni/curl/docs/libcurl/opts/CURLOPT_KRBLEVEL.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_KRBLEVEL 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_KRBLEVEL \- set FTP kerberos security level
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_KRBLEVEL, char *level);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_KRBLEVEL 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_KRBLEVEL \- set FTP kerberos security level
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_KRBLEVEL, char *level);
Changes to jni/curl/docs/libcurl/opts/CURLOPT_LOCALPORT.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_LOCALPORT 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_LOCALPORT \- set local port number to use for socket
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_LOCALPORT, long port);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_LOCALPORT 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_LOCALPORT \- set local port number to use for socket
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_LOCALPORT, long port);
Changes to jni/curl/docs/libcurl/opts/CURLOPT_LOCALPORTRANGE.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_LOCALPORTRANGE 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_LOCALPORTRANGE \- number of additional local ports to try
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_LOCALPORTRANGE,







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_LOCALPORTRANGE 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_LOCALPORTRANGE \- number of additional local ports to try
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_LOCALPORTRANGE,
Changes to jni/curl/docs/libcurl/opts/CURLOPT_LOGIN_OPTIONS.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_LOGIN_OPTIONS 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_LOGIN_OPTIONS \- set login options
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_LOGIN_OPTIONS, char *options);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_LOGIN_OPTIONS 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_LOGIN_OPTIONS \- set login options
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_LOGIN_OPTIONS, char *options);
Changes to jni/curl/docs/libcurl/opts/CURLOPT_LOW_SPEED_LIMIT.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_LOW_SPEED_LIMIT 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_LOW_SPEED_LIMIT \- set low speed limit in bytes per second
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_LOW_SPEED_LIMIT, long speedlimit);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_LOW_SPEED_LIMIT 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_LOW_SPEED_LIMIT \- set low speed limit in bytes per second
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_LOW_SPEED_LIMIT, long speedlimit);
Changes to jni/curl/docs/libcurl/opts/CURLOPT_LOW_SPEED_TIME.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_LOW_SPEED_TIME 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_LOW_SPEED_TIME \- set low speed limit time period
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_LOW_SPEED_TIME, long speedtime);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_LOW_SPEED_TIME 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_LOW_SPEED_TIME \- set low speed limit time period
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_LOW_SPEED_TIME, long speedtime);
Changes to jni/curl/docs/libcurl/opts/CURLOPT_MAIL_AUTH.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_MAIL_AUTH 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_MAIL_AUTH \- SMTP authentication address
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_MAIL_AUTH, char *auth);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_MAIL_AUTH 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_MAIL_AUTH \- SMTP authentication address
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_MAIL_AUTH, char *auth);
Changes to jni/curl/docs/libcurl/opts/CURLOPT_MAIL_FROM.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_MAIL_FROM 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_MAIL_FROM \- SMTP sender address
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_MAIL_FROM, char *from);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_MAIL_FROM 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_MAIL_FROM \- SMTP sender address
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_MAIL_FROM, char *from);
Changes to jni/curl/docs/libcurl/opts/CURLOPT_MAIL_RCPT.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_MAIL_RCPT 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_MAIL_RCPT \- list of SMTP mail recipients
.SH SYNOPSIS
.nf
#include <curl/curl.h>








|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_MAIL_RCPT 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_MAIL_RCPT \- list of SMTP mail recipients
.SH SYNOPSIS
.nf
#include <curl/curl.h>

Changes to jni/curl/docs/libcurl/opts/CURLOPT_MAIL_RCPT_ALLLOWFAILS.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_MAIL_RCPT_ALLLOWFAILS 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_MAIL_RCPT_ALLLOWFAILS \- allow RCPT TO command to fail for some recipients
.SH SYNOPSIS
.nf
#include <curl/curl.h>








|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_MAIL_RCPT_ALLLOWFAILS 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_MAIL_RCPT_ALLLOWFAILS \- allow RCPT TO command to fail for some recipients
.SH SYNOPSIS
.nf
#include <curl/curl.h>

Changes to jni/curl/docs/libcurl/opts/CURLOPT_MAXAGE_CONN.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_MAXAGE_CONN 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_MAXAGE_CONN \- max idle time allowed for reusing a connection
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_MAXAGE_CONN, long maxage);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_MAXAGE_CONN 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_MAXAGE_CONN \- max idle time allowed for reusing a connection
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_MAXAGE_CONN, long maxage);
Changes to jni/curl/docs/libcurl/opts/CURLOPT_MAXCONNECTS.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_MAXCONNECTS 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_MAXCONNECTS \- maximum connection cache size
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_MAXCONNECTS, long amount);
.SH DESCRIPTION
Pass a long. The set \fIamount\fP will be the maximum number of simultaneously
open persistent connections that libcurl may cache in the pool associated with
this handle. The default is 5, and there isn't much point in changing this
value unless you are perfectly aware of how this works and changes libcurl's
behaviour. This concerns connections using any of the protocols that support
persistent connections.

When reaching the maximum limit, curl closes the oldest one in the cache to
prevent increasing the number of open connections.

If you already have performed transfers with this curl handle, setting a
smaller \fICURLOPT_MAXCONNECTS(3)\fP than before may cause open connections to







|












|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_MAXCONNECTS 3 "December 31, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_MAXCONNECTS \- maximum connection cache size
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_MAXCONNECTS, long amount);
.SH DESCRIPTION
Pass a long. The set \fIamount\fP will be the maximum number of simultaneously
open persistent connections that libcurl may cache in the pool associated with
this handle. The default is 5, and there isn't much point in changing this
value unless you are perfectly aware of how this works and changes libcurl's
behavior. This concerns connections using any of the protocols that support
persistent connections.

When reaching the maximum limit, curl closes the oldest one in the cache to
prevent increasing the number of open connections.

If you already have performed transfers with this curl handle, setting a
smaller \fICURLOPT_MAXCONNECTS(3)\fP than before may cause open connections to
Changes to jni/curl/docs/libcurl/opts/CURLOPT_MAXFILESIZE.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_MAXFILESIZE 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_MAXFILESIZE \- maximum file size allowed to download
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_MAXFILESIZE, long size);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_MAXFILESIZE 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_MAXFILESIZE \- maximum file size allowed to download
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_MAXFILESIZE, long size);
Changes to jni/curl/docs/libcurl/opts/CURLOPT_MAXFILESIZE_LARGE.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_MAXFILESIZE_LARGE 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_MAXFILESIZE_LARGE \- maximum file size allowed to download
.SH SYNOPSIS
.nf
#include <curl/curl.h>








|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_MAXFILESIZE_LARGE 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_MAXFILESIZE_LARGE \- maximum file size allowed to download
.SH SYNOPSIS
.nf
#include <curl/curl.h>

Changes to jni/curl/docs/libcurl/opts/CURLOPT_MAXREDIRS.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_MAXREDIRS 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_MAXREDIRS \- maximum number of redirects allowed
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_MAXREDIRS, long amount);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_MAXREDIRS 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_MAXREDIRS \- maximum number of redirects allowed
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_MAXREDIRS, long amount);
Changes to jni/curl/docs/libcurl/opts/CURLOPT_MAX_RECV_SPEED_LARGE.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_MAX_RECV_SPEED_LARGE 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_MAX_RECV_SPEED_LARGE \- rate limit data download speed
.SH SYNOPSIS
.nf
#include <curl/curl.h>








|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_MAX_RECV_SPEED_LARGE 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_MAX_RECV_SPEED_LARGE \- rate limit data download speed
.SH SYNOPSIS
.nf
#include <curl/curl.h>

Changes to jni/curl/docs/libcurl/opts/CURLOPT_MAX_SEND_SPEED_LARGE.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_MAX_SEND_SPEED_LARGE 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_MAX_SEND_SPEED_LARGE \- rate limit data upload speed
.SH SYNOPSIS
.nf
#include <curl/curl.h>








|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_MAX_SEND_SPEED_LARGE 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_MAX_SEND_SPEED_LARGE \- rate limit data upload speed
.SH SYNOPSIS
.nf
#include <curl/curl.h>

Changes to jni/curl/docs/libcurl/opts/CURLOPT_MIMEPOST.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_MIMEPOST 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_MIMEPOST \- set post/send data from mime structure
.SH SYNOPSIS
.nf
#include <curl/curl.h>








|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_MIMEPOST 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_MIMEPOST \- set post/send data from mime structure
.SH SYNOPSIS
.nf
#include <curl/curl.h>

Changes to jni/curl/docs/libcurl/opts/CURLOPT_NETRC.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_NETRC 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_NETRC \- request that .netrc is used
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_NETRC, long level);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_NETRC 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_NETRC \- request that .netrc is used
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_NETRC, long level);
Changes to jni/curl/docs/libcurl/opts/CURLOPT_NETRC_FILE.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_NETRC_FILE 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_NETRC_FILE \- file name to read .netrc info from
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_NETRC_FILE, char *file);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_NETRC_FILE 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_NETRC_FILE \- file name to read .netrc info from
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_NETRC_FILE, char *file);
Changes to jni/curl/docs/libcurl/opts/CURLOPT_NEW_DIRECTORY_PERMS.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_NEW_DIRECTORY_PERMS 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_NEW_DIRECTORY_PERMS \- permissions for remotely created directories
.SH SYNOPSIS
.nf
#include <curl/curl.h>








|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_NEW_DIRECTORY_PERMS 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_NEW_DIRECTORY_PERMS \- permissions for remotely created directories
.SH SYNOPSIS
.nf
#include <curl/curl.h>

Changes to jni/curl/docs/libcurl/opts/CURLOPT_NEW_FILE_PERMS.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_NEW_FILE_PERMS 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_NEW_FILE_PERMS \- permissions for remotely created files
.SH SYNOPSIS
.nf
#include <curl/curl.h>








|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_NEW_FILE_PERMS 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_NEW_FILE_PERMS \- permissions for remotely created files
.SH SYNOPSIS
.nf
#include <curl/curl.h>

Changes to jni/curl/docs/libcurl/opts/CURLOPT_NOBODY.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_NOBODY 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_NOBODY \- do the download request without getting the body
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_NOBODY, long opt);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_NOBODY 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_NOBODY \- do the download request without getting the body
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_NOBODY, long opt);
Changes to jni/curl/docs/libcurl/opts/CURLOPT_NOPROGRESS.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_NOPROGRESS 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_NOPROGRESS \- switch off the progress meter
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_NOPROGRESS, long onoff);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_NOPROGRESS 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_NOPROGRESS \- switch off the progress meter
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_NOPROGRESS, long onoff);
Changes to jni/curl/docs/libcurl/opts/CURLOPT_NOPROXY.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_NOPROXY 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_NOPROXY \- disable proxy use for specific hosts
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_NOPROXY, char *noproxy);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_NOPROXY 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_NOPROXY \- disable proxy use for specific hosts
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_NOPROXY, char *noproxy);
Changes to jni/curl/docs/libcurl/opts/CURLOPT_NOSIGNAL.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_NOSIGNAL 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_NOSIGNAL \- skip all signal handling
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_NOSIGNAL, long onoff);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_NOSIGNAL 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_NOSIGNAL \- skip all signal handling
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_NOSIGNAL, long onoff);
Changes to jni/curl/docs/libcurl/opts/CURLOPT_OPENSOCKETDATA.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_OPENSOCKETDATA 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_OPENSOCKETDATA \- custom pointer passed to open socket callback
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_OPENSOCKETDATA, void *pointer);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_OPENSOCKETDATA 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_OPENSOCKETDATA \- custom pointer passed to open socket callback
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_OPENSOCKETDATA, void *pointer);
Changes to jni/curl/docs/libcurl/opts/CURLOPT_OPENSOCKETFUNCTION.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_OPENSOCKETFUNCTION 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_OPENSOCKETFUNCTION \- set callback for opening sockets
.SH SYNOPSIS
.nf
#include <curl/curl.h>








|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_OPENSOCKETFUNCTION 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_OPENSOCKETFUNCTION \- set callback for opening sockets
.SH SYNOPSIS
.nf
#include <curl/curl.h>

Changes to jni/curl/docs/libcurl/opts/CURLOPT_PASSWORD.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_PASSWORD 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_PASSWORD \- password to use in authentication
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PASSWORD, char *pwd);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_PASSWORD 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_PASSWORD \- password to use in authentication
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PASSWORD, char *pwd);
Changes to jni/curl/docs/libcurl/opts/CURLOPT_PATH_AS_IS.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_PATH_AS_IS 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_PATH_AS_IS \- do not handle dot dot sequences
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PATH_AS_IS, long leaveit);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_PATH_AS_IS 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_PATH_AS_IS \- do not handle dot dot sequences
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PATH_AS_IS, long leaveit);
Changes to jni/curl/docs/libcurl/opts/CURLOPT_PINNEDPUBLICKEY.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_PINNEDPUBLICKEY 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_PINNEDPUBLICKEY \- set pinned public key
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PINNEDPUBLICKEY, char *pinnedpubkey);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_PINNEDPUBLICKEY 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_PINNEDPUBLICKEY \- set pinned public key
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PINNEDPUBLICKEY, char *pinnedpubkey);
Changes to jni/curl/docs/libcurl/opts/CURLOPT_PIPEWAIT.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_PIPEWAIT 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_PIPEWAIT \- wait for pipelining/multiplexing
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PIPEWAIT, long wait);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_PIPEWAIT 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_PIPEWAIT \- wait for pipelining/multiplexing
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PIPEWAIT, long wait);
Changes to jni/curl/docs/libcurl/opts/CURLOPT_PORT.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_PORT 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_PORT \- set remote port number to work with
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PORT, long number);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_PORT 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_PORT \- set remote port number to work with
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PORT, long number);
Changes to jni/curl/docs/libcurl/opts/CURLOPT_POST.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_POST 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_POST \- request an HTTP POST
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_POST, long post);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_POST 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_POST \- request an HTTP POST
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_POST, long post);
Changes to jni/curl/docs/libcurl/opts/CURLOPT_POSTFIELDS.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_POSTFIELDS 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_POSTFIELDS \- specify data to POST to server
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_POSTFIELDS, char *postdata);
.SH DESCRIPTION
Pass a char * as parameter, pointing to the full data to send in an HTTP POST
operation. You must make sure that the data is formatted the way you want the
server to receive it. libcurl will not convert or encode it for you in any
way. For example, the web server may assume that this data is url-encoded.

The data pointed to is NOT copied by the library: as a consequence, it must be
preserved by the calling application until the associated transfer finishes.
This behaviour can be changed (so libcurl does copy the data) by setting the
\fICURLOPT_COPYPOSTFIELDS(3)\fP option.

This POST is a normal application/x-www-form-urlencoded kind (and libcurl will
set that Content-Type by default when this option is used), which is commonly
used by HTML forms. Change Content-Type with \fICURLOPT_HTTPHEADER(3)\fP.

You can use \fIcurl_easy_escape(3)\fP to url-encode your data, if necessary. It







|















|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_POSTFIELDS 3 "December 31, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_POSTFIELDS \- specify data to POST to server
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_POSTFIELDS, char *postdata);
.SH DESCRIPTION
Pass a char * as parameter, pointing to the full data to send in an HTTP POST
operation. You must make sure that the data is formatted the way you want the
server to receive it. libcurl will not convert or encode it for you in any
way. For example, the web server may assume that this data is url-encoded.

The data pointed to is NOT copied by the library: as a consequence, it must be
preserved by the calling application until the associated transfer finishes.
This behavior can be changed (so libcurl does copy the data) by setting the
\fICURLOPT_COPYPOSTFIELDS(3)\fP option.

This POST is a normal application/x-www-form-urlencoded kind (and libcurl will
set that Content-Type by default when this option is used), which is commonly
used by HTML forms. Change Content-Type with \fICURLOPT_HTTPHEADER(3)\fP.

You can use \fIcurl_easy_escape(3)\fP to url-encode your data, if necessary. It
Changes to jni/curl/docs/libcurl/opts/CURLOPT_POSTFIELDSIZE.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_POSTFIELDSIZE 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_POSTFIELDSIZE \- size of POST data pointed to
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_POSTFIELDSIZE, long size);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_POSTFIELDSIZE 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_POSTFIELDSIZE \- size of POST data pointed to
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_POSTFIELDSIZE, long size);
Changes to jni/curl/docs/libcurl/opts/CURLOPT_POSTFIELDSIZE_LARGE.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_POSTFIELDSIZE_LARGE 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_POSTFIELDSIZE_LARGE \- size of POST data pointed to
.SH SYNOPSIS
.nf
#include <curl/curl.h>








|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_POSTFIELDSIZE_LARGE 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_POSTFIELDSIZE_LARGE \- size of POST data pointed to
.SH SYNOPSIS
.nf
#include <curl/curl.h>

Changes to jni/curl/docs/libcurl/opts/CURLOPT_POSTQUOTE.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_POSTQUOTE 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_POSTQUOTE \- (S)FTP commands to run after the transfer
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_POSTQUOTE, struct curl_slist *cmds);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_POSTQUOTE 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_POSTQUOTE \- (S)FTP commands to run after the transfer
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_POSTQUOTE, struct curl_slist *cmds);
Changes to jni/curl/docs/libcurl/opts/CURLOPT_POSTREDIR.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_POSTREDIR 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_POSTREDIR \- how to act on an HTTP POST redirect
.SH SYNOPSIS
.nf
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_POSTREDIR,
                          long bitmask);
.SH DESCRIPTION
Pass a bitmask to control how libcurl acts on redirects after POSTs that get a
301, 302 or 303 response back.  A parameter with bit 0 set (value
\fBCURL_REDIR_POST_301\fP) tells the library to respect RFC 7231 (section
6.4.2 to 6.4.4) and not convert POST requests into GET requests when following
a 301 redirection.  Setting bit 1 (value \fBCURL_REDIR_POST_302\fP) makes
libcurl maintain the request method after a 302 redirect whilst setting bit 2
(value \fBCURL_REDIR_POST_303\fP) makes libcurl maintain the request method
after a 303 redirect. The value \fBCURL_REDIR_POST_ALL\fP is a convenience
define that sets all three bits.

The non-RFC behaviour is ubiquitous in web browsers, so the library does the
conversion by default to maintain consistency. However, a server may require a
POST to remain a POST after such a redirection. This option is meaningful only
when setting \fICURLOPT_FOLLOWLOCATION(3)\fP.
.SH DEFAULT
0
.SH PROTOCOLS
HTTP(S)







|




















|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_POSTREDIR 3 "December 31, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_POSTREDIR \- how to act on an HTTP POST redirect
.SH SYNOPSIS
.nf
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_POSTREDIR,
                          long bitmask);
.SH DESCRIPTION
Pass a bitmask to control how libcurl acts on redirects after POSTs that get a
301, 302 or 303 response back.  A parameter with bit 0 set (value
\fBCURL_REDIR_POST_301\fP) tells the library to respect RFC 7231 (section
6.4.2 to 6.4.4) and not convert POST requests into GET requests when following
a 301 redirection.  Setting bit 1 (value \fBCURL_REDIR_POST_302\fP) makes
libcurl maintain the request method after a 302 redirect whilst setting bit 2
(value \fBCURL_REDIR_POST_303\fP) makes libcurl maintain the request method
after a 303 redirect. The value \fBCURL_REDIR_POST_ALL\fP is a convenience
define that sets all three bits.

The non-RFC behavior is ubiquitous in web browsers, so the library does the
conversion by default to maintain consistency. However, a server may require a
POST to remain a POST after such a redirection. This option is meaningful only
when setting \fICURLOPT_FOLLOWLOCATION(3)\fP.
.SH DEFAULT
0
.SH PROTOCOLS
HTTP(S)
Changes to jni/curl/docs/libcurl/opts/CURLOPT_PREQUOTE.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_PREQUOTE 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_PREQUOTE \- commands to run before an FTP transfer
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PREQUOTE,







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_PREQUOTE 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_PREQUOTE \- commands to run before an FTP transfer
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PREQUOTE,
Changes to jni/curl/docs/libcurl/opts/CURLOPT_PRE_PROXY.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_PRE_PROXY 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_PRE_PROXY \- set pre-proxy to use
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PRE_PROXY, char *preproxy);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_PRE_PROXY 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_PRE_PROXY \- set pre-proxy to use
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PRE_PROXY, char *preproxy);
Changes to jni/curl/docs/libcurl/opts/CURLOPT_PRIVATE.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_PRIVATE 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_PRIVATE \- store a private pointer
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PRIVATE, void *pointer);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_PRIVATE 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_PRIVATE \- store a private pointer
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PRIVATE, void *pointer);
Changes to jni/curl/docs/libcurl/opts/CURLOPT_PROGRESSDATA.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_PROGRESSDATA 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_PROGRESSDATA \- custom pointer passed to the progress callback
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PROGRESSDATA, void *pointer);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_PROGRESSDATA 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_PROGRESSDATA \- custom pointer passed to the progress callback
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PROGRESSDATA, void *pointer);
Changes to jni/curl/docs/libcurl/opts/CURLOPT_PROGRESSFUNCTION.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_PROGRESSFUNCTION 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_PROGRESSFUNCTION \- callback to progress meter function
.SH SYNOPSIS
#include <curl/curl.h>

int progress_callback(void *clientp,







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_PROGRESSFUNCTION 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_PROGRESSFUNCTION \- callback to progress meter function
.SH SYNOPSIS
#include <curl/curl.h>

int progress_callback(void *clientp,
Changes to jni/curl/docs/libcurl/opts/CURLOPT_PROTOCOLS.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_PROTOCOLS 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_PROTOCOLS \- set allowed protocols
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PROTOCOLS, long bitmask);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_PROTOCOLS 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_PROTOCOLS \- set allowed protocols
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PROTOCOLS, long bitmask);
Changes to jni/curl/docs/libcurl/opts/CURLOPT_PROXY.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_PROXY 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_PROXY \- set proxy to use
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PROXY, char *proxy);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_PROXY 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_PROXY \- set proxy to use
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PROXY, char *proxy);
Changes to jni/curl/docs/libcurl/opts/CURLOPT_PROXYAUTH.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_PROXYAUTH 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_PROXYAUTH \- set HTTP proxy authentication methods to try
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PROXYAUTH, long bitmask);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_PROXYAUTH 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_PROXYAUTH \- set HTTP proxy authentication methods to try
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PROXYAUTH, long bitmask);
Changes to jni/curl/docs/libcurl/opts/CURLOPT_PROXYHEADER.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_PROXYHEADER 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_PROXYHEADER \- custom HTTP headers to pass to proxy
.SH SYNOPSIS
.nf
#include <curl/curl.h>








|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_PROXYHEADER 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_PROXYHEADER \- custom HTTP headers to pass to proxy
.SH SYNOPSIS
.nf
#include <curl/curl.h>

Changes to jni/curl/docs/libcurl/opts/CURLOPT_PROXYPASSWORD.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_PROXYPASSWORD 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_PROXYPASSWORD \- password to use with proxy authentication
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PROXYPASSWORD, char *pwd);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_PROXYPASSWORD 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_PROXYPASSWORD \- password to use with proxy authentication
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PROXYPASSWORD, char *pwd);
Changes to jni/curl/docs/libcurl/opts/CURLOPT_PROXYPORT.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_PROXYPORT 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_PROXYPORT \- port number the proxy listens on
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PROXYPORT, long port);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_PROXYPORT 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_PROXYPORT \- port number the proxy listens on
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PROXYPORT, long port);
Changes to jni/curl/docs/libcurl/opts/CURLOPT_PROXYTYPE.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_PROXYTYPE 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_PROXYTYPE \- proxy protocol type
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PROXYTYPE, long type);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_PROXYTYPE 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_PROXYTYPE \- proxy protocol type
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PROXYTYPE, long type);
Changes to jni/curl/docs/libcurl/opts/CURLOPT_PROXYUSERNAME.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_PROXYUSERNAME 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_PROXYUSERNAME \- user name to use for proxy authentication
.SH SYNOPSIS
.nf
#include <curl/curl.h>








|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_PROXYUSERNAME 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_PROXYUSERNAME \- user name to use for proxy authentication
.SH SYNOPSIS
.nf
#include <curl/curl.h>

Changes to jni/curl/docs/libcurl/opts/CURLOPT_PROXYUSERPWD.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_PROXYUSERPWD 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_PROXYUSERPWD \- user name and password to use for proxy authentication
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PROXYUSERPWD, char *userpwd);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_PROXYUSERPWD 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_PROXYUSERPWD \- user name and password to use for proxy authentication
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PROXYUSERPWD, char *userpwd);
Changes to jni/curl/docs/libcurl/opts/CURLOPT_PROXY_CAINFO.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_PROXY_CAINFO 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_PROXY_CAINFO \- path to proxy Certificate Authority (CA) bundle
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PROXY_CAINFO, char *path);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_PROXY_CAINFO 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_PROXY_CAINFO \- path to proxy Certificate Authority (CA) bundle
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PROXY_CAINFO, char *path);
Changes to jni/curl/docs/libcurl/opts/CURLOPT_PROXY_CAPATH.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_PROXY_CAPATH 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_PROXY_CAPATH \- specify directory holding proxy CA certificates
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PROXY_CAPATH, char *capath);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_PROXY_CAPATH 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_PROXY_CAPATH \- specify directory holding proxy CA certificates
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PROXY_CAPATH, char *capath);
Changes to jni/curl/docs/libcurl/opts/CURLOPT_PROXY_CRLFILE.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_PROXY_CRLFILE 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_PROXY_CRLFILE \- specify a proxy Certificate Revocation List file
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PROXY_CRLFILE, char *file);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_PROXY_CRLFILE 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_PROXY_CRLFILE \- specify a proxy Certificate Revocation List file
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PROXY_CRLFILE, char *file);
Changes to jni/curl/docs/libcurl/opts/CURLOPT_PROXY_ISSUERCERT.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_PROXY_ISSUERCERT 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_PROXY_ISSUERCERT \- proxy issuer SSL certificate filename
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PROXY_ISSUERCERT, char *file);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_PROXY_ISSUERCERT 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_PROXY_ISSUERCERT \- proxy issuer SSL certificate filename
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PROXY_ISSUERCERT, char *file);
Changes to jni/curl/docs/libcurl/opts/CURLOPT_PROXY_ISSUERCERT_BLOB.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_PROXY_ISSUERCERT_BLOB 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_ISSUERCERT_BLOB \- proxy issuer SSL certificate from memory blob
.SH SYNOPSIS
.nf
#include <curl/curl.h>








|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_PROXY_ISSUERCERT_BLOB 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_ISSUERCERT_BLOB \- proxy issuer SSL certificate from memory blob
.SH SYNOPSIS
.nf
#include <curl/curl.h>

Changes to jni/curl/docs/libcurl/opts/CURLOPT_PROXY_KEYPASSWD.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_PROXY_KEYPASSWD 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_PROXY_KEYPASSWD \- set passphrase to proxy private key
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PROXY_KEYPASSWD, char *pwd);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_PROXY_KEYPASSWD 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_PROXY_KEYPASSWD \- set passphrase to proxy private key
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PROXY_KEYPASSWD, char *pwd);
Changes to jni/curl/docs/libcurl/opts/CURLOPT_PROXY_PINNEDPUBLICKEY.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_PROXY_PINNEDPUBLICKEY 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_PROXY_PINNEDPUBLICKEY \- set pinned public key for https proxy
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PROXY_PINNEDPUBLICKEY, char *pinnedpubkey);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_PROXY_PINNEDPUBLICKEY 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_PROXY_PINNEDPUBLICKEY \- set pinned public key for https proxy
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PROXY_PINNEDPUBLICKEY, char *pinnedpubkey);
Changes to jni/curl/docs/libcurl/opts/CURLOPT_PROXY_SERVICE_NAME.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_PROXY_SERVICE_NAME 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_PROXY_SERVICE_NAME \- proxy authentication service name
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PROXY_SERVICE_NAME, char *name);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_PROXY_SERVICE_NAME 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_PROXY_SERVICE_NAME \- proxy authentication service name
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PROXY_SERVICE_NAME, char *name);
Changes to jni/curl/docs/libcurl/opts/CURLOPT_PROXY_SSLCERT.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_PROXY_SSLCERT 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_PROXY_SSLCERT \- set SSL proxy client certificate
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PROXY_SSLCERT, char *cert);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_PROXY_SSLCERT 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_PROXY_SSLCERT \- set SSL proxy client certificate
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PROXY_SSLCERT, char *cert);
Changes to jni/curl/docs/libcurl/opts/CURLOPT_PROXY_SSLCERTTYPE.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_PROXY_SSLCERTTYPE 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_PROXY_SSLCERTTYPE \- specify type of the proxy client SSL certificate
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PROXY_SSLCERTTYPE, char *type);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_PROXY_SSLCERTTYPE 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_PROXY_SSLCERTTYPE \- specify type of the proxy client SSL certificate
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PROXY_SSLCERTTYPE, char *type);
Changes to jni/curl/docs/libcurl/opts/CURLOPT_PROXY_SSLCERT_BLOB.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_PROXY_SSLCERT_BLOB 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_PROXY_SSLCERT_BLOB \- SSL proxy client certificate from memory blob
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PROXY_SSLCERT_BLOB, struct curl_blob *blob);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_PROXY_SSLCERT_BLOB 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_PROXY_SSLCERT_BLOB \- SSL proxy client certificate from memory blob
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PROXY_SSLCERT_BLOB, struct curl_blob *blob);
Changes to jni/curl/docs/libcurl/opts/CURLOPT_PROXY_SSLKEY.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_PROXY_SSLKEY 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_PROXY_SSLKEY \- specify private keyfile for TLS and SSL proxy client cert
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PROXY_SSLKEY, char *keyfile);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_PROXY_SSLKEY 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_PROXY_SSLKEY \- specify private keyfile for TLS and SSL proxy client cert
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PROXY_SSLKEY, char *keyfile);
Changes to jni/curl/docs/libcurl/opts/CURLOPT_PROXY_SSLKEYTYPE.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_PROXY_SSLKEYTYPE 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_PROXY_SSLKEYTYPE \- set type of the proxy private key file
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PROXY_SSLKEYTYPE, char *type);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_PROXY_SSLKEYTYPE 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_PROXY_SSLKEYTYPE \- set type of the proxy private key file
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PROXY_SSLKEYTYPE, char *type);
Changes to jni/curl/docs/libcurl/opts/CURLOPT_PROXY_SSLKEY_BLOB.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_PROXY_SSLKEY_BLOB 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_PROXY_SSLKEY_BLOB \- private key for proxy cert from memory blob
.SH SYNOPSIS
.nf
#include <curl/curl.h>








|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_PROXY_SSLKEY_BLOB 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_PROXY_SSLKEY_BLOB \- private key for proxy cert from memory blob
.SH SYNOPSIS
.nf
#include <curl/curl.h>

Changes to jni/curl/docs/libcurl/opts/CURLOPT_PROXY_SSLVERSION.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_PROXY_SSLVERSION 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_PROXY_SSLVERSION \- set preferred proxy TLS/SSL version
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PROXY_SSLVERSION, long version);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_PROXY_SSLVERSION 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_PROXY_SSLVERSION \- set preferred proxy TLS/SSL version
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PROXY_SSLVERSION, long version);
Changes to jni/curl/docs/libcurl/opts/CURLOPT_PROXY_SSL_CIPHER_LIST.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_PROXY_SSL_CIPHER_LIST 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_PROXY_SSL_CIPHER_LIST \- specify ciphers to use for proxy TLS
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PROXY_SSL_CIPHER_LIST, char *list);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_PROXY_SSL_CIPHER_LIST 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_PROXY_SSL_CIPHER_LIST \- specify ciphers to use for proxy TLS
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PROXY_SSL_CIPHER_LIST, char *list);
Changes to jni/curl/docs/libcurl/opts/CURLOPT_PROXY_SSL_OPTIONS.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_PROXY_SSL_OPTIONS 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_PROXY_SSL_OPTIONS \- set proxy SSL behavior options
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PROXY_SSL_OPTIONS, long bitmask);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_PROXY_SSL_OPTIONS 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_PROXY_SSL_OPTIONS \- set proxy SSL behavior options
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PROXY_SSL_OPTIONS, long bitmask);
Changes to jni/curl/docs/libcurl/opts/CURLOPT_PROXY_SSL_VERIFYHOST.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_PROXY_SSL_VERIFYHOST 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_PROXY_SSL_VERIFYHOST \- verify the proxy certificate's name against host
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PROXY_SSL_VERIFYHOST, long verify);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_PROXY_SSL_VERIFYHOST 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_PROXY_SSL_VERIFYHOST \- verify the proxy certificate's name against host
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PROXY_SSL_VERIFYHOST, long verify);
Changes to jni/curl/docs/libcurl/opts/CURLOPT_PROXY_SSL_VERIFYPEER.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_PROXY_SSL_VERIFYPEER 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_PROXY_SSL_VERIFYPEER \- verify the proxy's SSL certificate
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PROXY_SSL_VERIFYPEER, long verify);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_PROXY_SSL_VERIFYPEER 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_PROXY_SSL_VERIFYPEER \- verify the proxy's SSL certificate
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PROXY_SSL_VERIFYPEER, long verify);
Changes to jni/curl/docs/libcurl/opts/CURLOPT_PROXY_TLS13_CIPHERS.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_PROXY_TLS13_CIPHERS 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_PROXY_TLS13_CIPHERS \- ciphers suites for proxy TLS 1.3
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PROXY_TLS13_CIPHERS, char *list);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_PROXY_TLS13_CIPHERS 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_PROXY_TLS13_CIPHERS \- ciphers suites for proxy TLS 1.3
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PROXY_TLS13_CIPHERS, char *list);
Changes to jni/curl/docs/libcurl/opts/CURLOPT_PROXY_TLSAUTH_PASSWORD.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_PROXY_TLSAUTH_PASSWORD 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_PROXY_TLSAUTH_PASSWORD \- password to use for proxy TLS authentication
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PROXY_TLSAUTH_PASSWORD, char *pwd);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_PROXY_TLSAUTH_PASSWORD 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_PROXY_TLSAUTH_PASSWORD \- password to use for proxy TLS authentication
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PROXY_TLSAUTH_PASSWORD, char *pwd);
Changes to jni/curl/docs/libcurl/opts/CURLOPT_PROXY_TLSAUTH_TYPE.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_PROXY_TLSAUTH_TYPE 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_PROXY_TLSAUTH_TYPE \- set proxy TLS authentication methods
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PROXY_TLSAUTH_TYPE, char *type);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_PROXY_TLSAUTH_TYPE 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_PROXY_TLSAUTH_TYPE \- set proxy TLS authentication methods
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PROXY_TLSAUTH_TYPE, char *type);
Changes to jni/curl/docs/libcurl/opts/CURLOPT_PROXY_TLSAUTH_USERNAME.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_PROXY_TLSAUTH_USERNAME 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_PROXY_TLSAUTH_USERNAME \- user name to use for proxy TLS authentication
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PROXY_TLSAUTH_USERNAME, char *user);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_PROXY_TLSAUTH_USERNAME 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_PROXY_TLSAUTH_USERNAME \- user name to use for proxy TLS authentication
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PROXY_TLSAUTH_USERNAME, char *user);
Changes to jni/curl/docs/libcurl/opts/CURLOPT_PROXY_TRANSFER_MODE.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_PROXY_TRANSFER_MODE 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_PROXY_TRANSFER_MODE \- append FTP transfer mode to URL for proxy
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PROXY_TRANSFER_MODE, long enabled);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_PROXY_TRANSFER_MODE 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_PROXY_TRANSFER_MODE \- append FTP transfer mode to URL for proxy
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PROXY_TRANSFER_MODE, long enabled);
Changes to jni/curl/docs/libcurl/opts/CURLOPT_PUT.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_PUT 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_PUT \- make an HTTP PUT request
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PUT, long put);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_PUT 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_PUT \- make an HTTP PUT request
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PUT, long put);
Changes to jni/curl/docs/libcurl/opts/CURLOPT_QUOTE.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_QUOTE 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_QUOTE \- (S)FTP commands to run before transfer
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_QUOTE, struct curl_slist *cmds);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_QUOTE 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_QUOTE \- (S)FTP commands to run before transfer
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_QUOTE, struct curl_slist *cmds);
Changes to jni/curl/docs/libcurl/opts/CURLOPT_RANDOM_FILE.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_RANDOM_FILE 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_RANDOM_FILE \- specify a source for random data
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_RANDOM_FILE, char *path);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_RANDOM_FILE 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_RANDOM_FILE \- specify a source for random data
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_RANDOM_FILE, char *path);
Changes to jni/curl/docs/libcurl/opts/CURLOPT_RANGE.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_RANGE 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_RANGE \- set byte range to request
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_RANGE, char *range);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_RANGE 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_RANGE \- set byte range to request
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_RANGE, char *range);
Changes to jni/curl/docs/libcurl/opts/CURLOPT_READDATA.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_READDATA 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_READDATA \- custom pointer passed to the read callback
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_READDATA, void *pointer);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_READDATA 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_READDATA \- custom pointer passed to the read callback
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_READDATA, void *pointer);
Changes to jni/curl/docs/libcurl/opts/CURLOPT_READFUNCTION.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_READFUNCTION 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_READFUNCTION \- read callback for data uploads
.SH SYNOPSIS
#include <curl/curl.h>

size_t read_callback(char *buffer, size_t size, size_t nitems, void *userdata);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_READFUNCTION 3 "December 30, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_READFUNCTION \- read callback for data uploads
.SH SYNOPSIS
#include <curl/curl.h>

size_t read_callback(char *buffer, size_t size, size_t nitems, void *userdata);
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
and it allows for better error checking.
.SH DEFAULT
The default internal read callback is fread().
.SH PROTOCOLS
This is used for all protocols when doing uploads.
.SH EXAMPLE
.nf
size_t read_callback(void *ptr, size_t size, size_t nmemb, void *userdata)
{
  FILE *readhere = (FILE *)userdata;
  curl_off_t nread;

  /* copy as much data as possible into the 'ptr' buffer, but no more than
     'size' * 'nmemb' bytes! */
  size_t retcode = fread(ptr, size, nmemb, readhere);







|







72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
and it allows for better error checking.
.SH DEFAULT
The default internal read callback is fread().
.SH PROTOCOLS
This is used for all protocols when doing uploads.
.SH EXAMPLE
.nf
size_t read_callback(char *ptr, size_t size, size_t nmemb, void *userdata)
{
  FILE *readhere = (FILE *)userdata;
  curl_off_t nread;

  /* copy as much data as possible into the 'ptr' buffer, but no more than
     'size' * 'nmemb' bytes! */
  size_t retcode = fread(ptr, size, nmemb, readhere);
Changes to jni/curl/docs/libcurl/opts/CURLOPT_REDIR_PROTOCOLS.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_REDIR_PROTOCOLS 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_REDIR_PROTOCOLS \- set protocols allowed to redirect to
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_REDIR_PROTOCOLS, long bitmask);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_REDIR_PROTOCOLS 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_REDIR_PROTOCOLS \- set protocols allowed to redirect to
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_REDIR_PROTOCOLS, long bitmask);
Changes to jni/curl/docs/libcurl/opts/CURLOPT_REFERER.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_REFERER 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_REFERER \- set the HTTP referer header
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_REFERER, char *where);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_REFERER 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_REFERER \- set the HTTP referer header
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_REFERER, char *where);
Changes to jni/curl/docs/libcurl/opts/CURLOPT_REQUEST_TARGET.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_REQUEST_TARGET 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_REQUEST_TARGET \- specify an alternative target for this request
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_REQUEST_TARGET, string);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_REQUEST_TARGET 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_REQUEST_TARGET \- specify an alternative target for this request
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_REQUEST_TARGET, string);
Changes to jni/curl/docs/libcurl/opts/CURLOPT_RESOLVE.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51


52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69



70
71
72
73
74
75
76
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_RESOLVE 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_RESOLVE \- provide custom host name to IP address resolves
.SH SYNOPSIS
.nf
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_RESOLVE,
                          struct curl_slist *hosts);
.SH DESCRIPTION
Pass a pointer to a linked list of strings with host name resolve information
to use for requests with this handle. The linked list should be a fully valid
list of \fBstruct curl_slist\fP structs properly filled in. Use
\fIcurl_slist_append(3)\fP to create the list and \fIcurl_slist_free_all(3)\fP
to clean up an entire list.

Each single name resolve string should be written using the format
HOST:PORT:ADDRESS[,ADDRESS]... where HOST is the name libcurl will try
to resolve, PORT is the port number of the service where libcurl wants
to connect to the HOST and ADDRESS is one or more numerical IP
addresses. If you specify multiple ip addresses they need to be
separated by comma. If libcurl is built to support IPv6, each of the
ADDRESS entries can of course be either IPv4 or IPv6 style addressing.

This option effectively pre-populates the DNS cache with entries for the
host+port pair so redirects and everything that operations against the
HOST+PORT will instead use your provided ADDRESS. Addresses set with
\fICURLOPT_RESOLVE(3)\fP will not time-out from the DNS cache like ordinary


entries.

If the DNS cache already have an entry for the given host+port pair, then
this entry will be removed and a new entry will be created. This is because
old entry may have have different addresses or be ordinary entries with
time-outs.

The provided ADDRESS set by this option will be used even if
\fICURLOPT_IPRESOLVE(3)\fP is set to make libcurl use another IP version.

Remove names from the DNS cache again, to stop providing these fake resolves,
by including a string in the linked list that uses the format
\&"-HOST:PORT". The host name must be prefixed with a dash, and the host name
and port number must exactly match what was already added previously.

Support for providing the ADDRESS within [brackets] was added in 7.57.0.

Support for providing multiple IP addresses per entry was added in 7.59.0.



.SH DEFAULT
NULL
.SH PROTOCOLS
All
.SH EXAMPLE
.nf
CURL *curl;







|

















|








|
|
>
>
|

|

|
|












>
>
>







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_RESOLVE 3 "December 10, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_RESOLVE \- provide custom host name to IP address resolves
.SH SYNOPSIS
.nf
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_RESOLVE,
                          struct curl_slist *hosts);
.SH DESCRIPTION
Pass a pointer to a linked list of strings with host name resolve information
to use for requests with this handle. The linked list should be a fully valid
list of \fBstruct curl_slist\fP structs properly filled in. Use
\fIcurl_slist_append(3)\fP to create the list and \fIcurl_slist_free_all(3)\fP
to clean up an entire list.

Each single name resolve string should be written using the format
[+]HOST:PORT:ADDRESS[,ADDRESS]... where HOST is the name libcurl will try
to resolve, PORT is the port number of the service where libcurl wants
to connect to the HOST and ADDRESS is one or more numerical IP
addresses. If you specify multiple ip addresses they need to be
separated by comma. If libcurl is built to support IPv6, each of the
ADDRESS entries can of course be either IPv4 or IPv6 style addressing.

This option effectively pre-populates the DNS cache with entries for the
host+port pair so redirects and everything that operations against the
HOST+PORT will instead use your provided ADDRESS.

The optional leading "+" signifies whether the new entry should time-out or
not. Entires added with "HOST:..." will never time-out whereas entries added
with "+HOST:..." will time-out just like ordinary DNS cache entries.

If the DNS cache already has an entry for the given host+port pair, then
this entry will be removed and a new entry will be created. This is because
the old entry may have have different addresses or a different time-out
setting.

The provided ADDRESS set by this option will be used even if
\fICURLOPT_IPRESOLVE(3)\fP is set to make libcurl use another IP version.

Remove names from the DNS cache again, to stop providing these fake resolves,
by including a string in the linked list that uses the format
\&"-HOST:PORT". The host name must be prefixed with a dash, and the host name
and port number must exactly match what was already added previously.

Support for providing the ADDRESS within [brackets] was added in 7.57.0.

Support for providing multiple IP addresses per entry was added in 7.59.0.

Support for adding non-permanent entries by using the "+" prefix was added in
7.75.0.
.SH DEFAULT
NULL
.SH PROTOCOLS
All
.SH EXAMPLE
.nf
CURL *curl;
Changes to jni/curl/docs/libcurl/opts/CURLOPT_RESOLVER_START_DATA.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_RESOLVER_START_DATA 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_RESOLVER_START_DATA \- custom pointer passed to the resolver start callback
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_RESOLVER_START_DATA, void *pointer);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_RESOLVER_START_DATA 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_RESOLVER_START_DATA \- custom pointer passed to the resolver start callback
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_RESOLVER_START_DATA, void *pointer);
Changes to jni/curl/docs/libcurl/opts/CURLOPT_RESOLVER_START_FUNCTION.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_RESOLVER_START_FUNCTION 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_RESOLVER_START_FUNCTION \- set callback to be called before a new resolve request is started
.SH SYNOPSIS
.nf
#include <curl/curl.h>








|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_RESOLVER_START_FUNCTION 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_RESOLVER_START_FUNCTION \- set callback to be called before a new resolve request is started
.SH SYNOPSIS
.nf
#include <curl/curl.h>

Changes to jni/curl/docs/libcurl/opts/CURLOPT_RESUME_FROM.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_RESUME_FROM 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_RESUME_FROM \- set a point to resume transfer from
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_RESUME_FROM, long from);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_RESUME_FROM 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_RESUME_FROM \- set a point to resume transfer from
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_RESUME_FROM, long from);
Changes to jni/curl/docs/libcurl/opts/CURLOPT_RESUME_FROM_LARGE.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_RESUME_FROM_LARGE 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_RESUME_FROM_LARGE \- set a point to resume transfer from
.SH SYNOPSIS
.nf
#include <curl/curl.h>








|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_RESUME_FROM_LARGE 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_RESUME_FROM_LARGE \- set a point to resume transfer from
.SH SYNOPSIS
.nf
#include <curl/curl.h>

Changes to jni/curl/docs/libcurl/opts/CURLOPT_RTSP_CLIENT_CSEQ.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_RTSP_CLIENT_CSEQ 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_RTSP_CLIENT_CSEQ \- set the RTSP client CSEQ number
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_RTSP_CLIENT_CSEQ, long cseq);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_RTSP_CLIENT_CSEQ 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_RTSP_CLIENT_CSEQ \- set the RTSP client CSEQ number
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_RTSP_CLIENT_CSEQ, long cseq);
Changes to jni/curl/docs/libcurl/opts/CURLOPT_RTSP_REQUEST.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_RTSP_REQUEST 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_RTSP_REQUEST \- specify RTSP request
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_RTSP_REQUEST, long request);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_RTSP_REQUEST 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_RTSP_REQUEST \- specify RTSP request
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_RTSP_REQUEST, long request);
Changes to jni/curl/docs/libcurl/opts/CURLOPT_RTSP_SERVER_CSEQ.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_RTSP_SERVER_CSEQ 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_RTSP_SERVER_CSEQ \- set the RTSP server CSEQ number
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_RTSP_SERVER_CSEQ, long cseq);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_RTSP_SERVER_CSEQ 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_RTSP_SERVER_CSEQ \- set the RTSP server CSEQ number
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_RTSP_SERVER_CSEQ, long cseq);
Changes to jni/curl/docs/libcurl/opts/CURLOPT_RTSP_SESSION_ID.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_RTSP_SESSION_ID 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_RTSP_SESSION_ID \- set RTSP session ID
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_RTSP_SESSION_ID, char *id);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_RTSP_SESSION_ID 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_RTSP_SESSION_ID \- set RTSP session ID
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_RTSP_SESSION_ID, char *id);
Changes to jni/curl/docs/libcurl/opts/CURLOPT_RTSP_STREAM_URI.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_RTSP_STREAM_URI 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_RTSP_STREAM_URI \- set RTSP stream URI
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_RTSP_STREAM_URI, char *URI);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_RTSP_STREAM_URI 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_RTSP_STREAM_URI \- set RTSP stream URI
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_RTSP_STREAM_URI, char *URI);
Changes to jni/curl/docs/libcurl/opts/CURLOPT_RTSP_TRANSPORT.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_RTSP_TRANSPORT 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_RTSP_TRANSPORT \- set RTSP Transport: header
.SH SYNOPSIS
.nf
#include <curl/curl.h>








|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_RTSP_TRANSPORT 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_RTSP_TRANSPORT \- set RTSP Transport: header
.SH SYNOPSIS
.nf
#include <curl/curl.h>

Changes to jni/curl/docs/libcurl/opts/CURLOPT_SASL_AUTHZID.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_SASL_AUTHZID 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_SASL_AUTHZID \- authorisation identity (identity to act as)
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_SASL_AUTHZID, char *authzid);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_SASL_AUTHZID 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_SASL_AUTHZID \- authorisation identity (identity to act as)
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_SASL_AUTHZID, char *authzid);
Changes to jni/curl/docs/libcurl/opts/CURLOPT_SASL_IR.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_SASL_IR 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_SASL_IR \- enable sending initial response in first packet
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_SASL_IR, long enable);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_SASL_IR 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_SASL_IR \- enable sending initial response in first packet
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_SASL_IR, long enable);
Changes to jni/curl/docs/libcurl/opts/CURLOPT_SEEKDATA.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_SEEKDATA 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_SEEKDATA \- custom pointer passed to the seek callback
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_SEEKDATA, void *pointer);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_SEEKDATA 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_SEEKDATA \- custom pointer passed to the seek callback
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_SEEKDATA, void *pointer);
Changes to jni/curl/docs/libcurl/opts/CURLOPT_SEEKFUNCTION.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_SEEKFUNCTION 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_SEEKFUNCTION \- user callback for seeking in input stream
.SH SYNOPSIS
.nf
#include <curl/curl.h>








|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_SEEKFUNCTION 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_SEEKFUNCTION \- user callback for seeking in input stream
.SH SYNOPSIS
.nf
#include <curl/curl.h>

Changes to jni/curl/docs/libcurl/opts/CURLOPT_SERVICE_NAME.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_SERVICE_NAME 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_SERVICE_NAME \- authentication service name
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_SERVICE_NAME, char *name);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_SERVICE_NAME 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_SERVICE_NAME \- authentication service name
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_SERVICE_NAME, char *name);
Changes to jni/curl/docs/libcurl/opts/CURLOPT_SHARE.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_SHARE 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_SHARE \- specify share handle to use
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_SHARE, CURLSH *share);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_SHARE 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_SHARE \- specify share handle to use
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_SHARE, CURLSH *share);
Changes to jni/curl/docs/libcurl/opts/CURLOPT_SOCKOPTDATA.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_SOCKOPTDATA 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_SOCKOPTDATA \- custom pointer to pass to sockopt callback
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_SOCKOPTDATA, void *pointer);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_SOCKOPTDATA 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_SOCKOPTDATA \- custom pointer to pass to sockopt callback
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_SOCKOPTDATA, void *pointer);
Changes to jni/curl/docs/libcurl/opts/CURLOPT_SOCKOPTFUNCTION.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_SOCKOPTFUNCTION 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_SOCKOPTFUNCTION \- set callback for setting socket options
.SH SYNOPSIS
.nf
#include <curl/curl.h>








|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_SOCKOPTFUNCTION 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_SOCKOPTFUNCTION \- set callback for setting socket options
.SH SYNOPSIS
.nf
#include <curl/curl.h>

Changes to jni/curl/docs/libcurl/opts/CURLOPT_SOCKS5_AUTH.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_SOCKS5_AUTH 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_SOCKS5_AUTH \- set allowed methods for SOCKS5 proxy authentication
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_SOCKS5_AUTH, long bitmask);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_SOCKS5_AUTH 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_SOCKS5_AUTH \- set allowed methods for SOCKS5 proxy authentication
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_SOCKS5_AUTH, long bitmask);
Changes to jni/curl/docs/libcurl/opts/CURLOPT_SOCKS5_GSSAPI_NEC.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_SOCKS5_GSSAPI_NEC 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_SOCKS5_GSSAPI_NEC \- set socks proxy gssapi negotiation protection
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_SOCKS5_GSSAPI_NEC, long nec);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_SOCKS5_GSSAPI_NEC 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_SOCKS5_GSSAPI_NEC \- set socks proxy gssapi negotiation protection
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_SOCKS5_GSSAPI_NEC, long nec);
Changes to jni/curl/docs/libcurl/opts/CURLOPT_SOCKS5_GSSAPI_SERVICE.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_SOCKS5_GSSAPI_SERVICE 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_SOCKS5_GSSAPI_SERVICE \- SOCKS5 proxy authentication service name
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_SOCKS5_GSSAPI_SERVICE, char *name);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_SOCKS5_GSSAPI_SERVICE 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_SOCKS5_GSSAPI_SERVICE \- SOCKS5 proxy authentication service name
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_SOCKS5_GSSAPI_SERVICE, char *name);
Changes to jni/curl/docs/libcurl/opts/CURLOPT_SSH_AUTH_TYPES.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_SSH_AUTH_TYPES 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_SSH_AUTH_TYPES \- set desired auth types for SFTP and SCP
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_SSH_AUTH_TYPES, long bitmask);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_SSH_AUTH_TYPES 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_SSH_AUTH_TYPES \- set desired auth types for SFTP and SCP
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_SSH_AUTH_TYPES, long bitmask);
Changes to jni/curl/docs/libcurl/opts/CURLOPT_SSH_COMPRESSION.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_SSH_COMPRESSION 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_SSH_COMPRESSION \- enables compression / decompression of SSH traffic
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_SSH_COMPRESSION, long enable);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_SSH_COMPRESSION 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_SSH_COMPRESSION \- enables compression / decompression of SSH traffic
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_SSH_COMPRESSION, long enable);
Changes to jni/curl/docs/libcurl/opts/CURLOPT_SSH_HOST_PUBLIC_KEY_MD5.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_SSH_HOST_PUBLIC_KEY_MD5 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_SSH_HOST_PUBLIC_KEY_MD5 \- checksum of SSH server public key
.SH SYNOPSIS
.nf
#include <curl/curl.h>








|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_SSH_HOST_PUBLIC_KEY_MD5 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_SSH_HOST_PUBLIC_KEY_MD5 \- checksum of SSH server public key
.SH SYNOPSIS
.nf
#include <curl/curl.h>

Changes to jni/curl/docs/libcurl/opts/CURLOPT_SSH_KEYDATA.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_SSH_KEYDATA 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_SSH_KEYDATA \- pointer to pass to the SSH key callback
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_SSH_KEYDATA, void *pointer);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_SSH_KEYDATA 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_SSH_KEYDATA \- pointer to pass to the SSH key callback
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_SSH_KEYDATA, void *pointer);
Changes to jni/curl/docs/libcurl/opts/CURLOPT_SSH_KEYFUNCTION.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_SSH_KEYFUNCTION 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_SSH_KEYFUNCTION \- callback for known host matching logic
.SH SYNOPSIS
.nf
#include <curl/curl.h>








|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_SSH_KEYFUNCTION 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_SSH_KEYFUNCTION \- callback for known host matching logic
.SH SYNOPSIS
.nf
#include <curl/curl.h>

Changes to jni/curl/docs/libcurl/opts/CURLOPT_SSH_KNOWNHOSTS.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_SSH_KNOWNHOSTS 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_SSH_KNOWNHOSTS \- file name holding the SSH known hosts
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_SSH_KNOWNHOSTS, char *fname);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_SSH_KNOWNHOSTS 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_SSH_KNOWNHOSTS \- file name holding the SSH known hosts
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_SSH_KNOWNHOSTS, char *fname);
Changes to jni/curl/docs/libcurl/opts/CURLOPT_SSH_PRIVATE_KEYFILE.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_SSH_PRIVATE_KEYFILE 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_SSH_PRIVATE_KEYFILE \- set private key file for SSH auth
.SH SYNOPSIS
.nf
#include <curl/curl.h>








|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_SSH_PRIVATE_KEYFILE 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_SSH_PRIVATE_KEYFILE \- set private key file for SSH auth
.SH SYNOPSIS
.nf
#include <curl/curl.h>

Changes to jni/curl/docs/libcurl/opts/CURLOPT_SSH_PUBLIC_KEYFILE.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_SSH_PUBLIC_KEYFILE 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_SSH_PUBLIC_KEYFILE \- set public key file for SSH auth
.SH SYNOPSIS
.nf
#include <curl/curl.h>








|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_SSH_PUBLIC_KEYFILE 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_SSH_PUBLIC_KEYFILE \- set public key file for SSH auth
.SH SYNOPSIS
.nf
#include <curl/curl.h>

Changes to jni/curl/docs/libcurl/opts/CURLOPT_SSLCERT.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_SSLCERT 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_SSLCERT \- set SSL client certificate
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_SSLCERT, char *cert);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_SSLCERT 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_SSLCERT \- set SSL client certificate
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_SSLCERT, char *cert);
Changes to jni/curl/docs/libcurl/opts/CURLOPT_SSLCERTTYPE.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_SSLCERTTYPE 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_SSLCERTTYPE \- specify type of the client SSL certificate
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_SSLCERTTYPE, char *type);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_SSLCERTTYPE 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_SSLCERTTYPE \- specify type of the client SSL certificate
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_SSLCERTTYPE, char *type);
Changes to jni/curl/docs/libcurl/opts/CURLOPT_SSLCERT_BLOB.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_SSLCERT_BLOB 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_SSLCERT_BLOB \- SSL client certificate from memory blob
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_SSLCERT_BLOB, struct curl_blob *stblob);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_SSLCERT_BLOB 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_SSLCERT_BLOB \- SSL client certificate from memory blob
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_SSLCERT_BLOB, struct curl_blob *stblob);
Changes to jni/curl/docs/libcurl/opts/CURLOPT_SSLENGINE.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_SSLENGINE 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_SSLENGINE \- set SSL engine identifier
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_SSLENGINE, char *id);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_SSLENGINE 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_SSLENGINE \- set SSL engine identifier
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_SSLENGINE, char *id);
Changes to jni/curl/docs/libcurl/opts/CURLOPT_SSLENGINE_DEFAULT.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_SSLENGINE_DEFAULT 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_SSLENGINE_DEFAULT \- make SSL engine default
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_SSLENGINE_DEFAULT, long val);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_SSLENGINE_DEFAULT 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_SSLENGINE_DEFAULT \- make SSL engine default
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_SSLENGINE_DEFAULT, long val);
Changes to jni/curl/docs/libcurl/opts/CURLOPT_SSLKEY.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_SSLKEY 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_SSLKEY \- specify private keyfile for TLS and SSL client cert
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_SSLKEY, char *keyfile);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_SSLKEY 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_SSLKEY \- specify private keyfile for TLS and SSL client cert
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_SSLKEY, char *keyfile);
Changes to jni/curl/docs/libcurl/opts/CURLOPT_SSLKEYTYPE.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_SSLKEYTYPE 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_SSLKEYTYPE \- set type of the private key file
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_SSLKEYTYPE, char *type);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_SSLKEYTYPE 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_SSLKEYTYPE \- set type of the private key file
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_SSLKEYTYPE, char *type);
Changes to jni/curl/docs/libcurl/opts/CURLOPT_SSLKEY_BLOB.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_SSLKEY_BLOB 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_SSLKEY_BLOB \- private key for client cert from memory blob
.SH SYNOPSIS
.nf
#include <curl/curl.h>








|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_SSLKEY_BLOB 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_SSLKEY_BLOB \- private key for client cert from memory blob
.SH SYNOPSIS
.nf
#include <curl/curl.h>

Changes to jni/curl/docs/libcurl/opts/CURLOPT_SSLVERSION.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_SSLVERSION 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_SSLVERSION \- set preferred TLS/SSL version
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_SSLVERSION, long version);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_SSLVERSION 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_SSLVERSION \- set preferred TLS/SSL version
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_SSLVERSION, long version);
Changes to jni/curl/docs/libcurl/opts/CURLOPT_SSL_CIPHER_LIST.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_SSL_CIPHER_LIST 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_SSL_CIPHER_LIST \- specify ciphers to use for TLS
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_SSL_CIPHER_LIST, char *list);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_SSL_CIPHER_LIST 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_SSL_CIPHER_LIST \- specify ciphers to use for TLS
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_SSL_CIPHER_LIST, char *list);
Changes to jni/curl/docs/libcurl/opts/CURLOPT_SSL_CTX_DATA.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_SSL_CTX_DATA 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_SSL_CTX_DATA \- custom pointer passed to ssl_ctx callback
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_SSL_CTX_DATA, void *pointer);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_SSL_CTX_DATA 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_SSL_CTX_DATA \- custom pointer passed to ssl_ctx callback
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_SSL_CTX_DATA, void *pointer);
Changes to jni/curl/docs/libcurl/opts/CURLOPT_SSL_CTX_FUNCTION.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_SSL_CTX_FUNCTION 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_SSL_CTX_FUNCTION \- SSL context callback for OpenSSL, wolfSSL or mbedTLS
.SH SYNOPSIS
.nf
#include <curl/curl.h>








|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_SSL_CTX_FUNCTION 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_SSL_CTX_FUNCTION \- SSL context callback for OpenSSL, wolfSSL or mbedTLS
.SH SYNOPSIS
.nf
#include <curl/curl.h>

Changes to jni/curl/docs/libcurl/opts/CURLOPT_SSL_EC_CURVES.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_SSL_EC_CURVES 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_SSL_EC_CURVES \- set key exchange curves
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_SSL_EC_CURVES, char *alg_list);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_SSL_EC_CURVES 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_SSL_EC_CURVES \- set key exchange curves
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_SSL_EC_CURVES, char *alg_list);
Changes to jni/curl/docs/libcurl/opts/CURLOPT_SSL_ENABLE_ALPN.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_SSL_ENABLE_ALPN 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_SSL_ENABLE_ALPN \- enable ALPN
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_SSL_ENABLE_ALPN, long npn);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_SSL_ENABLE_ALPN 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_SSL_ENABLE_ALPN \- enable ALPN
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_SSL_ENABLE_ALPN, long npn);
Changes to jni/curl/docs/libcurl/opts/CURLOPT_SSL_ENABLE_NPN.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_SSL_ENABLE_NPN 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_SSL_ENABLE_NPN \- enable NPN
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_SSL_ENABLE_NPN, long npn);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_SSL_ENABLE_NPN 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_SSL_ENABLE_NPN \- enable NPN
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_SSL_ENABLE_NPN, long npn);
Changes to jni/curl/docs/libcurl/opts/CURLOPT_SSL_FALSESTART.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_SSL_FALSESTART 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_SSL_FALSESTART \- enable TLS false start
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_SSL_FALSESTART, long enable);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_SSL_FALSESTART 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_SSL_FALSESTART \- enable TLS false start
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_SSL_FALSESTART, long enable);
Changes to jni/curl/docs/libcurl/opts/CURLOPT_SSL_OPTIONS.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_SSL_OPTIONS 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_SSL_OPTIONS \- set SSL behavior options
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_SSL_OPTIONS, long bitmask);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_SSL_OPTIONS 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_SSL_OPTIONS \- set SSL behavior options
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_SSL_OPTIONS, long bitmask);
Changes to jni/curl/docs/libcurl/opts/CURLOPT_SSL_SESSIONID_CACHE.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_SSL_SESSIONID_CACHE 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_SSL_SESSIONID_CACHE \- enable/disable use of the SSL session-ID cache
.SH SYNOPSIS
.nf
#include <curl/curl.h>








|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_SSL_SESSIONID_CACHE 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_SSL_SESSIONID_CACHE \- enable/disable use of the SSL session-ID cache
.SH SYNOPSIS
.nf
#include <curl/curl.h>

Changes to jni/curl/docs/libcurl/opts/CURLOPT_SSL_VERIFYHOST.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_SSL_VERIFYHOST 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_SSL_VERIFYHOST \- verify the certificate's name against host
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_SSL_VERIFYHOST, long verify);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_SSL_VERIFYHOST 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_SSL_VERIFYHOST \- verify the certificate's name against host
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_SSL_VERIFYHOST, long verify);
Changes to jni/curl/docs/libcurl/opts/CURLOPT_SSL_VERIFYPEER.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_SSL_VERIFYPEER 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_SSL_VERIFYPEER \- verify the peer's SSL certificate
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_SSL_VERIFYPEER, long verify);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_SSL_VERIFYPEER 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_SSL_VERIFYPEER \- verify the peer's SSL certificate
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_SSL_VERIFYPEER, long verify);
Changes to jni/curl/docs/libcurl/opts/CURLOPT_SSL_VERIFYSTATUS.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_SSL_VERIFYSTATUS 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_SSL_VERIFYSTATUS \- verify the certificate's status
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_SSL_VERIFYSTATUS, long verify);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_SSL_VERIFYSTATUS 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_SSL_VERIFYSTATUS \- verify the certificate's status
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_SSL_VERIFYSTATUS, long verify);
Changes to jni/curl/docs/libcurl/opts/CURLOPT_STDERR.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_STDERR 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_STDERR \- redirect stderr to another stream
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_STDERR, FILE *stream);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_STDERR 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_STDERR \- redirect stderr to another stream
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_STDERR, FILE *stream);
Changes to jni/curl/docs/libcurl/opts/CURLOPT_STREAM_DEPENDS.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_STREAM_DEPENDS 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_STREAM_DEPENDS \- set stream this transfer depends on
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_STREAM_DEPENDS, CURL *dephandle);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_STREAM_DEPENDS 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_STREAM_DEPENDS \- set stream this transfer depends on
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_STREAM_DEPENDS, CURL *dephandle);
Changes to jni/curl/docs/libcurl/opts/CURLOPT_STREAM_DEPENDS_E.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_STREAM_DEPENDS_E 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_STREAM_DEPENDS_E \- set stream this transfer depends on exclusively
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_STREAM_DEPENDS_E, CURL *dephandle);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_STREAM_DEPENDS_E 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_STREAM_DEPENDS_E \- set stream this transfer depends on exclusively
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_STREAM_DEPENDS_E, CURL *dephandle);
Changes to jni/curl/docs/libcurl/opts/CURLOPT_STREAM_WEIGHT.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_STREAM_WEIGHT 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_STREAM_WEIGHT \- set numerical stream weight
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_STREAM_WEIGHT, long weight);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_STREAM_WEIGHT 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_STREAM_WEIGHT \- set numerical stream weight
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_STREAM_WEIGHT, long weight);
Changes to jni/curl/docs/libcurl/opts/CURLOPT_SUPPRESS_CONNECT_HEADERS.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_SUPPRESS_CONNECT_HEADERS 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_SUPPRESS_CONNECT_HEADERS \- Suppress proxy CONNECT response headers from user callbacks
.SH SYNOPSIS
.nf
#include <curl/curl.h>








|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_SUPPRESS_CONNECT_HEADERS 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_SUPPRESS_CONNECT_HEADERS \- Suppress proxy CONNECT response headers from user callbacks
.SH SYNOPSIS
.nf
#include <curl/curl.h>

Changes to jni/curl/docs/libcurl/opts/CURLOPT_TCP_FASTOPEN.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_TCP_FASTOPEN 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_TCP_FASTOPEN \- enable TCP Fast Open
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_TCP_FASTOPEN, long enable);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_TCP_FASTOPEN 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_TCP_FASTOPEN \- enable TCP Fast Open
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_TCP_FASTOPEN, long enable);
Changes to jni/curl/docs/libcurl/opts/CURLOPT_TCP_KEEPALIVE.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_TCP_KEEPALIVE 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_TCP_KEEPALIVE \- enable TCP keep-alive probing
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_TCP_KEEPALIVE, long probe);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_TCP_KEEPALIVE 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_TCP_KEEPALIVE \- enable TCP keep-alive probing
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_TCP_KEEPALIVE, long probe);
Changes to jni/curl/docs/libcurl/opts/CURLOPT_TCP_KEEPIDLE.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_TCP_KEEPIDLE 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_TCP_KEEPIDLE \- set TCP keep-alive idle time wait
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_TCP_KEEPIDLE, long delay);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_TCP_KEEPIDLE 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_TCP_KEEPIDLE \- set TCP keep-alive idle time wait
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_TCP_KEEPIDLE, long delay);
Changes to jni/curl/docs/libcurl/opts/CURLOPT_TCP_KEEPINTVL.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_TCP_KEEPINTVL 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_TCP_KEEPINTVL \- set TCP keep-alive interval
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_TCP_KEEPINTVL, long interval);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_TCP_KEEPINTVL 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_TCP_KEEPINTVL \- set TCP keep-alive interval
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_TCP_KEEPINTVL, long interval);
Changes to jni/curl/docs/libcurl/opts/CURLOPT_TCP_NODELAY.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_TCP_NODELAY 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_TCP_NODELAY \- set the TCP_NODELAY option
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_TCP_NODELAY, long nodelay);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_TCP_NODELAY 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_TCP_NODELAY \- set the TCP_NODELAY option
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_TCP_NODELAY, long nodelay);
Changes to jni/curl/docs/libcurl/opts/CURLOPT_TELNETOPTIONS.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_TELNETOPTIONS 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_TELNETOPTIONS \- custom telnet options
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_TELNETOPTIONS,







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_TELNETOPTIONS 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_TELNETOPTIONS \- custom telnet options
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_TELNETOPTIONS,
Changes to jni/curl/docs/libcurl/opts/CURLOPT_TFTP_BLKSIZE.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_TFTP_BLKSIZE 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_TFTP_BLKSIZE \- TFTP block size
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_TFTP_BLKSIZE, long blocksize);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_TFTP_BLKSIZE 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_TFTP_BLKSIZE \- TFTP block size
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_TFTP_BLKSIZE, long blocksize);
Changes to jni/curl/docs/libcurl/opts/CURLOPT_TFTP_NO_OPTIONS.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_TFTP_NO_OPTIONS 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_TFTP_NO_OPTIONS \- Do not send TFTP options requests.
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_TFTP_NO_OPTIONS, long onoff);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_TFTP_NO_OPTIONS 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_TFTP_NO_OPTIONS \- Do not send TFTP options requests.
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_TFTP_NO_OPTIONS, long onoff);
Changes to jni/curl/docs/libcurl/opts/CURLOPT_TIMECONDITION.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_TIMECONDITION 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_TIMECONDITION \- select condition for a time request
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_TIMECONDITION, long cond);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_TIMECONDITION 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_TIMECONDITION \- select condition for a time request
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_TIMECONDITION, long cond);
Changes to jni/curl/docs/libcurl/opts/CURLOPT_TIMEOUT.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_TIMEOUT 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_TIMEOUT \- set maximum time the request is allowed to take
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_TIMEOUT, long timeout);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_TIMEOUT 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_TIMEOUT \- set maximum time the request is allowed to take
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_TIMEOUT, long timeout);
Changes to jni/curl/docs/libcurl/opts/CURLOPT_TIMEOUT_MS.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_TIMEOUT_MS 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_TIMEOUT_MS \- set maximum time the request is allowed to take
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_TIMEOUT_MS, long timeout);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_TIMEOUT_MS 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_TIMEOUT_MS \- set maximum time the request is allowed to take
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_TIMEOUT_MS, long timeout);
Changes to jni/curl/docs/libcurl/opts/CURLOPT_TIMEVALUE.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_TIMEVALUE 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_TIMEVALUE \- set time value for conditional
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_TIMEVALUE, long val);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_TIMEVALUE 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_TIMEVALUE \- set time value for conditional
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_TIMEVALUE, long val);
Changes to jni/curl/docs/libcurl/opts/CURLOPT_TIMEVALUE_LARGE.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_TIMEVALUE_LARGE 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_TIMEVALUE_LARGE \- set time value for conditional
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_TIMEVALUE_LARGE, curl_off_t val);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_TIMEVALUE_LARGE 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_TIMEVALUE_LARGE \- set time value for conditional
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_TIMEVALUE_LARGE, curl_off_t val);
Changes to jni/curl/docs/libcurl/opts/CURLOPT_TLS13_CIPHERS.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_TLS13_CIPHERS 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_TLS13_CIPHERS \- specify ciphers suites to use for TLS 1.3
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_TLS13_CIPHERS, char *list);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_TLS13_CIPHERS 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_TLS13_CIPHERS \- specify ciphers suites to use for TLS 1.3
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_TLS13_CIPHERS, char *list);
Changes to jni/curl/docs/libcurl/opts/CURLOPT_TLSAUTH_PASSWORD.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_TLSAUTH_PASSWORD 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_TLSAUTH_PASSWORD \- password to use for TLS authentication
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_TLSAUTH_PASSWORD, char *pwd);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_TLSAUTH_PASSWORD 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_TLSAUTH_PASSWORD \- password to use for TLS authentication
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_TLSAUTH_PASSWORD, char *pwd);
Changes to jni/curl/docs/libcurl/opts/CURLOPT_TLSAUTH_TYPE.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_TLSAUTH_TYPE 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_TLSAUTH_TYPE \- set TLS authentication methods
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_TLSAUTH_TYPE, char *type);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_TLSAUTH_TYPE 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_TLSAUTH_TYPE \- set TLS authentication methods
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_TLSAUTH_TYPE, char *type);
Changes to jni/curl/docs/libcurl/opts/CURLOPT_TLSAUTH_USERNAME.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_TLSAUTH_USERNAME 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_TLSAUTH_USERNAME \- user name to use for TLS authentication
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_TLSAUTH_USERNAME, char *user);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_TLSAUTH_USERNAME 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_TLSAUTH_USERNAME \- user name to use for TLS authentication
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_TLSAUTH_USERNAME, char *user);
Changes to jni/curl/docs/libcurl/opts/CURLOPT_TRAILERDATA.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_TRAILERDATA 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_TRAILERDATA \- Custom pointer passed to the trailing headers callback
.SH SYNOPSIS
#include <curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_TRAILERDATA, void *userdata);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_TRAILERDATA 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_TRAILERDATA \- Custom pointer passed to the trailing headers callback
.SH SYNOPSIS
#include <curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_TRAILERDATA, void *userdata);
Changes to jni/curl/docs/libcurl/opts/CURLOPT_TRAILERFUNCTION.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_TRAILERFUNCTION 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_TRAILERFUNCTION \- Set callback for sending trailing headers
.SH SYNOPSIS
#include <curl.h>

int curl_trailer_callback(struct curl_slist ** list, void *userdata);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_TRAILERFUNCTION 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_TRAILERFUNCTION \- Set callback for sending trailing headers
.SH SYNOPSIS
#include <curl.h>

int curl_trailer_callback(struct curl_slist ** list, void *userdata);
Changes to jni/curl/docs/libcurl/opts/CURLOPT_TRANSFERTEXT.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_TRANSFERTEXT 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_TRANSFERTEXT \- request a text based transfer for FTP
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_TRANSFERTEXT, long text);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_TRANSFERTEXT 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_TRANSFERTEXT \- request a text based transfer for FTP
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_TRANSFERTEXT, long text);
Changes to jni/curl/docs/libcurl/opts/CURLOPT_TRANSFER_ENCODING.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_TRANSFER_ENCODING 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_TRANSFER_ENCODING \- ask for HTTP Transfer Encoding
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_TRANSFER_ENCODING, long enable);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_TRANSFER_ENCODING 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_TRANSFER_ENCODING \- ask for HTTP Transfer Encoding
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_TRANSFER_ENCODING, long enable);
Changes to jni/curl/docs/libcurl/opts/CURLOPT_UNIX_SOCKET_PATH.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_UNIX_SOCKET_PATH 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_UNIX_SOCKET_PATH \- set Unix domain socket
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_UNIX_SOCKET_PATH, char *path);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_UNIX_SOCKET_PATH 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_UNIX_SOCKET_PATH \- set Unix domain socket
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_UNIX_SOCKET_PATH, char *path);
Changes to jni/curl/docs/libcurl/opts/CURLOPT_UNRESTRICTED_AUTH.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_UNRESTRICTED_AUTH 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_UNRESTRICTED_AUTH \- send credentials to other hosts too
.SH SYNOPSIS
.nf
#include <curl/curl.h>








|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_UNRESTRICTED_AUTH 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_UNRESTRICTED_AUTH \- send credentials to other hosts too
.SH SYNOPSIS
.nf
#include <curl/curl.h>

Changes to jni/curl/docs/libcurl/opts/CURLOPT_UPKEEP_INTERVAL_MS.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_UPKEEP_INTERVAL_MS 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_UPKEEP_INTERVAL_MS \- connection upkeep interval
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_UPKEEP_INTERVAL_MS, long upkeep_interval_ms);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_UPKEEP_INTERVAL_MS 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_UPKEEP_INTERVAL_MS \- connection upkeep interval
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_UPKEEP_INTERVAL_MS, long upkeep_interval_ms);
Changes to jni/curl/docs/libcurl/opts/CURLOPT_UPLOAD.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_UPLOAD 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_UPLOAD \- enable data upload
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_UPLOAD, long upload);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_UPLOAD 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_UPLOAD \- enable data upload
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_UPLOAD, long upload);
Changes to jni/curl/docs/libcurl/opts/CURLOPT_UPLOAD_BUFFERSIZE.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_UPLOAD_BUFFERSIZE 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_UPLOAD_BUFFERSIZE \- set preferred upload buffer size
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_UPLOAD_BUFFERSIZE, long size);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_UPLOAD_BUFFERSIZE 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_UPLOAD_BUFFERSIZE \- set preferred upload buffer size
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_UPLOAD_BUFFERSIZE, long size);
Changes to jni/curl/docs/libcurl/opts/CURLOPT_URL.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_URL 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_URL \- provide the URL to use in the request
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_URL, char *URL);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_URL 3 "December 12, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_URL \- provide the URL to use in the request
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_URL, char *URL);
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304

The \fICURLOPT_URL(3)\fP string will be ignored if \fICURLOPT_CURLU(3)\fP is
set.

\fICURLOPT_URL(3)\fP or \fICURLOPT_CURLU(3)\fP \fBmust\fP be set before a
transfer is started.

The host part of the URL contains the address of the server that you want to
connect to. This can be the fully qualified domain name of the server, the
local network name of the machine on your network or the IP address of the
server or machine represented by either an IPv4 or IPv6 address. For example:

http://www.example.com/

http://hostname/

http://192.168.0.1/

http://[2001:1890:1112:1::20]/

It is also possible to specify the user name, password and any supported login
options as part of the host, for the following protocols, when connecting to
servers that require authentication:

http://user:password@www.example.com

ftp://user:password@ftp.example.com

smb://domain%2fuser:password@server.example.com

imap://user:password;options@mail.example.com

pop3://user:password;options@mail.example.com

smtp://user:password;options@mail.example.com

At present only IMAP, POP3 and SMTP support login options as part of the host.
For more information about the login options in URL syntax please see RFC2384,
RFC5092 and IETF draft draft-earhart-url-smtp-00.txt (Added in 7.31.0).

The port is optional and when not specified libcurl will use the default port
based on the determined or specified protocol: 80 for HTTP, 21 for FTP and 25
for SMTP, etc. The following examples show how to specify the port:

http://www.example.com:8080/ - This will connect to a web server using port
8080 rather than 80.

smtp://mail.example.com:587/ - This will connect to a SMTP server on the
alternative mail port.

The path part of the URL is protocol specific and whilst some examples are
given below this list is not conclusive:

.IP HTTP
The path part of an HTTP request specifies the file to retrieve and from what
directory. If the directory is not specified then the web server's root
directory is used. If the file is omitted then the default document will be
retrieved for either the directory specified or the root directory. The exact
resource returned for each URL is entirely dependent on the server's
configuration.

http://www.example.com - This gets the main page from the web server.

http://www.example.com/index.html - This returns the main page by explicitly
requesting it.

http://www.example.com/contactus/ - This returns the default document from
the contactus directory.

.IP FTP
The path part of an FTP request specifies the file to retrieve and from what
directory. If the file part is omitted then libcurl downloads the directory
listing for the directory specified. If the directory is omitted then
the directory listing for the root / home directory will be returned.

ftp://ftp.example.com - This retrieves the directory listing for the root
directory.

ftp://ftp.example.com/readme.txt - This downloads the file readme.txt from the
root directory.

ftp://ftp.example.com/libcurl/readme.txt - This downloads readme.txt from the
libcurl directory.

ftp://user:password@ftp.example.com/readme.txt - This retrieves the readme.txt
file from the user's home directory. When a username and password is
specified, everything that is specified in the path part is relative to the
user's home directory. To retrieve files from the root directory or a
directory underneath the root directory then the absolute path must be
specified by prepending an additional forward slash to the beginning of the
path.

ftp://user:password@ftp.example.com//readme.txt - This retrieves the readme.txt
from the root directory when logging in as a specified user.

.IP FILE
When a FILE:// URL is accessed on Windows systems, it can be crafted in a way
so that Windows attempts to connect to a (remote) machine when curl wants to
read or write such a path.
.IP SMTP
The path part of a SMTP request specifies the host name to present during
communication with the mail server. If the path is omitted then libcurl will
attempt to resolve the local computer's host name. However, this may not
return the fully qualified domain name that is required by some mail servers
and specifying this path allows you to set an alternative name, such as
your machine's fully qualified domain name, which you might have obtained
from an external function such as gethostname or getaddrinfo.

smtp://mail.example.com - This connects to the mail server at example.com and
sends your local computer's host name in the HELO / EHLO command.

smtp://mail.example.com/client.example.com - This will send client.example.com in
the HELO / EHLO command to the mail server at example.com.

.IP POP3
The path part of a POP3 request specifies the message ID to retrieve. If the
ID is not specified then a list of waiting messages is returned instead.

pop3://user:password@mail.example.com - This lists the available messages for
the user

pop3://user:password@mail.example.com/1 - This retrieves the first message for
the user

.IP IMAP
The path part of an IMAP request not only specifies the mailbox to list (Added
in 7.30.0) or select, but can also be used to check the UIDVALIDITY of the
mailbox, to specify the UID, SECTION (Added in 7.30.0) and PARTIAL octets
(Added in 7.37.0) of the message to fetch and to specify what messages to
search for (Added in 7.37.0).

imap://user:password@mail.example.com - Performs a top level folder list

imap://user:password@mail.example.com/INBOX - Performs a folder list on the
user's inbox

imap://user:password@mail.example.com/INBOX/;UID=1 - Selects the user's inbox
and fetches message with uid = 1

imap://user:password@mail.example.com/INBOX/;MAILINDEX=1 - Selects the user's inbox
and fetches the first message in the mail box

imap://user:password@mail.example.com/INBOX;UIDVALIDITY=50/;UID=2 - Selects
the user's inbox, checks the UIDVALIDITY of the mailbox is 50 and fetches
message 2 if it is

imap://user:password@mail.example.com/INBOX/;UID=3/;SECTION=TEXT - Selects the
user's inbox and fetches the text portion of message 3

imap://user:password@mail.example.com/INBOX/;UID=4/;PARTIAL=0.1024 - Selects
the user's inbox and fetches the first 1024 octets of message 4

imap://user:password@mail.example.com/INBOX?NEW - Selects the user's inbox and
checks for NEW messages

imap://user:password@mail.example.com/INBOX?SUBJECT%20shadows - Selects the
user's inbox and searches for messages containing "shadows" in the subject
line

For more information about the individual components of an IMAP URL please
see RFC5092.

.IP SCP
The path part of an SCP URL specifies the path and file to retrieve or
upload. The file part may not be omitted. The file is taken as an absolute
path from the root directory on the server. To specify a path relative to the
user's home directory on the server, prepend ~/ to the path portion.  If the
user name is not embedded in the URL, it can be set with the
\fICURLOPT_USERPWD(3)\fP or \fICURLOPT_USERNAME(3)\fP option.

scp://user@example.com/etc/issue - This specifies the file /etc/issue

scp://example.com/~/my-file - This specifies the file my-file in the
user's home directory on the server
.IP SFTP
The path part of an SFTP URL specifies the file to retrieve or upload. If the
path ends in a / then a directory listing is returned instead of a file.  If
the path is omitted entirely then the directory listing for the root / home
directory will be returned.  If the user name is not embedded in the URL, it
can be set with the \fICURLOPT_USERPWD(3)\fP or \fICURLOPT_USERNAME(3)\fP
option.

sftp://user:password@example.com/etc/issue - This specifies the file
/etc/issue

sftp://user@example.com/~/my-file - This specifies the file my-file in the
user's home directory

sftp://ssh.example.com/~/Documents/ - This requests a directory listing
of the Documents directory under the user's home directory

.IP SMB
The path part of a SMB request specifies the file to retrieve and from what
share and directory or the share to upload to and as such, may not be omitted.
If the user name is not embedded in the URL, it can be set with the
\fICURLOPT_USERPWD(3)\fP or \fICURLOPT_USERNAME(3)\fP option. If the user name
is embedded in the URL then it must contain the domain name and as such, the
backslash must be URL encoded as %2f.

smb://server.example.com/files/issue - This specifies the file "issue" located
in the root of the "files" share

smb://server.example.com/files/ -T issue - This specifies the file "issue" will
be uploaded to the root of the "files" share.

curl supports SMB version 1 (only)
.IP LDAP
The path part of a LDAP request can be used to specify the: Distinguished
Name, Attributes, Scope, Filter and Extension for a LDAP search. Each field
is separated by a question mark and when that field is not required an empty
string with the question mark separator should be included.

ldap://ldap.example.com/o=My%20Organisation - This will perform a LDAP search
with the DN as My Organisation.

ldap://ldap.example.com/o=My%20Organisation?postalAddress - This will perform
the same search but will only return postalAddress attributes.

ldap://ldap.example.com/?rootDomainNamingContext - This specifies an empty DN
and requests information about the rootDomainNamingContext attribute for an
Active Directory server.

For more information about the individual components of a LDAP URL please
see RFC4516.
.IP RTMP
There's no official URL spec for RTMP so libcurl uses the URL syntax supported
by the underlying librtmp library. It has a syntax where it wants a
traditional URL, followed by a space and a series of space-separated
name=value pairs.

While space is not typically a "legal" letter, libcurl accepts them. When a
user wants to pass in a '#' (hash) character it will be treated as a fragment
and get cut off by libcurl if provided literally. You will instead have to
escape it by providing it as backslash and its ASCII value in hexadecimal:
"\\23".

.RS 0
The application does not have to keep the string around after setting this
option.
.SH ENCODING
The string pointed to in the \fICURLOPT_URL(3)\fP argument is generally
expected to be a sequence of characters using an ASCII compatible encoding.

If libcurl is built with IDN support, the server name part of the URL can use







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







61
62
63
64
65
66
67






































































































































































































































68
69
70
71
72
73
74

The \fICURLOPT_URL(3)\fP string will be ignored if \fICURLOPT_CURLU(3)\fP is
set.

\fICURLOPT_URL(3)\fP or \fICURLOPT_CURLU(3)\fP \fBmust\fP be set before a
transfer is started.







































































































































































































































The application does not have to keep the string around after setting this
option.
.SH ENCODING
The string pointed to in the \fICURLOPT_URL(3)\fP argument is generally
expected to be a sequence of characters using an ASCII compatible encoding.

If libcurl is built with IDN support, the server name part of the URL can use
Changes to jni/curl/docs/libcurl/opts/CURLOPT_USERAGENT.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_USERAGENT 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_USERAGENT \- set HTTP user-agent header
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_USERAGENT, char *ua);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_USERAGENT 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_USERAGENT \- set HTTP user-agent header
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_USERAGENT, char *ua);
Changes to jni/curl/docs/libcurl/opts/CURLOPT_USERNAME.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_USERNAME 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_USERNAME \- user name to use in authentication
.SH SYNOPSIS
.nf
#include <curl/curl.h>








|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_USERNAME 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_USERNAME \- user name to use in authentication
.SH SYNOPSIS
.nf
#include <curl/curl.h>

Changes to jni/curl/docs/libcurl/opts/CURLOPT_USERPWD.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_USERPWD 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_USERPWD \- user name and password to use in authentication
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_USERPWD, char *userpwd);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_USERPWD 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_USERPWD \- user name and password to use in authentication
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_USERPWD, char *userpwd);
Changes to jni/curl/docs/libcurl/opts/CURLOPT_USE_SSL.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_USE_SSL 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_USE_SSL \- request using SSL / TLS for the transfer
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_USE_SSL, long level);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_USE_SSL 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_USE_SSL \- request using SSL / TLS for the transfer
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_USE_SSL, long level);
Changes to jni/curl/docs/libcurl/opts/CURLOPT_VERBOSE.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_VERBOSE 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_VERBOSE \- set verbose mode on/off
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_VERBOSE, long onoff);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_VERBOSE 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_VERBOSE \- set verbose mode on/off
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_VERBOSE, long onoff);
Changes to jni/curl/docs/libcurl/opts/CURLOPT_WILDCARDMATCH.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_WILDCARDMATCH 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_WILDCARDMATCH \- enable directory wildcard transfers
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_WILDCARDMATCH, long onoff);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_WILDCARDMATCH 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_WILDCARDMATCH \- enable directory wildcard transfers
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_WILDCARDMATCH, long onoff);
Changes to jni/curl/docs/libcurl/opts/CURLOPT_WRITEDATA.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_WRITEDATA 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_WRITEDATA \- custom pointer passed to the write callback
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_WRITEDATA, void *pointer);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_WRITEDATA 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_WRITEDATA \- custom pointer passed to the write callback
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_WRITEDATA, void *pointer);
Changes to jni/curl/docs/libcurl/opts/CURLOPT_WRITEFUNCTION.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_WRITEFUNCTION 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_WRITEFUNCTION \- set callback for writing received data
.SH SYNOPSIS
.nf
#include <curl/curl.h>








|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_WRITEFUNCTION 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_WRITEFUNCTION \- set callback for writing received data
.SH SYNOPSIS
.nf
#include <curl/curl.h>

Changes to jni/curl/docs/libcurl/opts/CURLOPT_XFERINFODATA.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_XFERINFODATA 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_XFERINFODATA \- custom pointer passed to the progress callback
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_XFERINFODATA, void *pointer);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_XFERINFODATA 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_XFERINFODATA \- custom pointer passed to the progress callback
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_XFERINFODATA, void *pointer);
Changes to jni/curl/docs/libcurl/opts/CURLOPT_XFERINFOFUNCTION.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_XFERINFOFUNCTION 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_XFERINFOFUNCTION \- callback to progress meter function
.SH SYNOPSIS
#include <curl/curl.h>

int progress_callback(void *clientp,







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_XFERINFOFUNCTION 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_XFERINFOFUNCTION \- callback to progress meter function
.SH SYNOPSIS
#include <curl/curl.h>

int progress_callback(void *clientp,
Changes to jni/curl/docs/libcurl/opts/CURLOPT_XOAUTH2_BEARER.3.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_XOAUTH2_BEARER 3 "November 04, 2020" "libcurl 7.74.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_XOAUTH2_BEARER \- specify OAuth 2.0 access token
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_XOAUTH2_BEARER, char *token);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_XOAUTH2_BEARER 3 "November 04, 2020" "libcurl 7.75.0" "curl_easy_setopt options"

.SH NAME
CURLOPT_XOAUTH2_BEARER \- specify OAuth 2.0 access token
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_XOAUTH2_BEARER, char *token);
Changes to jni/curl/docs/libcurl/opts/Makefile.in.
340
341
342
343
344
345
346

347
348
349
350
351
352
353
STRIP = @STRIP@
SUPPORT_FEATURES = @SUPPORT_FEATURES@
SUPPORT_PROTOCOLS = @SUPPORT_PROTOCOLS@
USE_ARES = @USE_ARES@
USE_BEARSSL = @USE_BEARSSL@
USE_GNUTLS = @USE_GNUTLS@
USE_GNUTLS_NETTLE = @USE_GNUTLS_NETTLE@

USE_LIBRTMP = @USE_LIBRTMP@
USE_LIBSSH = @USE_LIBSSH@
USE_LIBSSH2 = @USE_LIBSSH2@
USE_MBEDTLS = @USE_MBEDTLS@
USE_MESALINK = @USE_MESALINK@
USE_NGHTTP2 = @USE_NGHTTP2@
USE_NGHTTP3 = @USE_NGHTTP3@







>







340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
STRIP = @STRIP@
SUPPORT_FEATURES = @SUPPORT_FEATURES@
SUPPORT_PROTOCOLS = @SUPPORT_PROTOCOLS@
USE_ARES = @USE_ARES@
USE_BEARSSL = @USE_BEARSSL@
USE_GNUTLS = @USE_GNUTLS@
USE_GNUTLS_NETTLE = @USE_GNUTLS_NETTLE@
USE_HYPER = @USE_HYPER@
USE_LIBRTMP = @USE_LIBRTMP@
USE_LIBSSH = @USE_LIBSSH@
USE_LIBSSH2 = @USE_LIBSSH2@
USE_MBEDTLS = @USE_MBEDTLS@
USE_MESALINK = @USE_MESALINK@
USE_NGHTTP2 = @USE_NGHTTP2@
USE_NGHTTP3 = @USE_NGHTTP3@
780
781
782
783
784
785
786

787
788
789
790
791
792
793
  CURLOPT_UPLOAD.3                              \
  CURLOPT_UPLOAD_BUFFERSIZE.3                   \
  CURLOPT_URL.3                                 \
  CURLOPT_USERAGENT.3                           \
  CURLOPT_USERNAME.3                            \
  CURLOPT_USERPWD.3                             \
  CURLOPT_USE_SSL.3                             \

  CURLOPT_VERBOSE.3                             \
  CURLOPT_WILDCARDMATCH.3                       \
  CURLOPT_WRITEDATA.3                           \
  CURLOPT_WRITEFUNCTION.3                       \
  CURLOPT_XFERINFODATA.3                        \
  CURLOPT_XFERINFOFUNCTION.3                    \
  CURLOPT_XOAUTH2_BEARER.3







>







781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
  CURLOPT_UPLOAD.3                              \
  CURLOPT_UPLOAD_BUFFERSIZE.3                   \
  CURLOPT_URL.3                                 \
  CURLOPT_USERAGENT.3                           \
  CURLOPT_USERNAME.3                            \
  CURLOPT_USERPWD.3                             \
  CURLOPT_USE_SSL.3                             \
  CURLOPT_AWS_SIGV4.3                           \
  CURLOPT_VERBOSE.3                             \
  CURLOPT_WILDCARDMATCH.3                       \
  CURLOPT_WRITEDATA.3                           \
  CURLOPT_WRITEFUNCTION.3                       \
  CURLOPT_XFERINFODATA.3                        \
  CURLOPT_XFERINFOFUNCTION.3                    \
  CURLOPT_XOAUTH2_BEARER.3
Changes to jni/curl/docs/libcurl/opts/Makefile.inc.
378
379
380
381
382
383
384

385
386
387
388
389
390
391
  CURLOPT_UPLOAD.3                              \
  CURLOPT_UPLOAD_BUFFERSIZE.3                   \
  CURLOPT_URL.3                                 \
  CURLOPT_USERAGENT.3                           \
  CURLOPT_USERNAME.3                            \
  CURLOPT_USERPWD.3                             \
  CURLOPT_USE_SSL.3                             \

  CURLOPT_VERBOSE.3                             \
  CURLOPT_WILDCARDMATCH.3                       \
  CURLOPT_WRITEDATA.3                           \
  CURLOPT_WRITEFUNCTION.3                       \
  CURLOPT_XFERINFODATA.3                        \
  CURLOPT_XFERINFOFUNCTION.3                    \
  CURLOPT_XOAUTH2_BEARER.3







>







378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
  CURLOPT_UPLOAD.3                              \
  CURLOPT_UPLOAD_BUFFERSIZE.3                   \
  CURLOPT_URL.3                                 \
  CURLOPT_USERAGENT.3                           \
  CURLOPT_USERNAME.3                            \
  CURLOPT_USERPWD.3                             \
  CURLOPT_USE_SSL.3                             \
  CURLOPT_AWS_SIGV4.3                           \
  CURLOPT_VERBOSE.3                             \
  CURLOPT_WILDCARDMATCH.3                       \
  CURLOPT_WRITEDATA.3                           \
  CURLOPT_WRITEFUNCTION.3                       \
  CURLOPT_XFERINFODATA.3                        \
  CURLOPT_XFERINFOFUNCTION.3                    \
  CURLOPT_XOAUTH2_BEARER.3
Changes to jni/curl/docs/libcurl/symbols-in-versions.
25
26
27
28
29
30
31

32
33
34
35
36
37
38
CURLAUTH_GSSAPI                 7.55.0
CURLAUTH_GSSNEGOTIATE           7.10.6       7.38.0
CURLAUTH_NEGOTIATE              7.38.0
CURLAUTH_NONE                   7.10.6
CURLAUTH_NTLM                   7.10.6
CURLAUTH_NTLM_WB                7.22.0
CURLAUTH_ONLY                   7.21.3

CURLCLOSEPOLICY_CALLBACK        7.7
CURLCLOSEPOLICY_LEAST_RECENTLY_USED 7.7
CURLCLOSEPOLICY_LEAST_TRAFFIC   7.7
CURLCLOSEPOLICY_NONE            7.7
CURLCLOSEPOLICY_OLDEST          7.7
CURLCLOSEPOLICY_SLOWEST         7.7
CURLE_ABORTED_BY_CALLBACK       7.1







>







25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
CURLAUTH_GSSAPI                 7.55.0
CURLAUTH_GSSNEGOTIATE           7.10.6       7.38.0
CURLAUTH_NEGOTIATE              7.38.0
CURLAUTH_NONE                   7.10.6
CURLAUTH_NTLM                   7.10.6
CURLAUTH_NTLM_WB                7.22.0
CURLAUTH_ONLY                   7.21.3
CURLAUTH_AWS_SIGV4              7.75.0
CURLCLOSEPOLICY_CALLBACK        7.7
CURLCLOSEPOLICY_LEAST_RECENTLY_USED 7.7
CURLCLOSEPOLICY_LEAST_TRAFFIC   7.7
CURLCLOSEPOLICY_NONE            7.7
CURLCLOSEPOLICY_OLDEST          7.7
CURLCLOSEPOLICY_SLOWEST         7.7
CURLE_ABORTED_BY_CALLBACK       7.1
664
665
666
667
668
669
670

671
672
673
674
675
676
677
CURLOPT_UPLOAD                  7.1
CURLOPT_UPLOAD_BUFFERSIZE       7.62.0
CURLOPT_URL                     7.1
CURLOPT_USERAGENT               7.1
CURLOPT_USERNAME                7.19.1
CURLOPT_USERPWD                 7.1
CURLOPT_USE_SSL                 7.17.0

CURLOPT_VERBOSE                 7.1
CURLOPT_WILDCARDMATCH           7.21.0
CURLOPT_WRITEDATA               7.9.7
CURLOPT_WRITEFUNCTION           7.1
CURLOPT_WRITEHEADER             7.1
CURLOPT_WRITEINFO               7.1
CURLOPT_XFERINFODATA            7.32.0







>







665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
CURLOPT_UPLOAD                  7.1
CURLOPT_UPLOAD_BUFFERSIZE       7.62.0
CURLOPT_URL                     7.1
CURLOPT_USERAGENT               7.1
CURLOPT_USERNAME                7.19.1
CURLOPT_USERPWD                 7.1
CURLOPT_USE_SSL                 7.17.0
CURLOPT_AWS_SIGV4               7.75.0
CURLOPT_VERBOSE                 7.1
CURLOPT_WILDCARDMATCH           7.21.0
CURLOPT_WRITEDATA               7.9.7
CURLOPT_WRITEFUNCTION           7.1
CURLOPT_WRITEHEADER             7.1
CURLOPT_WRITEINFO               7.1
CURLOPT_XFERINFODATA            7.32.0
697
698
699
700
701
702
703

704
705
706
707
708
709
710
CURLPIPE_NOTHING                7.43.0
CURLPROTO_ALL                   7.19.4
CURLPROTO_DICT                  7.19.4
CURLPROTO_FILE                  7.19.4
CURLPROTO_FTP                   7.19.4
CURLPROTO_FTPS                  7.19.4
CURLPROTO_GOPHER                7.21.2

CURLPROTO_HTTP                  7.19.4
CURLPROTO_HTTPS                 7.19.4
CURLPROTO_IMAP                  7.20.0
CURLPROTO_IMAPS                 7.20.0
CURLPROTO_LDAP                  7.19.4
CURLPROTO_LDAPS                 7.19.4
CURLPROTO_MQTT                  7.71.0







>







699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
CURLPIPE_NOTHING                7.43.0
CURLPROTO_ALL                   7.19.4
CURLPROTO_DICT                  7.19.4
CURLPROTO_FILE                  7.19.4
CURLPROTO_FTP                   7.19.4
CURLPROTO_FTPS                  7.19.4
CURLPROTO_GOPHER                7.21.2
CURLPROTO_GOPHERS               7.75.0
CURLPROTO_HTTP                  7.19.4
CURLPROTO_HTTPS                 7.19.4
CURLPROTO_IMAP                  7.20.0
CURLPROTO_IMAPS                 7.20.0
CURLPROTO_LDAP                  7.19.4
CURLPROTO_LDAPS                 7.19.4
CURLPROTO_MQTT                  7.71.0
863
864
865
866
867
868
869

870
871
872
873
874
875
876
CURLU_PATH_AS_IS                7.62.0
CURLU_URLDECODE                 7.62.0
CURLU_URLENCODE                 7.62.0
CURLVERSION_EIGHTH              7.72.0
CURLVERSION_FIFTH               7.57.0
CURLVERSION_FIRST               7.10
CURLVERSION_FOURTH              7.16.1

CURLVERSION_NOW                 7.10
CURLVERSION_SECOND              7.11.1
CURLVERSION_SEVENTH             7.70.0
CURLVERSION_SIXTH               7.66.0
CURLVERSION_THIRD               7.12.0
CURL_CHUNK_BGN_FUNC_FAIL        7.21.0
CURL_CHUNK_BGN_FUNC_OK          7.21.0







>







866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
CURLU_PATH_AS_IS                7.62.0
CURLU_URLDECODE                 7.62.0
CURLU_URLENCODE                 7.62.0
CURLVERSION_EIGHTH              7.72.0
CURLVERSION_FIFTH               7.57.0
CURLVERSION_FIRST               7.10
CURLVERSION_FOURTH              7.16.1
CURLVERSION_NINTH               7.75.0
CURLVERSION_NOW                 7.10
CURLVERSION_SECOND              7.11.1
CURLVERSION_SEVENTH             7.70.0
CURLVERSION_SIXTH               7.66.0
CURLVERSION_THIRD               7.12.0
CURL_CHUNK_BGN_FUNC_FAIL        7.21.0
CURL_CHUNK_BGN_FUNC_OK          7.21.0
Changes to jni/curl/docs/options-in-versions.
10
11
12
13
14
15
16

17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32

33
34
35
36
37
38
39

 Long (short)                        Introduced

--abstract-unix-socket               7.53.0
--alt-svc                            7.64.1
--anyauth                            7.10.6
--append (-a)                        4.8

--basic                              7.10.6
--cacert                             7.5
--capath                             7.9.8
--cert (-E)                          5.0
--cert-status                        7.41.0
--cert-type                          7.9.3
--ciphers                            7.9
--compressed                         7.10
--compressed-ssh                     7.56.0
--config (-K)                        4.10
--connect-timeout                    7.7
--connect-to                         7.49.0
--continue-at (-C)                   4.8
--cookie (-b)                        4.9
--cookie-jar (-c)                    7.9
--create-dirs                        7.10.3

--crlf                               5.7
--crlfile                            7.19.7
--curves                             7.73.0
--data (-d)                          4.0
--data-ascii                         7.2
--data-binary                        7.2
--data-raw                           7.43.0







>
















>







10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41

 Long (short)                        Introduced

--abstract-unix-socket               7.53.0
--alt-svc                            7.64.1
--anyauth                            7.10.6
--append (-a)                        4.8
--aws-sigv4                          7.75.0
--basic                              7.10.6
--cacert                             7.5
--capath                             7.9.8
--cert (-E)                          5.0
--cert-status                        7.41.0
--cert-type                          7.9.3
--ciphers                            7.9
--compressed                         7.10
--compressed-ssh                     7.56.0
--config (-K)                        4.10
--connect-timeout                    7.7
--connect-to                         7.49.0
--continue-at (-C)                   4.8
--cookie (-b)                        4.9
--cookie-jar (-c)                    7.9
--create-dirs                        7.10.3
--create-file-mode                   7.75.0
--crlf                               5.7
--crlfile                            7.19.7
--curves                             7.73.0
--data (-d)                          4.0
--data-ascii                         7.2
--data-binary                        7.2
--data-raw                           7.43.0
Changes to jni/curl/include/Makefile.in.
325
326
327
328
329
330
331

332
333
334
335
336
337
338
STRIP = @STRIP@
SUPPORT_FEATURES = @SUPPORT_FEATURES@
SUPPORT_PROTOCOLS = @SUPPORT_PROTOCOLS@
USE_ARES = @USE_ARES@
USE_BEARSSL = @USE_BEARSSL@
USE_GNUTLS = @USE_GNUTLS@
USE_GNUTLS_NETTLE = @USE_GNUTLS_NETTLE@

USE_LIBRTMP = @USE_LIBRTMP@
USE_LIBSSH = @USE_LIBSSH@
USE_LIBSSH2 = @USE_LIBSSH2@
USE_MBEDTLS = @USE_MBEDTLS@
USE_MESALINK = @USE_MESALINK@
USE_NGHTTP2 = @USE_NGHTTP2@
USE_NGHTTP3 = @USE_NGHTTP3@







>







325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
STRIP = @STRIP@
SUPPORT_FEATURES = @SUPPORT_FEATURES@
SUPPORT_PROTOCOLS = @SUPPORT_PROTOCOLS@
USE_ARES = @USE_ARES@
USE_BEARSSL = @USE_BEARSSL@
USE_GNUTLS = @USE_GNUTLS@
USE_GNUTLS_NETTLE = @USE_GNUTLS_NETTLE@
USE_HYPER = @USE_HYPER@
USE_LIBRTMP = @USE_LIBRTMP@
USE_LIBSSH = @USE_LIBSSH@
USE_LIBSSH2 = @USE_LIBSSH2@
USE_MBEDTLS = @USE_MBEDTLS@
USE_MESALINK = @USE_MESALINK@
USE_NGHTTP2 = @USE_NGHTTP2@
USE_NGHTTP3 = @USE_NGHTTP3@
Changes to jni/curl/include/curl/Makefile.in.
312
313
314
315
316
317
318

319
320
321
322
323
324
325
STRIP = @STRIP@
SUPPORT_FEATURES = @SUPPORT_FEATURES@
SUPPORT_PROTOCOLS = @SUPPORT_PROTOCOLS@
USE_ARES = @USE_ARES@
USE_BEARSSL = @USE_BEARSSL@
USE_GNUTLS = @USE_GNUTLS@
USE_GNUTLS_NETTLE = @USE_GNUTLS_NETTLE@

USE_LIBRTMP = @USE_LIBRTMP@
USE_LIBSSH = @USE_LIBSSH@
USE_LIBSSH2 = @USE_LIBSSH2@
USE_MBEDTLS = @USE_MBEDTLS@
USE_MESALINK = @USE_MESALINK@
USE_NGHTTP2 = @USE_NGHTTP2@
USE_NGHTTP3 = @USE_NGHTTP3@







>







312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
STRIP = @STRIP@
SUPPORT_FEATURES = @SUPPORT_FEATURES@
SUPPORT_PROTOCOLS = @SUPPORT_PROTOCOLS@
USE_ARES = @USE_ARES@
USE_BEARSSL = @USE_BEARSSL@
USE_GNUTLS = @USE_GNUTLS@
USE_GNUTLS_NETTLE = @USE_GNUTLS_NETTLE@
USE_HYPER = @USE_HYPER@
USE_LIBRTMP = @USE_LIBRTMP@
USE_LIBSSH = @USE_LIBSSH@
USE_LIBSSH2 = @USE_LIBSSH2@
USE_MBEDTLS = @USE_MBEDTLS@
USE_MESALINK = @USE_MESALINK@
USE_NGHTTP2 = @USE_NGHTTP2@
USE_NGHTTP3 = @USE_NGHTTP3@
Changes to jni/curl/include/curl/curl.h.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#ifndef CURLINC_CURL_H
#define CURLINC_CURL_H
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2020, 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 https://curl.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









|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#ifndef CURLINC_CURL_H
#define CURLINC_CURL_H
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2021, 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 https://curl.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
783
784
785
786
787
788
789

790
791
792
793
794
795
796
#define CURLAUTH_GSSNEGOTIATE CURLAUTH_NEGOTIATE
/* Used for CURLOPT_SOCKS5_AUTH to stay terminologically correct */
#define CURLAUTH_GSSAPI 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_BEARER       (((unsigned long)1)<<6)

#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 */







>







783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
#define CURLAUTH_GSSNEGOTIATE CURLAUTH_NEGOTIATE
/* Used for CURLOPT_SOCKS5_AUTH to stay terminologically correct */
#define CURLAUTH_GSSAPI 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_BEARER       (((unsigned long)1)<<6)
#define CURLAUTH_AWS_SIGV4    (((unsigned long)1)<<7)
#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 */
1011
1012
1013
1014
1015
1016
1017

1018
1019
1020
1021
1022
1023
1024
#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_MQTT   (1<<28)

#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







>







1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
#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_MQTT   (1<<28)
#define CURLPROTO_GOPHERS (1<<29)
#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
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
  CURLOPT(CURLOPT_HTTP_CONTENT_DECODING, CURLOPTTYPE_LONG, 158),

  /* Permission used when creating new files and directories on the remote
     server for protocols that support it, SFTP/SCP/FILE */
  CURLOPT(CURLOPT_NEW_FILE_PERMS, CURLOPTTYPE_LONG, 159),
  CURLOPT(CURLOPT_NEW_DIRECTORY_PERMS, CURLOPTTYPE_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 */
  CURLOPT(CURLOPT_POSTREDIR, CURLOPTTYPE_VALUES, 161),

  /* used by scp/sftp to verify the host's public key */
  CURLOPT(CURLOPT_SSH_HOST_PUBLIC_KEY_MD5, CURLOPTTYPE_STRINGPOINT, 162),

  /* Callback function for opening socket (instead of socket(2)). Optionally,







|







1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
  CURLOPT(CURLOPT_HTTP_CONTENT_DECODING, CURLOPTTYPE_LONG, 158),

  /* Permission used when creating new files and directories on the remote
     server for protocols that support it, SFTP/SCP/FILE */
  CURLOPT(CURLOPT_NEW_FILE_PERMS, CURLOPTTYPE_LONG, 159),
  CURLOPT(CURLOPT_NEW_DIRECTORY_PERMS, CURLOPTTYPE_LONG, 160),

  /* Set the behavior of POST when redirecting. Values must be set to one
     of CURL_REDIR* defines below. This used to be called CURLOPT_POST301 */
  CURLOPT(CURLOPT_POSTREDIR, CURLOPTTYPE_VALUES, 161),

  /* used by scp/sftp to verify the host's public key */
  CURLOPT(CURLOPT_SSH_HOST_PUBLIC_KEY_MD5, CURLOPTTYPE_STRINGPOINT, 162),

  /* Callback function for opening socket (instead of socket(2)). Optionally,
2069
2070
2071
2072
2073
2074
2075



2076
2077
2078
2079
2080
2081
2082
  CURLOPT(CURLOPT_HSTSREADFUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 301),
  CURLOPT(CURLOPT_HSTSREADDATA, CURLOPTTYPE_CBPOINT, 302),

  /* HSTS write callback */
  CURLOPT(CURLOPT_HSTSWRITEFUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 303),
  CURLOPT(CURLOPT_HSTSWRITEDATA, CURLOPTTYPE_CBPOINT, 304),




  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 */







>
>
>







2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
  CURLOPT(CURLOPT_HSTSREADFUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 301),
  CURLOPT(CURLOPT_HSTSREADDATA, CURLOPTTYPE_CBPOINT, 302),

  /* HSTS write callback */
  CURLOPT(CURLOPT_HSTSWRITEFUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 303),
  CURLOPT(CURLOPT_HSTSWRITEDATA, CURLOPTTYPE_CBPOINT, 304),

  /* Parameters for V4 signature */
  CURLOPT(CURLOPT_AWS_SIGV4, CURLOPTTYPE_STRINGPOINT, 305),

  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 */
2845
2846
2847
2848
2849
2850
2851

2852
2853
2854
2855
2856
2857
2858
2859
2860
2861
2862
2863
2864
2865
2866
2867
  CURLVERSION_SECOND,
  CURLVERSION_THIRD,
  CURLVERSION_FOURTH,
  CURLVERSION_FIFTH,
  CURLVERSION_SIXTH,
  CURLVERSION_SEVENTH,
  CURLVERSION_EIGHTH,

  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_EIGHTH

struct curl_version_info_data {
  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 */







>








|







2850
2851
2852
2853
2854
2855
2856
2857
2858
2859
2860
2861
2862
2863
2864
2865
2866
2867
2868
2869
2870
2871
2872
2873
  CURLVERSION_SECOND,
  CURLVERSION_THIRD,
  CURLVERSION_FOURTH,
  CURLVERSION_FIFTH,
  CURLVERSION_SIXTH,
  CURLVERSION_SEVENTH,
  CURLVERSION_EIGHTH,
  CURLVERSION_NINTH,
  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_NINTH

struct curl_version_info_data {
  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 */
2904
2905
2906
2907
2908
2909
2910


2911
2912
2913
2914
2915
2916
2917
                                  be NULL */

  /* These fields were added in CURLVERSION_EIGHTH */
  unsigned int zstd_ver_num; /* Numeric Zstd version
                                  (MAJOR << 24) | (MINOR << 12) | PATCH */
  const char *zstd_version; /* human readable string. */



};
typedef struct curl_version_info_data 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 */







>
>







2910
2911
2912
2913
2914
2915
2916
2917
2918
2919
2920
2921
2922
2923
2924
2925
                                  be NULL */

  /* These fields were added in CURLVERSION_EIGHTH */
  unsigned int zstd_ver_num; /* Numeric Zstd version
                                  (MAJOR << 24) | (MINOR << 12) | PATCH */
  const char *zstd_version; /* human readable string. */

  /* These fields were added in CURLVERSION_NINTH */
  const char *hyper_version; /* human readable string. */
};
typedef struct curl_version_info_data 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 */
Changes to jni/curl/include/curl/curlver.h.
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
   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 - 2020 Daniel Stenberg, <daniel@haxx.se>."

/* This is the version number of the libcurl package from which this header
   file origins: */
#define LIBCURL_VERSION "7.74.0"

/* The numeric version number is also available "in parts" by using these
   defines: */
#define LIBCURL_VERSION_MAJOR 7
#define LIBCURL_VERSION_MINOR 74
#define LIBCURL_VERSION_PATCH 0

/* This is the numeric version of the libcurl version number, meant for easier
   parsing and comparisons by programs. The LIBCURL_VERSION_NUM define will
   always follow this syntax:

         0xXXYYZZ







|




|







26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
   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 - 2020 Daniel Stenberg, <daniel@haxx.se>."

/* This is the version number of the libcurl package from which this header
   file origins: */
#define LIBCURL_VERSION "7.75.0"

/* The numeric version number is also available "in parts" by using these
   defines: */
#define LIBCURL_VERSION_MAJOR 7
#define LIBCURL_VERSION_MINOR 75
#define LIBCURL_VERSION_PATCH 0

/* This is the numeric version of the libcurl version number, meant for easier
   parsing and comparisons by programs. The LIBCURL_VERSION_NUM define will
   always follow this syntax:

         0xXXYYZZ
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
   and it is always a greater number in a more recent release. It makes
   comparisons with greater than and less than work.

   Note: This define is the full hex number and _does not_ use the
   CURL_VERSION_BITS() macro since curl's own configure script greps for it
   and needs it to contain the full number.
*/
#define LIBCURL_VERSION_NUM 0x074a00

/*
 * 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 follows this template:
 *
 * "2007-11-23"
 */
#define LIBCURL_TIMESTAMP "2020-12-09"

#define CURL_VERSION_BITS(x,y,z) ((x)<<16|(y)<<8|(z))
#define CURL_AT_LEAST_VERSION(x,y,z) \
  (LIBCURL_VERSION_NUM >= CURL_VERSION_BITS(x, y, z))

#endif /* CURLINC_CURLVER_H */







|










|






53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
   and it is always a greater number in a more recent release. It makes
   comparisons with greater than and less than work.

   Note: This define is the full hex number and _does not_ use the
   CURL_VERSION_BITS() macro since curl's own configure script greps for it
   and needs it to contain the full number.
*/
#define LIBCURL_VERSION_NUM 0x074b00

/*
 * 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 follows this template:
 *
 * "2007-11-23"
 */
#define LIBCURL_TIMESTAMP "2021-02-03"

#define CURL_VERSION_BITS(x,y,z) ((x)<<16|(y)<<8|(z))
#define CURL_AT_LEAST_VERSION(x,y,z) \
  (LIBCURL_VERSION_NUM >= CURL_VERSION_BITS(x, y, z))

#endif /* CURLINC_CURLVER_H */
Changes to jni/curl/include/curl/typecheck-gcc.h.
330
331
332
333
334
335
336

337
338
339
340
341
342
343
   (option) == CURLOPT_TLSAUTH_PASSWORD ||                                    \
   (option) == CURLOPT_TLSAUTH_TYPE ||                                        \
   (option) == CURLOPT_TLSAUTH_USERNAME ||                                    \
   (option) == CURLOPT_UNIX_SOCKET_PATH ||                                    \
   (option) == CURLOPT_URL ||                                                 \
   (option) == CURLOPT_USERAGENT ||                                           \
   (option) == CURLOPT_USERNAME ||                                            \

   (option) == CURLOPT_USERPWD ||                                             \
   (option) == CURLOPT_XOAUTH2_BEARER ||                                      \
   (option) == CURLOPT_SSL_EC_CURVES ||                                       \
   0)

/* evaluates to true if option takes a curl_write_callback argument */
#define curlcheck_write_cb_option(option)                               \







>







330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
   (option) == CURLOPT_TLSAUTH_PASSWORD ||                                    \
   (option) == CURLOPT_TLSAUTH_TYPE ||                                        \
   (option) == CURLOPT_TLSAUTH_USERNAME ||                                    \
   (option) == CURLOPT_UNIX_SOCKET_PATH ||                                    \
   (option) == CURLOPT_URL ||                                                 \
   (option) == CURLOPT_USERAGENT ||                                           \
   (option) == CURLOPT_USERNAME ||                                            \
   (option) == CURLOPT_AWS_SIGV4 ||                                           \
   (option) == CURLOPT_USERPWD ||                                             \
   (option) == CURLOPT_XOAUTH2_BEARER ||                                      \
   (option) == CURLOPT_SSL_EC_CURVES ||                                       \
   0)

/* evaluates to true if option takes a curl_write_callback argument */
#define curlcheck_write_cb_option(option)                               \
Changes to jni/curl/lib/Makefile.in.
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#***************************************************************************
#                                  _   _ ____  _
#  Project                     ___| | | |  _ \| |
#                             / __| | | | |_) | |
#                            | (__| |_| |  _ <| |___
#                             \___|\___/|_| \_\_____|
#
# Copyright (C) 1998 - 2020, 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 https://curl.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







|







17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#***************************************************************************
#                                  _   _ ____  _
#  Project                     ___| | | |  _ \| |
#                             / __| | | | |_) | |
#                            | (__| |_| |  _ <| |___
#                             \___|\___/|_| \_\_____|
#
# Copyright (C) 1998 - 2021, 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 https://curl.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
177
178
179
180
181
182
183
184

185
186
187
188
189
190
191
192
193
194
195
196

197
198
199
200
201
202
203
204

205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
         $(am__cd) "$$dir" && rm -f $$files; }; \
  }
am__installdirs = "$(DESTDIR)$(libdir)"
LTLIBRARIES = $(lib_LTLIBRARIES) $(noinst_LTLIBRARIES)
libcurl_la_LIBADD =
am__objects_1 = libcurl_la-altsvc.lo libcurl_la-amigaos.lo \
	libcurl_la-asyn-ares.lo libcurl_la-asyn-thread.lo \
	libcurl_la-base64.lo libcurl_la-conncache.lo \

	libcurl_la-connect.lo libcurl_la-content_encoding.lo \
	libcurl_la-cookie.lo libcurl_la-curl_addrinfo.lo \
	libcurl_la-curl_ctype.lo libcurl_la-curl_des.lo \
	libcurl_la-curl_endian.lo libcurl_la-curl_fnmatch.lo \
	libcurl_la-curl_get_line.lo libcurl_la-curl_gethostname.lo \
	libcurl_la-curl_gssapi.lo libcurl_la-curl_memrchr.lo \
	libcurl_la-curl_multibyte.lo libcurl_la-curl_ntlm_core.lo \
	libcurl_la-curl_ntlm_wb.lo libcurl_la-curl_path.lo \
	libcurl_la-curl_range.lo libcurl_la-curl_rtmp.lo \
	libcurl_la-curl_sasl.lo libcurl_la-curl_sspi.lo \
	libcurl_la-curl_threads.lo libcurl_la-dict.lo \
	libcurl_la-dotdot.lo libcurl_la-easy.lo libcurl_la-escape.lo \

	libcurl_la-file.lo libcurl_la-fileinfo.lo \
	libcurl_la-formdata.lo libcurl_la-ftp.lo libcurl_la-url.lo \
	libcurl_la-ftplistparser.lo libcurl_la-getenv.lo \
	libcurl_la-getinfo.lo libcurl_la-gopher.lo libcurl_la-hash.lo \
	libcurl_la-hmac.lo libcurl_la-hostasyn.lo \
	libcurl_la-hostcheck.lo libcurl_la-hostip.lo \
	libcurl_la-hostip4.lo libcurl_la-hostip6.lo \
	libcurl_la-hostsyn.lo libcurl_la-http.lo libcurl_la-http2.lo \

	libcurl_la-http_chunks.lo libcurl_la-http_digest.lo \
	libcurl_la-http_negotiate.lo libcurl_la-http_ntlm.lo \
	libcurl_la-http_proxy.lo libcurl_la-idn_win32.lo \
	libcurl_la-if2ip.lo libcurl_la-imap.lo libcurl_la-inet_ntop.lo \
	libcurl_la-inet_pton.lo libcurl_la-krb5.lo libcurl_la-ldap.lo \
	libcurl_la-llist.lo libcurl_la-md4.lo libcurl_la-md5.lo \
	libcurl_la-memdebug.lo libcurl_la-mime.lo \
	libcurl_la-mprintf.lo libcurl_la-mqtt.lo libcurl_la-multi.lo \
	libcurl_la-netrc.lo libcurl_la-non-ascii.lo \
	libcurl_la-nonblock.lo libcurl_la-openldap.lo \
	libcurl_la-parsedate.lo libcurl_la-pingpong.lo \
	libcurl_la-pop3.lo libcurl_la-progress.lo libcurl_la-psl.lo \
	libcurl_la-doh.lo libcurl_la-rand.lo libcurl_la-rename.lo \
	libcurl_la-rtsp.lo libcurl_la-select.lo libcurl_la-sendf.lo \
	libcurl_la-setopt.lo libcurl_la-sha256.lo libcurl_la-share.lo \
	libcurl_la-slist.lo libcurl_la-smb.lo libcurl_la-smtp.lo \
	libcurl_la-socketpair.lo libcurl_la-socks.lo \
	libcurl_la-socks_gssapi.lo libcurl_la-socks_sspi.lo \
	libcurl_la-speedcheck.lo libcurl_la-splay.lo \
	libcurl_la-strcase.lo libcurl_la-strdup.lo \
	libcurl_la-strerror.lo libcurl_la-strtok.lo \
	libcurl_la-strtoofft.lo libcurl_la-system_win32.lo \
	libcurl_la-telnet.lo libcurl_la-tftp.lo libcurl_la-timeval.lo \
	libcurl_la-transfer.lo libcurl_la-urlapi.lo \
	libcurl_la-version.lo libcurl_la-warnless.lo \
	libcurl_la-wildcard.lo libcurl_la-x509asn1.lo \
	libcurl_la-dynbuf.lo libcurl_la-version_win32.lo \
	libcurl_la-easyoptions.lo libcurl_la-easygetopt.lo \
	libcurl_la-hsts.lo
am__dirstamp = $(am__leading_dot)dirstamp
am__objects_2 = vauth/libcurl_la-cleartext.lo vauth/libcurl_la-cram.lo \
	vauth/libcurl_la-digest.lo vauth/libcurl_la-digest_sspi.lo \
	vauth/libcurl_la-krb5_gssapi.lo vauth/libcurl_la-krb5_sspi.lo \
	vauth/libcurl_la-ntlm.lo vauth/libcurl_la-ntlm_sspi.lo \
	vauth/libcurl_la-oauth2.lo vauth/libcurl_la-spnego_gssapi.lo \
	vauth/libcurl_la-spnego_sspi.lo vauth/libcurl_la-vauth.lo







|
>
|
|
|
|
|
|
|
|
|
|
|
|
>
|
|





|
>
|
|
|









|
|
|
|
|
|
<
|



|
|
|
<
<
|







177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225

226
227
228
229
230
231
232


233
234
235
236
237
238
239
240
         $(am__cd) "$$dir" && rm -f $$files; }; \
  }
am__installdirs = "$(DESTDIR)$(libdir)"
LTLIBRARIES = $(lib_LTLIBRARIES) $(noinst_LTLIBRARIES)
libcurl_la_LIBADD =
am__objects_1 = libcurl_la-altsvc.lo libcurl_la-amigaos.lo \
	libcurl_la-asyn-ares.lo libcurl_la-asyn-thread.lo \
	libcurl_la-base64.lo libcurl_la-c-hyper.lo \
	libcurl_la-conncache.lo libcurl_la-connect.lo \
	libcurl_la-content_encoding.lo libcurl_la-cookie.lo \
	libcurl_la-curl_addrinfo.lo libcurl_la-curl_ctype.lo \
	libcurl_la-curl_des.lo libcurl_la-curl_endian.lo \
	libcurl_la-curl_fnmatch.lo libcurl_la-curl_get_line.lo \
	libcurl_la-curl_gethostname.lo libcurl_la-curl_gssapi.lo \
	libcurl_la-curl_memrchr.lo libcurl_la-curl_multibyte.lo \
	libcurl_la-curl_ntlm_core.lo libcurl_la-curl_ntlm_wb.lo \
	libcurl_la-curl_path.lo libcurl_la-curl_range.lo \
	libcurl_la-curl_rtmp.lo libcurl_la-curl_sasl.lo \
	libcurl_la-curl_sspi.lo libcurl_la-curl_threads.lo \
	libcurl_la-dict.lo libcurl_la-doh.lo libcurl_la-dotdot.lo \
	libcurl_la-dynbuf.lo libcurl_la-easy.lo \
	libcurl_la-easygetopt.lo libcurl_la-easyoptions.lo \
	libcurl_la-escape.lo libcurl_la-file.lo libcurl_la-fileinfo.lo \
	libcurl_la-formdata.lo libcurl_la-ftp.lo \
	libcurl_la-ftplistparser.lo libcurl_la-getenv.lo \
	libcurl_la-getinfo.lo libcurl_la-gopher.lo libcurl_la-hash.lo \
	libcurl_la-hmac.lo libcurl_la-hostasyn.lo \
	libcurl_la-hostcheck.lo libcurl_la-hostip.lo \
	libcurl_la-hostip4.lo libcurl_la-hostip6.lo \
	libcurl_la-hostsyn.lo libcurl_la-hsts.lo libcurl_la-http.lo \
	libcurl_la-http2.lo libcurl_la-http_chunks.lo \
	libcurl_la-http_digest.lo libcurl_la-http_negotiate.lo \
	libcurl_la-http_ntlm.lo libcurl_la-http_proxy.lo \
	libcurl_la-http_aws_sigv4.lo libcurl_la-idn_win32.lo \
	libcurl_la-if2ip.lo libcurl_la-imap.lo libcurl_la-inet_ntop.lo \
	libcurl_la-inet_pton.lo libcurl_la-krb5.lo libcurl_la-ldap.lo \
	libcurl_la-llist.lo libcurl_la-md4.lo libcurl_la-md5.lo \
	libcurl_la-memdebug.lo libcurl_la-mime.lo \
	libcurl_la-mprintf.lo libcurl_la-mqtt.lo libcurl_la-multi.lo \
	libcurl_la-netrc.lo libcurl_la-non-ascii.lo \
	libcurl_la-nonblock.lo libcurl_la-openldap.lo \
	libcurl_la-parsedate.lo libcurl_la-pingpong.lo \
	libcurl_la-pop3.lo libcurl_la-progress.lo libcurl_la-psl.lo \
	libcurl_la-rand.lo libcurl_la-rename.lo libcurl_la-rtsp.lo \
	libcurl_la-select.lo libcurl_la-sendf.lo libcurl_la-setopt.lo \
	libcurl_la-sha256.lo libcurl_la-share.lo libcurl_la-slist.lo \
	libcurl_la-smb.lo libcurl_la-smtp.lo libcurl_la-socketpair.lo \
	libcurl_la-socks.lo libcurl_la-socks_gssapi.lo \
	libcurl_la-socks_sspi.lo libcurl_la-speedcheck.lo \

	libcurl_la-splay.lo libcurl_la-strcase.lo libcurl_la-strdup.lo \
	libcurl_la-strerror.lo libcurl_la-strtok.lo \
	libcurl_la-strtoofft.lo libcurl_la-system_win32.lo \
	libcurl_la-telnet.lo libcurl_la-tftp.lo libcurl_la-timeval.lo \
	libcurl_la-transfer.lo libcurl_la-url.lo libcurl_la-urlapi.lo \
	libcurl_la-version.lo libcurl_la-version_win32.lo \
	libcurl_la-warnless.lo libcurl_la-wildcard.lo \


	libcurl_la-x509asn1.lo
am__dirstamp = $(am__leading_dot)dirstamp
am__objects_2 = vauth/libcurl_la-cleartext.lo vauth/libcurl_la-cram.lo \
	vauth/libcurl_la-digest.lo vauth/libcurl_la-digest_sspi.lo \
	vauth/libcurl_la-krb5_gssapi.lo vauth/libcurl_la-krb5_sspi.lo \
	vauth/libcurl_la-ntlm.lo vauth/libcurl_la-ntlm_sspi.lo \
	vauth/libcurl_la-oauth2.lo vauth/libcurl_la-spnego_gssapi.lo \
	vauth/libcurl_la-spnego_sspi.lo vauth/libcurl_la-vauth.lo
264
265
266
267
268
269
270
271

272
273
274
275
276
277
278
279
280
281
282
283

284
285
286
287
288
289
290
291
292
293
294
295
296

297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319

320
321
322
323
324
325
326
327
328
329
330
331
am__v_lt_1 = 
libcurl_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
	$(LIBTOOLFLAGS) --mode=link $(CCLD) $(libcurl_la_CFLAGS) \
	$(CFLAGS) $(libcurl_la_LDFLAGS) $(LDFLAGS) -o $@
libcurlu_la_LIBADD =
am__objects_9 = libcurlu_la-altsvc.lo libcurlu_la-amigaos.lo \
	libcurlu_la-asyn-ares.lo libcurlu_la-asyn-thread.lo \
	libcurlu_la-base64.lo libcurlu_la-conncache.lo \

	libcurlu_la-connect.lo libcurlu_la-content_encoding.lo \
	libcurlu_la-cookie.lo libcurlu_la-curl_addrinfo.lo \
	libcurlu_la-curl_ctype.lo libcurlu_la-curl_des.lo \
	libcurlu_la-curl_endian.lo libcurlu_la-curl_fnmatch.lo \
	libcurlu_la-curl_get_line.lo libcurlu_la-curl_gethostname.lo \
	libcurlu_la-curl_gssapi.lo libcurlu_la-curl_memrchr.lo \
	libcurlu_la-curl_multibyte.lo libcurlu_la-curl_ntlm_core.lo \
	libcurlu_la-curl_ntlm_wb.lo libcurlu_la-curl_path.lo \
	libcurlu_la-curl_range.lo libcurlu_la-curl_rtmp.lo \
	libcurlu_la-curl_sasl.lo libcurlu_la-curl_sspi.lo \
	libcurlu_la-curl_threads.lo libcurlu_la-dict.lo \
	libcurlu_la-dotdot.lo libcurlu_la-easy.lo \

	libcurlu_la-escape.lo libcurlu_la-file.lo \
	libcurlu_la-fileinfo.lo libcurlu_la-formdata.lo \
	libcurlu_la-ftp.lo libcurlu_la-url.lo \
	libcurlu_la-ftplistparser.lo libcurlu_la-getenv.lo \
	libcurlu_la-getinfo.lo libcurlu_la-gopher.lo \
	libcurlu_la-hash.lo libcurlu_la-hmac.lo \
	libcurlu_la-hostasyn.lo libcurlu_la-hostcheck.lo \
	libcurlu_la-hostip.lo libcurlu_la-hostip4.lo \
	libcurlu_la-hostip6.lo libcurlu_la-hostsyn.lo \
	libcurlu_la-http.lo libcurlu_la-http2.lo \
	libcurlu_la-http_chunks.lo libcurlu_la-http_digest.lo \
	libcurlu_la-http_negotiate.lo libcurlu_la-http_ntlm.lo \
	libcurlu_la-http_proxy.lo libcurlu_la-idn_win32.lo \

	libcurlu_la-if2ip.lo libcurlu_la-imap.lo \
	libcurlu_la-inet_ntop.lo libcurlu_la-inet_pton.lo \
	libcurlu_la-krb5.lo libcurlu_la-ldap.lo libcurlu_la-llist.lo \
	libcurlu_la-md4.lo libcurlu_la-md5.lo libcurlu_la-memdebug.lo \
	libcurlu_la-mime.lo libcurlu_la-mprintf.lo libcurlu_la-mqtt.lo \
	libcurlu_la-multi.lo libcurlu_la-netrc.lo \
	libcurlu_la-non-ascii.lo libcurlu_la-nonblock.lo \
	libcurlu_la-openldap.lo libcurlu_la-parsedate.lo \
	libcurlu_la-pingpong.lo libcurlu_la-pop3.lo \
	libcurlu_la-progress.lo libcurlu_la-psl.lo libcurlu_la-doh.lo \
	libcurlu_la-rand.lo libcurlu_la-rename.lo libcurlu_la-rtsp.lo \
	libcurlu_la-select.lo libcurlu_la-sendf.lo \
	libcurlu_la-setopt.lo libcurlu_la-sha256.lo \
	libcurlu_la-share.lo libcurlu_la-slist.lo libcurlu_la-smb.lo \
	libcurlu_la-smtp.lo libcurlu_la-socketpair.lo \
	libcurlu_la-socks.lo libcurlu_la-socks_gssapi.lo \
	libcurlu_la-socks_sspi.lo libcurlu_la-speedcheck.lo \
	libcurlu_la-splay.lo libcurlu_la-strcase.lo \
	libcurlu_la-strdup.lo libcurlu_la-strerror.lo \
	libcurlu_la-strtok.lo libcurlu_la-strtoofft.lo \
	libcurlu_la-system_win32.lo libcurlu_la-telnet.lo \
	libcurlu_la-tftp.lo libcurlu_la-timeval.lo \
	libcurlu_la-transfer.lo libcurlu_la-urlapi.lo \

	libcurlu_la-version.lo libcurlu_la-warnless.lo \
	libcurlu_la-wildcard.lo libcurlu_la-x509asn1.lo \
	libcurlu_la-dynbuf.lo libcurlu_la-version_win32.lo \
	libcurlu_la-easyoptions.lo libcurlu_la-easygetopt.lo \
	libcurlu_la-hsts.lo
am__objects_10 = vauth/libcurlu_la-cleartext.lo \
	vauth/libcurlu_la-cram.lo vauth/libcurlu_la-digest.lo \
	vauth/libcurlu_la-digest_sspi.lo \
	vauth/libcurlu_la-krb5_gssapi.lo \
	vauth/libcurlu_la-krb5_sspi.lo vauth/libcurlu_la-ntlm.lo \
	vauth/libcurlu_la-ntlm_sspi.lo vauth/libcurlu_la-oauth2.lo \
	vauth/libcurlu_la-spnego_gssapi.lo \







|
>
|
|
|
|
|
|
|
|
|
|
|
|
>


|
|
<
|



|


|
>
|
|
|
|
|




|
|











|
>
|
|
<
<
<







264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289

290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324



325
326
327
328
329
330
331
am__v_lt_1 = 
libcurl_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
	$(LIBTOOLFLAGS) --mode=link $(CCLD) $(libcurl_la_CFLAGS) \
	$(CFLAGS) $(libcurl_la_LDFLAGS) $(LDFLAGS) -o $@
libcurlu_la_LIBADD =
am__objects_9 = libcurlu_la-altsvc.lo libcurlu_la-amigaos.lo \
	libcurlu_la-asyn-ares.lo libcurlu_la-asyn-thread.lo \
	libcurlu_la-base64.lo libcurlu_la-c-hyper.lo \
	libcurlu_la-conncache.lo libcurlu_la-connect.lo \
	libcurlu_la-content_encoding.lo libcurlu_la-cookie.lo \
	libcurlu_la-curl_addrinfo.lo libcurlu_la-curl_ctype.lo \
	libcurlu_la-curl_des.lo libcurlu_la-curl_endian.lo \
	libcurlu_la-curl_fnmatch.lo libcurlu_la-curl_get_line.lo \
	libcurlu_la-curl_gethostname.lo libcurlu_la-curl_gssapi.lo \
	libcurlu_la-curl_memrchr.lo libcurlu_la-curl_multibyte.lo \
	libcurlu_la-curl_ntlm_core.lo libcurlu_la-curl_ntlm_wb.lo \
	libcurlu_la-curl_path.lo libcurlu_la-curl_range.lo \
	libcurlu_la-curl_rtmp.lo libcurlu_la-curl_sasl.lo \
	libcurlu_la-curl_sspi.lo libcurlu_la-curl_threads.lo \
	libcurlu_la-dict.lo libcurlu_la-doh.lo libcurlu_la-dotdot.lo \
	libcurlu_la-dynbuf.lo libcurlu_la-easy.lo \
	libcurlu_la-easygetopt.lo libcurlu_la-easyoptions.lo \
	libcurlu_la-escape.lo libcurlu_la-file.lo \
	libcurlu_la-fileinfo.lo libcurlu_la-formdata.lo \
	libcurlu_la-ftp.lo libcurlu_la-ftplistparser.lo \
	libcurlu_la-getenv.lo libcurlu_la-getinfo.lo \

	libcurlu_la-gopher.lo libcurlu_la-hash.lo libcurlu_la-hmac.lo \
	libcurlu_la-hostasyn.lo libcurlu_la-hostcheck.lo \
	libcurlu_la-hostip.lo libcurlu_la-hostip4.lo \
	libcurlu_la-hostip6.lo libcurlu_la-hostsyn.lo \
	libcurlu_la-hsts.lo libcurlu_la-http.lo libcurlu_la-http2.lo \
	libcurlu_la-http_chunks.lo libcurlu_la-http_digest.lo \
	libcurlu_la-http_negotiate.lo libcurlu_la-http_ntlm.lo \
	libcurlu_la-http_proxy.lo libcurlu_la-http_aws_sigv4.lo \
	libcurlu_la-idn_win32.lo libcurlu_la-if2ip.lo \
	libcurlu_la-imap.lo libcurlu_la-inet_ntop.lo \
	libcurlu_la-inet_pton.lo libcurlu_la-krb5.lo \
	libcurlu_la-ldap.lo libcurlu_la-llist.lo libcurlu_la-md4.lo \
	libcurlu_la-md5.lo libcurlu_la-memdebug.lo libcurlu_la-mime.lo \
	libcurlu_la-mprintf.lo libcurlu_la-mqtt.lo \
	libcurlu_la-multi.lo libcurlu_la-netrc.lo \
	libcurlu_la-non-ascii.lo libcurlu_la-nonblock.lo \
	libcurlu_la-openldap.lo libcurlu_la-parsedate.lo \
	libcurlu_la-pingpong.lo libcurlu_la-pop3.lo \
	libcurlu_la-progress.lo libcurlu_la-psl.lo libcurlu_la-rand.lo \
	libcurlu_la-rename.lo libcurlu_la-rtsp.lo \
	libcurlu_la-select.lo libcurlu_la-sendf.lo \
	libcurlu_la-setopt.lo libcurlu_la-sha256.lo \
	libcurlu_la-share.lo libcurlu_la-slist.lo libcurlu_la-smb.lo \
	libcurlu_la-smtp.lo libcurlu_la-socketpair.lo \
	libcurlu_la-socks.lo libcurlu_la-socks_gssapi.lo \
	libcurlu_la-socks_sspi.lo libcurlu_la-speedcheck.lo \
	libcurlu_la-splay.lo libcurlu_la-strcase.lo \
	libcurlu_la-strdup.lo libcurlu_la-strerror.lo \
	libcurlu_la-strtok.lo libcurlu_la-strtoofft.lo \
	libcurlu_la-system_win32.lo libcurlu_la-telnet.lo \
	libcurlu_la-tftp.lo libcurlu_la-timeval.lo \
	libcurlu_la-transfer.lo libcurlu_la-url.lo \
	libcurlu_la-urlapi.lo libcurlu_la-version.lo \
	libcurlu_la-version_win32.lo libcurlu_la-warnless.lo \
	libcurlu_la-wildcard.lo libcurlu_la-x509asn1.lo



am__objects_10 = vauth/libcurlu_la-cleartext.lo \
	vauth/libcurlu_la-cram.lo vauth/libcurlu_la-digest.lo \
	vauth/libcurlu_la-digest_sspi.lo \
	vauth/libcurlu_la-krb5_gssapi.lo \
	vauth/libcurlu_la-krb5_sspi.lo vauth/libcurlu_la-ntlm.lo \
	vauth/libcurlu_la-ntlm_sspi.lo vauth/libcurlu_la-oauth2.lo \
	vauth/libcurlu_la-spnego_gssapi.lo \
367
368
369
370
371
372
373

374
375
376
377
378
379
380
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__maybe_remake_depfiles = depfiles
am__depfiles_remade = ./$(DEPDIR)/libcurl_la-altsvc.Plo \
	./$(DEPDIR)/libcurl_la-amigaos.Plo \
	./$(DEPDIR)/libcurl_la-asyn-ares.Plo \
	./$(DEPDIR)/libcurl_la-asyn-thread.Plo \
	./$(DEPDIR)/libcurl_la-base64.Plo \

	./$(DEPDIR)/libcurl_la-conncache.Plo \
	./$(DEPDIR)/libcurl_la-connect.Plo \
	./$(DEPDIR)/libcurl_la-content_encoding.Plo \
	./$(DEPDIR)/libcurl_la-cookie.Plo \
	./$(DEPDIR)/libcurl_la-curl_addrinfo.Plo \
	./$(DEPDIR)/libcurl_la-curl_ctype.Plo \
	./$(DEPDIR)/libcurl_la-curl_des.Plo \







>







367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__maybe_remake_depfiles = depfiles
am__depfiles_remade = ./$(DEPDIR)/libcurl_la-altsvc.Plo \
	./$(DEPDIR)/libcurl_la-amigaos.Plo \
	./$(DEPDIR)/libcurl_la-asyn-ares.Plo \
	./$(DEPDIR)/libcurl_la-asyn-thread.Plo \
	./$(DEPDIR)/libcurl_la-base64.Plo \
	./$(DEPDIR)/libcurl_la-c-hyper.Plo \
	./$(DEPDIR)/libcurl_la-conncache.Plo \
	./$(DEPDIR)/libcurl_la-connect.Plo \
	./$(DEPDIR)/libcurl_la-content_encoding.Plo \
	./$(DEPDIR)/libcurl_la-cookie.Plo \
	./$(DEPDIR)/libcurl_la-curl_addrinfo.Plo \
	./$(DEPDIR)/libcurl_la-curl_ctype.Plo \
	./$(DEPDIR)/libcurl_la-curl_des.Plo \
415
416
417
418
419
420
421

422
423
424
425
426
427
428
	./$(DEPDIR)/libcurl_la-hostip.Plo \
	./$(DEPDIR)/libcurl_la-hostip4.Plo \
	./$(DEPDIR)/libcurl_la-hostip6.Plo \
	./$(DEPDIR)/libcurl_la-hostsyn.Plo \
	./$(DEPDIR)/libcurl_la-hsts.Plo \
	./$(DEPDIR)/libcurl_la-http.Plo \
	./$(DEPDIR)/libcurl_la-http2.Plo \

	./$(DEPDIR)/libcurl_la-http_chunks.Plo \
	./$(DEPDIR)/libcurl_la-http_digest.Plo \
	./$(DEPDIR)/libcurl_la-http_negotiate.Plo \
	./$(DEPDIR)/libcurl_la-http_ntlm.Plo \
	./$(DEPDIR)/libcurl_la-http_proxy.Plo \
	./$(DEPDIR)/libcurl_la-idn_win32.Plo \
	./$(DEPDIR)/libcurl_la-if2ip.Plo \







>







416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
	./$(DEPDIR)/libcurl_la-hostip.Plo \
	./$(DEPDIR)/libcurl_la-hostip4.Plo \
	./$(DEPDIR)/libcurl_la-hostip6.Plo \
	./$(DEPDIR)/libcurl_la-hostsyn.Plo \
	./$(DEPDIR)/libcurl_la-hsts.Plo \
	./$(DEPDIR)/libcurl_la-http.Plo \
	./$(DEPDIR)/libcurl_la-http2.Plo \
	./$(DEPDIR)/libcurl_la-http_aws_sigv4.Plo \
	./$(DEPDIR)/libcurl_la-http_chunks.Plo \
	./$(DEPDIR)/libcurl_la-http_digest.Plo \
	./$(DEPDIR)/libcurl_la-http_negotiate.Plo \
	./$(DEPDIR)/libcurl_la-http_ntlm.Plo \
	./$(DEPDIR)/libcurl_la-http_proxy.Plo \
	./$(DEPDIR)/libcurl_la-idn_win32.Plo \
	./$(DEPDIR)/libcurl_la-if2ip.Plo \
480
481
482
483
484
485
486

487
488
489
490
491
492
493
	./$(DEPDIR)/libcurl_la-wildcard.Plo \
	./$(DEPDIR)/libcurl_la-x509asn1.Plo \
	./$(DEPDIR)/libcurlu_la-altsvc.Plo \
	./$(DEPDIR)/libcurlu_la-amigaos.Plo \
	./$(DEPDIR)/libcurlu_la-asyn-ares.Plo \
	./$(DEPDIR)/libcurlu_la-asyn-thread.Plo \
	./$(DEPDIR)/libcurlu_la-base64.Plo \

	./$(DEPDIR)/libcurlu_la-conncache.Plo \
	./$(DEPDIR)/libcurlu_la-connect.Plo \
	./$(DEPDIR)/libcurlu_la-content_encoding.Plo \
	./$(DEPDIR)/libcurlu_la-cookie.Plo \
	./$(DEPDIR)/libcurlu_la-curl_addrinfo.Plo \
	./$(DEPDIR)/libcurlu_la-curl_ctype.Plo \
	./$(DEPDIR)/libcurlu_la-curl_des.Plo \







>







482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
	./$(DEPDIR)/libcurl_la-wildcard.Plo \
	./$(DEPDIR)/libcurl_la-x509asn1.Plo \
	./$(DEPDIR)/libcurlu_la-altsvc.Plo \
	./$(DEPDIR)/libcurlu_la-amigaos.Plo \
	./$(DEPDIR)/libcurlu_la-asyn-ares.Plo \
	./$(DEPDIR)/libcurlu_la-asyn-thread.Plo \
	./$(DEPDIR)/libcurlu_la-base64.Plo \
	./$(DEPDIR)/libcurlu_la-c-hyper.Plo \
	./$(DEPDIR)/libcurlu_la-conncache.Plo \
	./$(DEPDIR)/libcurlu_la-connect.Plo \
	./$(DEPDIR)/libcurlu_la-content_encoding.Plo \
	./$(DEPDIR)/libcurlu_la-cookie.Plo \
	./$(DEPDIR)/libcurlu_la-curl_addrinfo.Plo \
	./$(DEPDIR)/libcurlu_la-curl_ctype.Plo \
	./$(DEPDIR)/libcurlu_la-curl_des.Plo \
529
530
531
532
533
534
535

536
537
538
539
540
541
542
	./$(DEPDIR)/libcurlu_la-hostip.Plo \
	./$(DEPDIR)/libcurlu_la-hostip4.Plo \
	./$(DEPDIR)/libcurlu_la-hostip6.Plo \
	./$(DEPDIR)/libcurlu_la-hostsyn.Plo \
	./$(DEPDIR)/libcurlu_la-hsts.Plo \
	./$(DEPDIR)/libcurlu_la-http.Plo \
	./$(DEPDIR)/libcurlu_la-http2.Plo \

	./$(DEPDIR)/libcurlu_la-http_chunks.Plo \
	./$(DEPDIR)/libcurlu_la-http_digest.Plo \
	./$(DEPDIR)/libcurlu_la-http_negotiate.Plo \
	./$(DEPDIR)/libcurlu_la-http_ntlm.Plo \
	./$(DEPDIR)/libcurlu_la-http_proxy.Plo \
	./$(DEPDIR)/libcurlu_la-idn_win32.Plo \
	./$(DEPDIR)/libcurlu_la-if2ip.Plo \







>







532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
	./$(DEPDIR)/libcurlu_la-hostip.Plo \
	./$(DEPDIR)/libcurlu_la-hostip4.Plo \
	./$(DEPDIR)/libcurlu_la-hostip6.Plo \
	./$(DEPDIR)/libcurlu_la-hostsyn.Plo \
	./$(DEPDIR)/libcurlu_la-hsts.Plo \
	./$(DEPDIR)/libcurlu_la-http.Plo \
	./$(DEPDIR)/libcurlu_la-http2.Plo \
	./$(DEPDIR)/libcurlu_la-http_aws_sigv4.Plo \
	./$(DEPDIR)/libcurlu_la-http_chunks.Plo \
	./$(DEPDIR)/libcurlu_la-http_digest.Plo \
	./$(DEPDIR)/libcurlu_la-http_negotiate.Plo \
	./$(DEPDIR)/libcurlu_la-http_ntlm.Plo \
	./$(DEPDIR)/libcurlu_la-http_proxy.Plo \
	./$(DEPDIR)/libcurlu_la-idn_win32.Plo \
	./$(DEPDIR)/libcurlu_la-if2ip.Plo \
841
842
843
844
845
846
847

848
849
850
851
852
853
854
STRIP = @STRIP@
SUPPORT_FEATURES = @SUPPORT_FEATURES@
SUPPORT_PROTOCOLS = @SUPPORT_PROTOCOLS@
USE_ARES = @USE_ARES@
USE_BEARSSL = @USE_BEARSSL@
USE_GNUTLS = @USE_GNUTLS@
USE_GNUTLS_NETTLE = @USE_GNUTLS_NETTLE@

USE_LIBRTMP = @USE_LIBRTMP@
USE_LIBSSH = @USE_LIBSSH@
USE_LIBSSH2 = @USE_LIBSSH2@
USE_MBEDTLS = @USE_MBEDTLS@
USE_MESALINK = @USE_MESALINK@
USE_NGHTTP2 = @USE_NGHTTP2@
USE_NGHTTP3 = @USE_NGHTTP3@







>







845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
STRIP = @STRIP@
SUPPORT_FEATURES = @SUPPORT_FEATURES@
SUPPORT_PROTOCOLS = @SUPPORT_PROTOCOLS@
USE_ARES = @USE_ARES@
USE_BEARSSL = @USE_BEARSSL@
USE_GNUTLS = @USE_GNUTLS@
USE_GNUTLS_NETTLE = @USE_GNUTLS_NETTLE@
USE_HYPER = @USE_HYPER@
USE_LIBRTMP = @USE_LIBRTMP@
USE_LIBSSH = @USE_LIBSSH@
USE_LIBSSH2 = @USE_LIBSSH2@
USE_MBEDTLS = @USE_MBEDTLS@
USE_MESALINK = @USE_MESALINK@
USE_NGHTTP2 = @USE_NGHTTP2@
USE_NGHTTP3 = @USE_NGHTTP3@
993
994
995
996
997
998
999
1000



1001



1002



1003
1004
1005




1006





1007




1008


1009
1010
1011





1012


1013










































1014
1015
1016
1017
1018





1019

1020
1021
1022
1023

1024




1025






1026









1027
1028















1029






1030












1031

1032

1033





1034






1035





















































1036
1037
1038
1039
1040
1041
1042
1043









1044



















1045
1046
1047
1048
1049
1050






1051



1052








1053









1054
1055
1056
1057
1058
1059
1060
1061
1062
libcurl_la_CFLAGS_EXTRA = $(am__append_9)
libcurl_la_CPPFLAGS = $(AM_CPPFLAGS) $(libcurl_la_CPPFLAGS_EXTRA)
libcurl_la_LDFLAGS = $(AM_LDFLAGS) $(libcurl_la_LDFLAGS_EXTRA) $(LDFLAGS) $(LIBCURL_LIBS)
libcurl_la_CFLAGS = $(AM_CFLAGS) $(libcurl_la_CFLAGS_EXTRA)
libcurlu_la_CPPFLAGS = $(AM_CPPFLAGS) -DCURL_STATICLIB -DUNITTESTS
libcurlu_la_LDFLAGS = $(AM_LDFLAGS) -static $(LIBCURL_LIBS)
libcurlu_la_CFLAGS = $(AM_CFLAGS)
LIB_VAUTH_CFILES = vauth/cleartext.c vauth/cram.c vauth/digest.c             \



  vauth/digest_sspi.c vauth/krb5_gssapi.c vauth/krb5_sspi.c vauth/ntlm.c     \



  vauth/ntlm_sspi.c vauth/oauth2.c vauth/spnego_gssapi.c vauth/spnego_sspi.c \



  vauth/vauth.c

LIB_VAUTH_HFILES = vauth/digest.h vauth/ntlm.h vauth/vauth.h




LIB_VTLS_CFILES = vtls/bearssl.c vtls/gskit.c vtls/gtls.c vtls/keylog.c  \





  vtls/mbedtls.c vtls/mbedtls_threadlock.c vtls/mesalink.c vtls/nss.c    \




  vtls/openssl.c vtls/schannel.c vtls/schannel_verify.c vtls/sectransp.c \


  vtls/vtls.c vtls/wolfssl.c

LIB_VTLS_HFILES = vtls/bearssl.h vtls/gskit.h vtls/gtls.h vtls/keylog.h      \





  vtls/mbedtls.h vtls/mbedtls_threadlock.h vtls/mesalink.h vtls/nssg.h       \


  vtls/openssl.h vtls/schannel.h vtls/sectransp.h vtls/vtls.h vtls/wolfssl.h











































LIB_VQUIC_CFILES = vquic/ngtcp2.c vquic/quiche.c vquic/vquic.c
LIB_VQUIC_HFILES = vquic/ngtcp2.h vquic/quiche.h vquic/vquic.h
LIB_VSSH_CFILES = vssh/libssh.c vssh/libssh2.c vssh/wolfssh.c
LIB_VSSH_HFILES = vssh/ssh.h





LIB_CFILES = altsvc.c amigaos.c asyn-ares.c asyn-thread.c base64.c            \

  conncache.c connect.c content_encoding.c cookie.c curl_addrinfo.c           \
  curl_ctype.c curl_des.c curl_endian.c curl_fnmatch.c curl_get_line.c        \
  curl_gethostname.c curl_gssapi.c curl_memrchr.c curl_multibyte.c            \
  curl_ntlm_core.c curl_ntlm_wb.c curl_path.c curl_range.c curl_rtmp.c        \

  curl_sasl.c curl_sspi.c curl_threads.c dict.c dotdot.c easy.c escape.c      \




  file.c fileinfo.c formdata.c ftp.c url.c ftplistparser.c getenv.c getinfo.c \






  gopher.c hash.c hmac.c hostasyn.c hostcheck.c hostip.c hostip4.c hostip6.c  \









  hostsyn.c http.c http2.c http_chunks.c http_digest.c http_negotiate.c       \
  http_ntlm.c http_proxy.c idn_win32.c if2ip.c imap.c inet_ntop.c inet_pton.c \















  krb5.c ldap.c llist.c md4.c md5.c memdebug.c mime.c mprintf.c mqtt.c        \






  multi.c netrc.c non-ascii.c nonblock.c openldap.c parsedate.c pingpong.c    \












  pop3.c progress.c psl.c doh.c rand.c rename.c rtsp.c select.c               \

  sendf.c setopt.c sha256.c share.c slist.c smb.c smtp.c socketpair.c socks.c \

  socks_gssapi.c socks_sspi.c speedcheck.c splay.c strcase.c strdup.c         \





  strerror.c strtok.c strtoofft.c system_win32.c telnet.c tftp.c timeval.c    \






  transfer.c urlapi.c version.c warnless.c wildcard.c x509asn1.c dynbuf.c     \





















































  version_win32.c easyoptions.c easygetopt.c hsts.c

LIB_HFILES = altsvc.h amigaos.h arpa_telnet.h asyn.h conncache.h connect.h    \
  content_encoding.h cookie.h curl_addrinfo.h curl_base64.h curl_ctype.h      \
  curl_des.h curl_endian.h curl_fnmatch.h curl_get_line.h curl_gethostname.h  \
  curl_gssapi.h curl_hmac.h curl_ldap.h curl_md4.h curl_md5.h curl_memory.h   \
  curl_memrchr.h curl_multibyte.h curl_ntlm_core.h curl_ntlm_wb.h curl_path.h \
  curl_printf.h curl_range.h curl_rtmp.h curl_sasl.h curl_krb5.h curl_setup.h \









  curl_setup_once.h curl_sha256.h curl_sspi.h curl_threads.h curlx.h dict.h   \



















  dotdot.h easyif.h escape.h file.h fileinfo.h formdata.h ftp.h url.h         \
  ftplistparser.h getinfo.h gopher.h hash.h hostcheck.h hostip.h http.h       \
  http2.h http_chunks.h http_digest.h http_negotiate.h http_ntlm.h            \
  http_proxy.h if2ip.h imap.h inet_ntop.h inet_pton.h llist.h memdebug.h      \
  mime.h mqtt.h multihandle.h multiif.h netrc.h non-ascii.h nonblock.h        \
  parsedate.h pingpong.h pop3.h progress.h psl.h doh.h quic.h rand.h rename.h \






  rtsp.h select.h sendf.h setopt.h setup-vms.h share.h sigpipe.h slist.h      \



  smb.h smtp.h sockaddr.h socketpair.h socks.h speedcheck.h splay.h strcase.h \








  strdup.h strerror.h strtok.h strtoofft.h system_win32.h telnet.h tftp.h     \









  timeval.h transfer.h urlapi-int.h urldata.h warnless.h wildcard.h           \
  x509asn1.h dynbuf.h version_win32.h easyoptions.h hsts.h

LIB_RCFILES = libcurl.rc
CSOURCES = $(LIB_CFILES) $(LIB_VAUTH_CFILES) $(LIB_VTLS_CFILES) \
  $(LIB_VQUIC_CFILES) $(LIB_VSSH_CFILES)

HHEADERS = $(LIB_HFILES) $(LIB_VAUTH_HFILES) $(LIB_VTLS_HFILES) \
  $(LIB_VQUIC_HFILES) $(LIB_VSSH_HFILES)







|
>
>
>
|
>
>
>
|
>
>
>


|
>
>
>
>
|
>
>
>
>
>
|
>
>
>
>
|
>
>
|

|
>
>
>
>
>
|
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
|
|
|
|
>
>
>
>
>
|
>
|
|
|
|
>
|
>
>
>
>
|
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
|
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
|
>
|
>
|
>
>
>
>
>
|
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
|
|
|
|
|
|
|
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
|
|
|
|
|
>
>
>
>
>
>
|
>
>
>
|
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
|
|







998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
libcurl_la_CFLAGS_EXTRA = $(am__append_9)
libcurl_la_CPPFLAGS = $(AM_CPPFLAGS) $(libcurl_la_CPPFLAGS_EXTRA)
libcurl_la_LDFLAGS = $(AM_LDFLAGS) $(libcurl_la_LDFLAGS_EXTRA) $(LDFLAGS) $(LIBCURL_LIBS)
libcurl_la_CFLAGS = $(AM_CFLAGS) $(libcurl_la_CFLAGS_EXTRA)
libcurlu_la_CPPFLAGS = $(AM_CPPFLAGS) -DCURL_STATICLIB -DUNITTESTS
libcurlu_la_LDFLAGS = $(AM_LDFLAGS) -static $(LIBCURL_LIBS)
libcurlu_la_CFLAGS = $(AM_CFLAGS)
LIB_VAUTH_CFILES = \
  vauth/cleartext.c     \
  vauth/cram.c          \
  vauth/digest.c        \
  vauth/digest_sspi.c   \
  vauth/krb5_gssapi.c   \
  vauth/krb5_sspi.c     \
  vauth/ntlm.c          \
  vauth/ntlm_sspi.c     \
  vauth/oauth2.c        \
  vauth/spnego_gssapi.c \
  vauth/spnego_sspi.c   \
  vauth/vauth.c

LIB_VAUTH_HFILES = \
  vauth/digest.h        \
  vauth/ntlm.h          \
  vauth/vauth.h

LIB_VTLS_CFILES = \
  vtls/bearssl.c            \
  vtls/gskit.c              \
  vtls/gtls.c               \
  vtls/keylog.c             \
  vtls/mbedtls.c            \
  vtls/mbedtls_threadlock.c \
  vtls/mesalink.c           \
  vtls/nss.c                \
  vtls/openssl.c            \
  vtls/schannel.c           \
  vtls/schannel_verify.c    \
  vtls/sectransp.c          \
  vtls/vtls.c               \
  vtls/wolfssl.c

LIB_VTLS_HFILES = \
  vtls/bearssl.h            \
  vtls/gskit.h              \
  vtls/gtls.h               \
  vtls/keylog.h             \
  vtls/mbedtls.h            \
  vtls/mbedtls_threadlock.h \
  vtls/mesalink.h           \
  vtls/nssg.h               \
  vtls/openssl.h            \
  vtls/schannel.h           \
  vtls/sectransp.h          \
  vtls/vtls.h               \
  vtls/wolfssl.h

LIB_VQUIC_CFILES = \
  vquic/ngtcp2.c   \
  vquic/quiche.c   \
  vquic/vquic.c

LIB_VQUIC_HFILES = \
  vquic/ngtcp2.h   \
  vquic/quiche.h   \
  vquic/vquic.h

LIB_VSSH_CFILES = \
  vssh/libssh.c    \
  vssh/libssh2.c   \
  vssh/wolfssh.c

LIB_VSSH_HFILES = \
  vssh/ssh.h

LIB_CFILES = \
  altsvc.c           \
  amigaos.c          \
  asyn-ares.c        \
  asyn-thread.c      \
  base64.c           \
  c-hyper.c          \
  conncache.c        \
  connect.c          \
  content_encoding.c \
  cookie.c           \
  curl_addrinfo.c    \
  curl_ctype.c       \
  curl_des.c         \
  curl_endian.c      \
  curl_fnmatch.c     \
  curl_get_line.c    \
  curl_gethostname.c \
  curl_gssapi.c      \
  curl_memrchr.c     \
  curl_multibyte.c   \
  curl_ntlm_core.c   \
  curl_ntlm_wb.c     \
  curl_path.c        \
  curl_range.c       \
  curl_rtmp.c        \
  curl_sasl.c        \
  curl_sspi.c        \
  curl_threads.c     \
  dict.c             \
  doh.c              \
  dotdot.c           \
  dynbuf.c           \
  easy.c             \
  easygetopt.c       \
  easyoptions.c      \
  escape.c           \
  file.c             \
  fileinfo.c         \
  formdata.c         \
  ftp.c              \
  ftplistparser.c    \
  getenv.c           \
  getinfo.c          \
  gopher.c           \
  hash.c             \
  hmac.c             \
  hostasyn.c         \
  hostcheck.c        \
  hostip.c           \
  hostip4.c          \
  hostip6.c          \
  hostsyn.c          \
  hsts.c             \
  http.c             \
  http2.c            \
  http_chunks.c      \
  http_digest.c      \
  http_negotiate.c   \
  http_ntlm.c        \
  http_proxy.c       \
  http_aws_sigv4.c   \
  idn_win32.c        \
  if2ip.c            \
  imap.c             \
  inet_ntop.c        \
  inet_pton.c        \
  krb5.c             \
  ldap.c             \
  llist.c            \
  md4.c              \
  md5.c              \
  memdebug.c         \
  mime.c             \
  mprintf.c          \
  mqtt.c             \
  multi.c            \
  netrc.c            \
  non-ascii.c        \
  nonblock.c         \
  openldap.c         \
  parsedate.c        \
  pingpong.c         \
  pop3.c             \
  progress.c         \
  psl.c              \
  rand.c             \
  rename.c           \
  rtsp.c             \
  select.c           \
  sendf.c            \
  setopt.c           \
  sha256.c           \
  share.c            \
  slist.c            \
  smb.c              \
  smtp.c             \
  socketpair.c       \
  socks.c            \
  socks_gssapi.c     \
  socks_sspi.c       \
  speedcheck.c       \
  splay.c            \
  strcase.c          \
  strdup.c           \
  strerror.c         \
  strtok.c           \
  strtoofft.c        \
  system_win32.c     \
  telnet.c           \
  tftp.c             \
  timeval.c          \
  transfer.c         \
  url.c              \
  urlapi.c           \
  version.c          \
  version_win32.c    \
  warnless.c         \
  wildcard.c         \
  x509asn1.c

LIB_HFILES = \
  altsvc.h           \
  amigaos.h          \
  arpa_telnet.h      \
  asyn.h             \
  c-hyper.h          \
  conncache.h        \
  connect.h          \
  content_encoding.h \
  cookie.h           \
  curl_addrinfo.h    \
  curl_base64.h      \
  curl_ctype.h       \
  curl_des.h         \
  curl_endian.h      \
  curl_fnmatch.h     \
  curl_get_line.h    \
  curl_gethostname.h \
  curl_gssapi.h      \
  curl_hmac.h        \
  curl_krb5.h        \
  curl_ldap.h        \
  curl_md4.h         \
  curl_md5.h         \
  curl_memory.h      \
  curl_memrchr.h     \
  curl_multibyte.h   \
  curl_ntlm_core.h   \
  curl_ntlm_wb.h     \
  curl_path.h        \
  curl_printf.h      \
  curl_range.h       \
  curl_rtmp.h        \
  curl_sasl.h        \
  curl_setup.h       \
  curl_setup_once.h  \
  curl_sha256.h      \
  curl_sspi.h        \
  curl_threads.h     \
  curlx.h            \
  dict.h             \
  doh.h              \
  dotdot.h           \
  dynbuf.h           \
  easyif.h           \
  easyoptions.h      \
  escape.h           \
  file.h             \
  fileinfo.h         \
  formdata.h         \
  ftp.h              \
  ftplistparser.h    \
  getinfo.h          \
  gopher.h           \
  hash.h             \
  hostcheck.h        \
  hostip.h           \
  hsts.h             \
  http.h             \
  http2.h            \
  http_chunks.h      \
  http_digest.h      \
  http_negotiate.h   \
  http_ntlm.h        \
  http_proxy.h       \
  http_aws_sigv4.h   \
  if2ip.h            \
  imap.h             \
  inet_ntop.h        \
  inet_pton.h        \
  llist.h            \
  memdebug.h         \
  mime.h             \
  mqtt.h             \
  multihandle.h      \
  multiif.h          \
  netrc.h            \
  non-ascii.h        \
  nonblock.h         \
  parsedate.h        \
  pingpong.h         \
  pop3.h             \
  progress.h         \
  psl.h              \
  quic.h             \
  rand.h             \
  rename.h           \
  rtsp.h             \
  select.h           \
  sendf.h            \
  setopt.h           \
  setup-vms.h        \
  share.h            \
  sigpipe.h          \
  slist.h            \
  smb.h              \
  smtp.h             \
  sockaddr.h         \
  socketpair.h       \
  socks.h            \
  speedcheck.h       \
  splay.h            \
  strcase.h          \
  strdup.h           \
  strerror.h         \
  strtok.h           \
  strtoofft.h        \
  system_win32.h     \
  telnet.h           \
  tftp.h             \
  timeval.h          \
  transfer.h         \
  url.h              \
  urlapi-int.h       \
  urldata.h          \
  version_win32.h    \
  warnless.h         \
  wildcard.h         \
  x509asn1.h

LIB_RCFILES = libcurl.rc
CSOURCES = $(LIB_CFILES) $(LIB_VAUTH_CFILES) $(LIB_VTLS_CFILES) \
  $(LIB_VQUIC_CFILES) $(LIB_VSSH_CFILES)

HHEADERS = $(LIB_HFILES) $(LIB_VAUTH_HFILES) $(LIB_VTLS_HFILES) \
  $(LIB_VQUIC_HFILES) $(LIB_VSSH_HFILES)
1345
1346
1347
1348
1349
1350
1351

1352
1353
1354
1355
1356
1357
1358
	-rm -f *.tab.c

@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-altsvc.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-amigaos.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-asyn-ares.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-asyn-thread.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-base64.Plo@am__quote@ # am--include-marker

@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-conncache.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-connect.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-content_encoding.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-cookie.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-curl_addrinfo.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-curl_ctype.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-curl_des.Plo@am__quote@ # am--include-marker







>







1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
	-rm -f *.tab.c

@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-altsvc.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-amigaos.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-asyn-ares.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-asyn-thread.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-base64.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-c-hyper.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-conncache.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-connect.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-content_encoding.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-cookie.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-curl_addrinfo.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-curl_ctype.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-curl_des.Plo@am__quote@ # am--include-marker
1394
1395
1396
1397
1398
1399
1400

1401
1402
1403
1404
1405
1406
1407
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-hostip.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-hostip4.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-hostip6.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-hostsyn.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-hsts.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-http.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-http2.Plo@am__quote@ # am--include-marker

@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-http_chunks.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-http_digest.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-http_negotiate.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-http_ntlm.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-http_proxy.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-idn_win32.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-if2ip.Plo@am__quote@ # am--include-marker







>







1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-hostip.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-hostip4.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-hostip6.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-hostsyn.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-hsts.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-http.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-http2.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-http_aws_sigv4.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-http_chunks.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-http_digest.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-http_negotiate.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-http_ntlm.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-http_proxy.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-idn_win32.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-if2ip.Plo@am__quote@ # am--include-marker
1462
1463
1464
1465
1466
1467
1468

1469
1470
1471
1472
1473
1474
1475
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-wildcard.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-x509asn1.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-altsvc.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-amigaos.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-asyn-ares.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-asyn-thread.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-base64.Plo@am__quote@ # am--include-marker

@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-conncache.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-connect.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-content_encoding.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-cookie.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-curl_addrinfo.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-curl_ctype.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-curl_des.Plo@am__quote@ # am--include-marker







>







1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-wildcard.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-x509asn1.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-altsvc.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-amigaos.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-asyn-ares.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-asyn-thread.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-base64.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-c-hyper.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-conncache.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-connect.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-content_encoding.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-cookie.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-curl_addrinfo.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-curl_ctype.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-curl_des.Plo@am__quote@ # am--include-marker
1511
1512
1513
1514
1515
1516
1517

1518
1519
1520
1521
1522
1523
1524
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-hostip.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-hostip4.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-hostip6.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-hostsyn.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-hsts.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-http.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-http2.Plo@am__quote@ # am--include-marker

@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-http_chunks.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-http_digest.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-http_negotiate.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-http_ntlm.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-http_proxy.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-idn_win32.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-if2ip.Plo@am__quote@ # am--include-marker







>







1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-hostip.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-hostip4.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-hostip6.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-hostsyn.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-hsts.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-http.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-http2.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-http_aws_sigv4.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-http_chunks.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-http_digest.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-http_negotiate.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-http_ntlm.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-http_proxy.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-idn_win32.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-if2ip.Plo@am__quote@ # am--include-marker
1704
1705
1706
1707
1708
1709
1710







1711
1712
1713
1714
1715
1716
1717
libcurl_la-base64.lo: base64.c
@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-base64.lo -MD -MP -MF $(DEPDIR)/libcurl_la-base64.Tpo -c -o libcurl_la-base64.lo `test -f 'base64.c' || echo '$(srcdir)/'`base64.c
@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-base64.Tpo $(DEPDIR)/libcurl_la-base64.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='base64.c' object='libcurl_la-base64.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-base64.lo `test -f 'base64.c' || echo '$(srcdir)/'`base64.c








libcurl_la-conncache.lo: conncache.c
@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-conncache.lo -MD -MP -MF $(DEPDIR)/libcurl_la-conncache.Tpo -c -o libcurl_la-conncache.lo `test -f 'conncache.c' || echo '$(srcdir)/'`conncache.c
@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-conncache.Tpo $(DEPDIR)/libcurl_la-conncache.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='conncache.c' object='libcurl_la-conncache.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-conncache.lo `test -f 'conncache.c' || echo '$(srcdir)/'`conncache.c








>
>
>
>
>
>
>







1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
libcurl_la-base64.lo: base64.c
@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-base64.lo -MD -MP -MF $(DEPDIR)/libcurl_la-base64.Tpo -c -o libcurl_la-base64.lo `test -f 'base64.c' || echo '$(srcdir)/'`base64.c
@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-base64.Tpo $(DEPDIR)/libcurl_la-base64.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='base64.c' object='libcurl_la-base64.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-base64.lo `test -f 'base64.c' || echo '$(srcdir)/'`base64.c

libcurl_la-c-hyper.lo: c-hyper.c
@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-c-hyper.lo -MD -MP -MF $(DEPDIR)/libcurl_la-c-hyper.Tpo -c -o libcurl_la-c-hyper.lo `test -f 'c-hyper.c' || echo '$(srcdir)/'`c-hyper.c
@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-c-hyper.Tpo $(DEPDIR)/libcurl_la-c-hyper.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='c-hyper.c' object='libcurl_la-c-hyper.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-c-hyper.lo `test -f 'c-hyper.c' || echo '$(srcdir)/'`c-hyper.c

libcurl_la-conncache.lo: conncache.c
@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-conncache.lo -MD -MP -MF $(DEPDIR)/libcurl_la-conncache.Tpo -c -o libcurl_la-conncache.lo `test -f 'conncache.c' || echo '$(srcdir)/'`conncache.c
@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-conncache.Tpo $(DEPDIR)/libcurl_la-conncache.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='conncache.c' object='libcurl_la-conncache.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-conncache.lo `test -f 'conncache.c' || echo '$(srcdir)/'`conncache.c

1865
1866
1867
1868
1869
1870
1871







1872
1873
1874
1875
1876
1877
1878







1879
1880
1881
1882
1883
1884
1885














1886
1887
1888
1889
1890
1891
1892
libcurl_la-dict.lo: dict.c
@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-dict.lo -MD -MP -MF $(DEPDIR)/libcurl_la-dict.Tpo -c -o libcurl_la-dict.lo `test -f 'dict.c' || echo '$(srcdir)/'`dict.c
@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-dict.Tpo $(DEPDIR)/libcurl_la-dict.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='dict.c' object='libcurl_la-dict.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-dict.lo `test -f 'dict.c' || echo '$(srcdir)/'`dict.c








libcurl_la-dotdot.lo: dotdot.c
@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-dotdot.lo -MD -MP -MF $(DEPDIR)/libcurl_la-dotdot.Tpo -c -o libcurl_la-dotdot.lo `test -f 'dotdot.c' || echo '$(srcdir)/'`dotdot.c
@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-dotdot.Tpo $(DEPDIR)/libcurl_la-dotdot.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='dotdot.c' object='libcurl_la-dotdot.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-dotdot.lo `test -f 'dotdot.c' || echo '$(srcdir)/'`dotdot.c








libcurl_la-easy.lo: easy.c
@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-easy.lo -MD -MP -MF $(DEPDIR)/libcurl_la-easy.Tpo -c -o libcurl_la-easy.lo `test -f 'easy.c' || echo '$(srcdir)/'`easy.c
@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-easy.Tpo $(DEPDIR)/libcurl_la-easy.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='easy.c' object='libcurl_la-easy.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-easy.lo `test -f 'easy.c' || echo '$(srcdir)/'`easy.c















libcurl_la-escape.lo: escape.c
@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-escape.lo -MD -MP -MF $(DEPDIR)/libcurl_la-escape.Tpo -c -o libcurl_la-escape.lo `test -f 'escape.c' || echo '$(srcdir)/'`escape.c
@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-escape.Tpo $(DEPDIR)/libcurl_la-escape.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='escape.c' object='libcurl_la-escape.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-escape.lo `test -f 'escape.c' || echo '$(srcdir)/'`escape.c








>
>
>
>
>
>
>







>
>
>
>
>
>
>







>
>
>
>
>
>
>
>
>
>
>
>
>
>







2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
libcurl_la-dict.lo: dict.c
@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-dict.lo -MD -MP -MF $(DEPDIR)/libcurl_la-dict.Tpo -c -o libcurl_la-dict.lo `test -f 'dict.c' || echo '$(srcdir)/'`dict.c
@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-dict.Tpo $(DEPDIR)/libcurl_la-dict.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='dict.c' object='libcurl_la-dict.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-dict.lo `test -f 'dict.c' || echo '$(srcdir)/'`dict.c

libcurl_la-doh.lo: doh.c
@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-doh.lo -MD -MP -MF $(DEPDIR)/libcurl_la-doh.Tpo -c -o libcurl_la-doh.lo `test -f 'doh.c' || echo '$(srcdir)/'`doh.c
@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-doh.Tpo $(DEPDIR)/libcurl_la-doh.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='doh.c' object='libcurl_la-doh.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-doh.lo `test -f 'doh.c' || echo '$(srcdir)/'`doh.c

libcurl_la-dotdot.lo: dotdot.c
@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-dotdot.lo -MD -MP -MF $(DEPDIR)/libcurl_la-dotdot.Tpo -c -o libcurl_la-dotdot.lo `test -f 'dotdot.c' || echo '$(srcdir)/'`dotdot.c
@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-dotdot.Tpo $(DEPDIR)/libcurl_la-dotdot.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='dotdot.c' object='libcurl_la-dotdot.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-dotdot.lo `test -f 'dotdot.c' || echo '$(srcdir)/'`dotdot.c

libcurl_la-dynbuf.lo: dynbuf.c
@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-dynbuf.lo -MD -MP -MF $(DEPDIR)/libcurl_la-dynbuf.Tpo -c -o libcurl_la-dynbuf.lo `test -f 'dynbuf.c' || echo '$(srcdir)/'`dynbuf.c
@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-dynbuf.Tpo $(DEPDIR)/libcurl_la-dynbuf.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='dynbuf.c' object='libcurl_la-dynbuf.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-dynbuf.lo `test -f 'dynbuf.c' || echo '$(srcdir)/'`dynbuf.c

libcurl_la-easy.lo: easy.c
@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-easy.lo -MD -MP -MF $(DEPDIR)/libcurl_la-easy.Tpo -c -o libcurl_la-easy.lo `test -f 'easy.c' || echo '$(srcdir)/'`easy.c
@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-easy.Tpo $(DEPDIR)/libcurl_la-easy.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='easy.c' object='libcurl_la-easy.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-easy.lo `test -f 'easy.c' || echo '$(srcdir)/'`easy.c

libcurl_la-easygetopt.lo: easygetopt.c
@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-easygetopt.lo -MD -MP -MF $(DEPDIR)/libcurl_la-easygetopt.Tpo -c -o libcurl_la-easygetopt.lo `test -f 'easygetopt.c' || echo '$(srcdir)/'`easygetopt.c
@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-easygetopt.Tpo $(DEPDIR)/libcurl_la-easygetopt.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='easygetopt.c' object='libcurl_la-easygetopt.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-easygetopt.lo `test -f 'easygetopt.c' || echo '$(srcdir)/'`easygetopt.c

libcurl_la-easyoptions.lo: easyoptions.c
@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-easyoptions.lo -MD -MP -MF $(DEPDIR)/libcurl_la-easyoptions.Tpo -c -o libcurl_la-easyoptions.lo `test -f 'easyoptions.c' || echo '$(srcdir)/'`easyoptions.c
@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-easyoptions.Tpo $(DEPDIR)/libcurl_la-easyoptions.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='easyoptions.c' object='libcurl_la-easyoptions.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-easyoptions.lo `test -f 'easyoptions.c' || echo '$(srcdir)/'`easyoptions.c

libcurl_la-escape.lo: escape.c
@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-escape.lo -MD -MP -MF $(DEPDIR)/libcurl_la-escape.Tpo -c -o libcurl_la-escape.lo `test -f 'escape.c' || echo '$(srcdir)/'`escape.c
@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-escape.Tpo $(DEPDIR)/libcurl_la-escape.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='escape.c' object='libcurl_la-escape.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-escape.lo `test -f 'escape.c' || echo '$(srcdir)/'`escape.c

1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
libcurl_la-ftp.lo: ftp.c
@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-ftp.lo -MD -MP -MF $(DEPDIR)/libcurl_la-ftp.Tpo -c -o libcurl_la-ftp.lo `test -f 'ftp.c' || echo '$(srcdir)/'`ftp.c
@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-ftp.Tpo $(DEPDIR)/libcurl_la-ftp.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='ftp.c' object='libcurl_la-ftp.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-ftp.lo `test -f 'ftp.c' || echo '$(srcdir)/'`ftp.c

libcurl_la-url.lo: url.c
@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-url.lo -MD -MP -MF $(DEPDIR)/libcurl_la-url.Tpo -c -o libcurl_la-url.lo `test -f 'url.c' || echo '$(srcdir)/'`url.c
@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-url.Tpo $(DEPDIR)/libcurl_la-url.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='url.c' object='libcurl_la-url.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-url.lo `test -f 'url.c' || echo '$(srcdir)/'`url.c

libcurl_la-ftplistparser.lo: ftplistparser.c
@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-ftplistparser.lo -MD -MP -MF $(DEPDIR)/libcurl_la-ftplistparser.Tpo -c -o libcurl_la-ftplistparser.lo `test -f 'ftplistparser.c' || echo '$(srcdir)/'`ftplistparser.c
@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-ftplistparser.Tpo $(DEPDIR)/libcurl_la-ftplistparser.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='ftplistparser.c' object='libcurl_la-ftplistparser.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-ftplistparser.lo `test -f 'ftplistparser.c' || echo '$(srcdir)/'`ftplistparser.c








<
<
<
<
<
<
<







2210
2211
2212
2213
2214
2215
2216







2217
2218
2219
2220
2221
2222
2223
libcurl_la-ftp.lo: ftp.c
@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-ftp.lo -MD -MP -MF $(DEPDIR)/libcurl_la-ftp.Tpo -c -o libcurl_la-ftp.lo `test -f 'ftp.c' || echo '$(srcdir)/'`ftp.c
@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-ftp.Tpo $(DEPDIR)/libcurl_la-ftp.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='ftp.c' object='libcurl_la-ftp.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-ftp.lo `test -f 'ftp.c' || echo '$(srcdir)/'`ftp.c








libcurl_la-ftplistparser.lo: ftplistparser.c
@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-ftplistparser.lo -MD -MP -MF $(DEPDIR)/libcurl_la-ftplistparser.Tpo -c -o libcurl_la-ftplistparser.lo `test -f 'ftplistparser.c' || echo '$(srcdir)/'`ftplistparser.c
@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-ftplistparser.Tpo $(DEPDIR)/libcurl_la-ftplistparser.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='ftplistparser.c' object='libcurl_la-ftplistparser.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-ftplistparser.lo `test -f 'ftplistparser.c' || echo '$(srcdir)/'`ftplistparser.c

2005
2006
2007
2008
2009
2010
2011







2012
2013
2014
2015
2016
2017
2018
libcurl_la-hostsyn.lo: hostsyn.c
@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-hostsyn.lo -MD -MP -MF $(DEPDIR)/libcurl_la-hostsyn.Tpo -c -o libcurl_la-hostsyn.lo `test -f 'hostsyn.c' || echo '$(srcdir)/'`hostsyn.c
@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-hostsyn.Tpo $(DEPDIR)/libcurl_la-hostsyn.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='hostsyn.c' object='libcurl_la-hostsyn.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-hostsyn.lo `test -f 'hostsyn.c' || echo '$(srcdir)/'`hostsyn.c








libcurl_la-http.lo: http.c
@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-http.lo -MD -MP -MF $(DEPDIR)/libcurl_la-http.Tpo -c -o libcurl_la-http.lo `test -f 'http.c' || echo '$(srcdir)/'`http.c
@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-http.Tpo $(DEPDIR)/libcurl_la-http.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='http.c' object='libcurl_la-http.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-http.lo `test -f 'http.c' || echo '$(srcdir)/'`http.c








>
>
>
>
>
>
>







2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
libcurl_la-hostsyn.lo: hostsyn.c
@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-hostsyn.lo -MD -MP -MF $(DEPDIR)/libcurl_la-hostsyn.Tpo -c -o libcurl_la-hostsyn.lo `test -f 'hostsyn.c' || echo '$(srcdir)/'`hostsyn.c
@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-hostsyn.Tpo $(DEPDIR)/libcurl_la-hostsyn.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='hostsyn.c' object='libcurl_la-hostsyn.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-hostsyn.lo `test -f 'hostsyn.c' || echo '$(srcdir)/'`hostsyn.c

libcurl_la-hsts.lo: hsts.c
@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-hsts.lo -MD -MP -MF $(DEPDIR)/libcurl_la-hsts.Tpo -c -o libcurl_la-hsts.lo `test -f 'hsts.c' || echo '$(srcdir)/'`hsts.c
@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-hsts.Tpo $(DEPDIR)/libcurl_la-hsts.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='hsts.c' object='libcurl_la-hsts.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-hsts.lo `test -f 'hsts.c' || echo '$(srcdir)/'`hsts.c

libcurl_la-http.lo: http.c
@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-http.lo -MD -MP -MF $(DEPDIR)/libcurl_la-http.Tpo -c -o libcurl_la-http.lo `test -f 'http.c' || echo '$(srcdir)/'`http.c
@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-http.Tpo $(DEPDIR)/libcurl_la-http.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='http.c' object='libcurl_la-http.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-http.lo `test -f 'http.c' || echo '$(srcdir)/'`http.c

2054
2055
2056
2057
2058
2059
2060







2061
2062
2063
2064
2065
2066
2067
libcurl_la-http_proxy.lo: http_proxy.c
@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-http_proxy.lo -MD -MP -MF $(DEPDIR)/libcurl_la-http_proxy.Tpo -c -o libcurl_la-http_proxy.lo `test -f 'http_proxy.c' || echo '$(srcdir)/'`http_proxy.c
@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-http_proxy.Tpo $(DEPDIR)/libcurl_la-http_proxy.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='http_proxy.c' object='libcurl_la-http_proxy.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-http_proxy.lo `test -f 'http_proxy.c' || echo '$(srcdir)/'`http_proxy.c








libcurl_la-idn_win32.lo: idn_win32.c
@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-idn_win32.lo -MD -MP -MF $(DEPDIR)/libcurl_la-idn_win32.Tpo -c -o libcurl_la-idn_win32.lo `test -f 'idn_win32.c' || echo '$(srcdir)/'`idn_win32.c
@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-idn_win32.Tpo $(DEPDIR)/libcurl_la-idn_win32.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='idn_win32.c' object='libcurl_la-idn_win32.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-idn_win32.lo `test -f 'idn_win32.c' || echo '$(srcdir)/'`idn_win32.c








>
>
>
>
>
>
>







2350
2351
2352
2353
2354
2355
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
2370
libcurl_la-http_proxy.lo: http_proxy.c
@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-http_proxy.lo -MD -MP -MF $(DEPDIR)/libcurl_la-http_proxy.Tpo -c -o libcurl_la-http_proxy.lo `test -f 'http_proxy.c' || echo '$(srcdir)/'`http_proxy.c
@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-http_proxy.Tpo $(DEPDIR)/libcurl_la-http_proxy.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='http_proxy.c' object='libcurl_la-http_proxy.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-http_proxy.lo `test -f 'http_proxy.c' || echo '$(srcdir)/'`http_proxy.c

libcurl_la-http_aws_sigv4.lo: http_aws_sigv4.c
@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-http_aws_sigv4.lo -MD -MP -MF $(DEPDIR)/libcurl_la-http_aws_sigv4.Tpo -c -o libcurl_la-http_aws_sigv4.lo `test -f 'http_aws_sigv4.c' || echo '$(srcdir)/'`http_aws_sigv4.c
@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-http_aws_sigv4.Tpo $(DEPDIR)/libcurl_la-http_aws_sigv4.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='http_aws_sigv4.c' object='libcurl_la-http_aws_sigv4.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-http_aws_sigv4.lo `test -f 'http_aws_sigv4.c' || echo '$(srcdir)/'`http_aws_sigv4.c

libcurl_la-idn_win32.lo: idn_win32.c
@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-idn_win32.lo -MD -MP -MF $(DEPDIR)/libcurl_la-idn_win32.Tpo -c -o libcurl_la-idn_win32.lo `test -f 'idn_win32.c' || echo '$(srcdir)/'`idn_win32.c
@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-idn_win32.Tpo $(DEPDIR)/libcurl_la-idn_win32.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='idn_win32.c' object='libcurl_la-idn_win32.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-idn_win32.lo `test -f 'idn_win32.c' || echo '$(srcdir)/'`idn_win32.c

2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
libcurl_la-psl.lo: psl.c
@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-psl.lo -MD -MP -MF $(DEPDIR)/libcurl_la-psl.Tpo -c -o libcurl_la-psl.lo `test -f 'psl.c' || echo '$(srcdir)/'`psl.c
@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-psl.Tpo $(DEPDIR)/libcurl_la-psl.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='psl.c' object='libcurl_la-psl.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-psl.lo `test -f 'psl.c' || echo '$(srcdir)/'`psl.c

libcurl_la-doh.lo: doh.c
@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-doh.lo -MD -MP -MF $(DEPDIR)/libcurl_la-doh.Tpo -c -o libcurl_la-doh.lo `test -f 'doh.c' || echo '$(srcdir)/'`doh.c
@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-doh.Tpo $(DEPDIR)/libcurl_la-doh.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='doh.c' object='libcurl_la-doh.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-doh.lo `test -f 'doh.c' || echo '$(srcdir)/'`doh.c

libcurl_la-rand.lo: rand.c
@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-rand.lo -MD -MP -MF $(DEPDIR)/libcurl_la-rand.Tpo -c -o libcurl_la-rand.lo `test -f 'rand.c' || echo '$(srcdir)/'`rand.c
@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-rand.Tpo $(DEPDIR)/libcurl_la-rand.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='rand.c' object='libcurl_la-rand.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-rand.lo `test -f 'rand.c' || echo '$(srcdir)/'`rand.c








<
<
<
<
<
<
<







2525
2526
2527
2528
2529
2530
2531







2532
2533
2534
2535
2536
2537
2538
libcurl_la-psl.lo: psl.c
@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-psl.lo -MD -MP -MF $(DEPDIR)/libcurl_la-psl.Tpo -c -o libcurl_la-psl.lo `test -f 'psl.c' || echo '$(srcdir)/'`psl.c
@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-psl.Tpo $(DEPDIR)/libcurl_la-psl.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='psl.c' object='libcurl_la-psl.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-psl.lo `test -f 'psl.c' || echo '$(srcdir)/'`psl.c








libcurl_la-rand.lo: rand.c
@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-rand.lo -MD -MP -MF $(DEPDIR)/libcurl_la-rand.Tpo -c -o libcurl_la-rand.lo `test -f 'rand.c' || echo '$(srcdir)/'`rand.c
@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-rand.Tpo $(DEPDIR)/libcurl_la-rand.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='rand.c' object='libcurl_la-rand.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-rand.lo `test -f 'rand.c' || echo '$(srcdir)/'`rand.c

2418
2419
2420
2421
2422
2423
2424







2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438







2439
2440
2441
2442
2443
2444
2445
libcurl_la-transfer.lo: transfer.c
@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-transfer.lo -MD -MP -MF $(DEPDIR)/libcurl_la-transfer.Tpo -c -o libcurl_la-transfer.lo `test -f 'transfer.c' || echo '$(srcdir)/'`transfer.c
@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-transfer.Tpo $(DEPDIR)/libcurl_la-transfer.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='transfer.c' object='libcurl_la-transfer.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-transfer.lo `test -f 'transfer.c' || echo '$(srcdir)/'`transfer.c








libcurl_la-urlapi.lo: urlapi.c
@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-urlapi.lo -MD -MP -MF $(DEPDIR)/libcurl_la-urlapi.Tpo -c -o libcurl_la-urlapi.lo `test -f 'urlapi.c' || echo '$(srcdir)/'`urlapi.c
@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-urlapi.Tpo $(DEPDIR)/libcurl_la-urlapi.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='urlapi.c' object='libcurl_la-urlapi.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-urlapi.lo `test -f 'urlapi.c' || echo '$(srcdir)/'`urlapi.c

libcurl_la-version.lo: version.c
@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-version.lo -MD -MP -MF $(DEPDIR)/libcurl_la-version.Tpo -c -o libcurl_la-version.lo `test -f 'version.c' || echo '$(srcdir)/'`version.c
@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-version.Tpo $(DEPDIR)/libcurl_la-version.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='version.c' object='libcurl_la-version.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-version.lo `test -f 'version.c' || echo '$(srcdir)/'`version.c








libcurl_la-warnless.lo: warnless.c
@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-warnless.lo -MD -MP -MF $(DEPDIR)/libcurl_la-warnless.Tpo -c -o libcurl_la-warnless.lo `test -f 'warnless.c' || echo '$(srcdir)/'`warnless.c
@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-warnless.Tpo $(DEPDIR)/libcurl_la-warnless.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='warnless.c' object='libcurl_la-warnless.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-warnless.lo `test -f 'warnless.c' || echo '$(srcdir)/'`warnless.c








>
>
>
>
>
>
>














>
>
>
>
>
>
>







2714
2715
2716
2717
2718
2719
2720
2721
2722
2723
2724
2725
2726
2727
2728
2729
2730
2731
2732
2733
2734
2735
2736
2737
2738
2739
2740
2741
2742
2743
2744
2745
2746
2747
2748
2749
2750
2751
2752
2753
2754
2755
libcurl_la-transfer.lo: transfer.c
@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-transfer.lo -MD -MP -MF $(DEPDIR)/libcurl_la-transfer.Tpo -c -o libcurl_la-transfer.lo `test -f 'transfer.c' || echo '$(srcdir)/'`transfer.c
@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-transfer.Tpo $(DEPDIR)/libcurl_la-transfer.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='transfer.c' object='libcurl_la-transfer.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-transfer.lo `test -f 'transfer.c' || echo '$(srcdir)/'`transfer.c

libcurl_la-url.lo: url.c
@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-url.lo -MD -MP -MF $(DEPDIR)/libcurl_la-url.Tpo -c -o libcurl_la-url.lo `test -f 'url.c' || echo '$(srcdir)/'`url.c
@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-url.Tpo $(DEPDIR)/libcurl_la-url.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='url.c' object='libcurl_la-url.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-url.lo `test -f 'url.c' || echo '$(srcdir)/'`url.c

libcurl_la-urlapi.lo: urlapi.c
@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-urlapi.lo -MD -MP -MF $(DEPDIR)/libcurl_la-urlapi.Tpo -c -o libcurl_la-urlapi.lo `test -f 'urlapi.c' || echo '$(srcdir)/'`urlapi.c
@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-urlapi.Tpo $(DEPDIR)/libcurl_la-urlapi.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='urlapi.c' object='libcurl_la-urlapi.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-urlapi.lo `test -f 'urlapi.c' || echo '$(srcdir)/'`urlapi.c

libcurl_la-version.lo: version.c
@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-version.lo -MD -MP -MF $(DEPDIR)/libcurl_la-version.Tpo -c -o libcurl_la-version.lo `test -f 'version.c' || echo '$(srcdir)/'`version.c
@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-version.Tpo $(DEPDIR)/libcurl_la-version.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='version.c' object='libcurl_la-version.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-version.lo `test -f 'version.c' || echo '$(srcdir)/'`version.c

libcurl_la-version_win32.lo: version_win32.c
@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-version_win32.lo -MD -MP -MF $(DEPDIR)/libcurl_la-version_win32.Tpo -c -o libcurl_la-version_win32.lo `test -f 'version_win32.c' || echo '$(srcdir)/'`version_win32.c
@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-version_win32.Tpo $(DEPDIR)/libcurl_la-version_win32.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='version_win32.c' object='libcurl_la-version_win32.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-version_win32.lo `test -f 'version_win32.c' || echo '$(srcdir)/'`version_win32.c

libcurl_la-warnless.lo: warnless.c
@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-warnless.lo -MD -MP -MF $(DEPDIR)/libcurl_la-warnless.Tpo -c -o libcurl_la-warnless.lo `test -f 'warnless.c' || echo '$(srcdir)/'`warnless.c
@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-warnless.Tpo $(DEPDIR)/libcurl_la-warnless.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='warnless.c' object='libcurl_la-warnless.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-warnless.lo `test -f 'warnless.c' || echo '$(srcdir)/'`warnless.c

2453
2454
2455
2456
2457
2458
2459
2460
2461
2462
2463
2464
2465
2466
2467
2468
2469
2470
2471
2472
2473
2474
2475
2476
2477
2478
2479
2480
2481
2482
2483
2484
2485
2486
2487
2488
2489
2490
2491
2492
2493
2494
2495
2496
2497
2498
2499
2500
2501
libcurl_la-x509asn1.lo: x509asn1.c
@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-x509asn1.lo -MD -MP -MF $(DEPDIR)/libcurl_la-x509asn1.Tpo -c -o libcurl_la-x509asn1.lo `test -f 'x509asn1.c' || echo '$(srcdir)/'`x509asn1.c
@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-x509asn1.Tpo $(DEPDIR)/libcurl_la-x509asn1.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='x509asn1.c' object='libcurl_la-x509asn1.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-x509asn1.lo `test -f 'x509asn1.c' || echo '$(srcdir)/'`x509asn1.c

libcurl_la-dynbuf.lo: dynbuf.c
@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-dynbuf.lo -MD -MP -MF $(DEPDIR)/libcurl_la-dynbuf.Tpo -c -o libcurl_la-dynbuf.lo `test -f 'dynbuf.c' || echo '$(srcdir)/'`dynbuf.c
@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-dynbuf.Tpo $(DEPDIR)/libcurl_la-dynbuf.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='dynbuf.c' object='libcurl_la-dynbuf.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-dynbuf.lo `test -f 'dynbuf.c' || echo '$(srcdir)/'`dynbuf.c

libcurl_la-version_win32.lo: version_win32.c
@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-version_win32.lo -MD -MP -MF $(DEPDIR)/libcurl_la-version_win32.Tpo -c -o libcurl_la-version_win32.lo `test -f 'version_win32.c' || echo '$(srcdir)/'`version_win32.c
@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-version_win32.Tpo $(DEPDIR)/libcurl_la-version_win32.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='version_win32.c' object='libcurl_la-version_win32.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-version_win32.lo `test -f 'version_win32.c' || echo '$(srcdir)/'`version_win32.c

libcurl_la-easyoptions.lo: easyoptions.c
@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-easyoptions.lo -MD -MP -MF $(DEPDIR)/libcurl_la-easyoptions.Tpo -c -o libcurl_la-easyoptions.lo `test -f 'easyoptions.c' || echo '$(srcdir)/'`easyoptions.c
@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-easyoptions.Tpo $(DEPDIR)/libcurl_la-easyoptions.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='easyoptions.c' object='libcurl_la-easyoptions.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-easyoptions.lo `test -f 'easyoptions.c' || echo '$(srcdir)/'`easyoptions.c

libcurl_la-easygetopt.lo: easygetopt.c
@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-easygetopt.lo -MD -MP -MF $(DEPDIR)/libcurl_la-easygetopt.Tpo -c -o libcurl_la-easygetopt.lo `test -f 'easygetopt.c' || echo '$(srcdir)/'`easygetopt.c
@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-easygetopt.Tpo $(DEPDIR)/libcurl_la-easygetopt.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='easygetopt.c' object='libcurl_la-easygetopt.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-easygetopt.lo `test -f 'easygetopt.c' || echo '$(srcdir)/'`easygetopt.c

libcurl_la-hsts.lo: hsts.c
@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-hsts.lo -MD -MP -MF $(DEPDIR)/libcurl_la-hsts.Tpo -c -o libcurl_la-hsts.lo `test -f 'hsts.c' || echo '$(srcdir)/'`hsts.c
@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-hsts.Tpo $(DEPDIR)/libcurl_la-hsts.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='hsts.c' object='libcurl_la-hsts.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-hsts.lo `test -f 'hsts.c' || echo '$(srcdir)/'`hsts.c

vauth/libcurl_la-cleartext.lo: vauth/cleartext.c
@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT vauth/libcurl_la-cleartext.lo -MD -MP -MF vauth/$(DEPDIR)/libcurl_la-cleartext.Tpo -c -o vauth/libcurl_la-cleartext.lo `test -f 'vauth/cleartext.c' || echo '$(srcdir)/'`vauth/cleartext.c
@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) vauth/$(DEPDIR)/libcurl_la-cleartext.Tpo vauth/$(DEPDIR)/libcurl_la-cleartext.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='vauth/cleartext.c' object='vauth/libcurl_la-cleartext.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o vauth/libcurl_la-cleartext.lo `test -f 'vauth/cleartext.c' || echo '$(srcdir)/'`vauth/cleartext.c








<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







2763
2764
2765
2766
2767
2768
2769



































2770
2771
2772
2773
2774
2775
2776
libcurl_la-x509asn1.lo: x509asn1.c
@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-x509asn1.lo -MD -MP -MF $(DEPDIR)/libcurl_la-x509asn1.Tpo -c -o libcurl_la-x509asn1.lo `test -f 'x509asn1.c' || echo '$(srcdir)/'`x509asn1.c
@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-x509asn1.Tpo $(DEPDIR)/libcurl_la-x509asn1.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='x509asn1.c' object='libcurl_la-x509asn1.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-x509asn1.lo `test -f 'x509asn1.c' || echo '$(srcdir)/'`x509asn1.c




































vauth/libcurl_la-cleartext.lo: vauth/cleartext.c
@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT vauth/libcurl_la-cleartext.lo -MD -MP -MF vauth/$(DEPDIR)/libcurl_la-cleartext.Tpo -c -o vauth/libcurl_la-cleartext.lo `test -f 'vauth/cleartext.c' || echo '$(srcdir)/'`vauth/cleartext.c
@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) vauth/$(DEPDIR)/libcurl_la-cleartext.Tpo vauth/$(DEPDIR)/libcurl_la-cleartext.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='vauth/cleartext.c' object='vauth/libcurl_la-cleartext.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o vauth/libcurl_la-cleartext.lo `test -f 'vauth/cleartext.c' || echo '$(srcdir)/'`vauth/cleartext.c

2747
2748
2749
2750
2751
2752
2753







2754
2755
2756
2757
2758
2759
2760
libcurlu_la-base64.lo: base64.c
@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-base64.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-base64.Tpo -c -o libcurlu_la-base64.lo `test -f 'base64.c' || echo '$(srcdir)/'`base64.c
@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-base64.Tpo $(DEPDIR)/libcurlu_la-base64.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='base64.c' object='libcurlu_la-base64.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-base64.lo `test -f 'base64.c' || echo '$(srcdir)/'`base64.c








libcurlu_la-conncache.lo: conncache.c
@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-conncache.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-conncache.Tpo -c -o libcurlu_la-conncache.lo `test -f 'conncache.c' || echo '$(srcdir)/'`conncache.c
@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-conncache.Tpo $(DEPDIR)/libcurlu_la-conncache.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='conncache.c' object='libcurlu_la-conncache.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-conncache.lo `test -f 'conncache.c' || echo '$(srcdir)/'`conncache.c








>
>
>
>
>
>
>







3022
3023
3024
3025
3026
3027
3028
3029
3030
3031
3032
3033
3034
3035
3036
3037
3038
3039
3040
3041
3042
libcurlu_la-base64.lo: base64.c
@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-base64.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-base64.Tpo -c -o libcurlu_la-base64.lo `test -f 'base64.c' || echo '$(srcdir)/'`base64.c
@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-base64.Tpo $(DEPDIR)/libcurlu_la-base64.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='base64.c' object='libcurlu_la-base64.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-base64.lo `test -f 'base64.c' || echo '$(srcdir)/'`base64.c

libcurlu_la-c-hyper.lo: c-hyper.c
@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-c-hyper.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-c-hyper.Tpo -c -o libcurlu_la-c-hyper.lo `test -f 'c-hyper.c' || echo '$(srcdir)/'`c-hyper.c
@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-c-hyper.Tpo $(DEPDIR)/libcurlu_la-c-hyper.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='c-hyper.c' object='libcurlu_la-c-hyper.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-c-hyper.lo `test -f 'c-hyper.c' || echo '$(srcdir)/'`c-hyper.c

libcurlu_la-conncache.lo: conncache.c
@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-conncache.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-conncache.Tpo -c -o libcurlu_la-conncache.lo `test -f 'conncache.c' || echo '$(srcdir)/'`conncache.c
@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-conncache.Tpo $(DEPDIR)/libcurlu_la-conncache.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='conncache.c' object='libcurlu_la-conncache.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-conncache.lo `test -f 'conncache.c' || echo '$(srcdir)/'`conncache.c

2908
2909
2910
2911
2912
2913
2914







2915
2916
2917
2918
2919
2920
2921







2922
2923
2924
2925
2926
2927
2928














2929
2930
2931
2932
2933
2934
2935
libcurlu_la-dict.lo: dict.c
@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-dict.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-dict.Tpo -c -o libcurlu_la-dict.lo `test -f 'dict.c' || echo '$(srcdir)/'`dict.c
@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-dict.Tpo $(DEPDIR)/libcurlu_la-dict.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='dict.c' object='libcurlu_la-dict.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-dict.lo `test -f 'dict.c' || echo '$(srcdir)/'`dict.c








libcurlu_la-dotdot.lo: dotdot.c
@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-dotdot.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-dotdot.Tpo -c -o libcurlu_la-dotdot.lo `test -f 'dotdot.c' || echo '$(srcdir)/'`dotdot.c
@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-dotdot.Tpo $(DEPDIR)/libcurlu_la-dotdot.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='dotdot.c' object='libcurlu_la-dotdot.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-dotdot.lo `test -f 'dotdot.c' || echo '$(srcdir)/'`dotdot.c








libcurlu_la-easy.lo: easy.c
@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-easy.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-easy.Tpo -c -o libcurlu_la-easy.lo `test -f 'easy.c' || echo '$(srcdir)/'`easy.c
@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-easy.Tpo $(DEPDIR)/libcurlu_la-easy.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='easy.c' object='libcurlu_la-easy.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-easy.lo `test -f 'easy.c' || echo '$(srcdir)/'`easy.c















libcurlu_la-escape.lo: escape.c
@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-escape.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-escape.Tpo -c -o libcurlu_la-escape.lo `test -f 'escape.c' || echo '$(srcdir)/'`escape.c
@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-escape.Tpo $(DEPDIR)/libcurlu_la-escape.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='escape.c' object='libcurlu_la-escape.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-escape.lo `test -f 'escape.c' || echo '$(srcdir)/'`escape.c








>
>
>
>
>
>
>







>
>
>
>
>
>
>







>
>
>
>
>
>
>
>
>
>
>
>
>
>







3190
3191
3192
3193
3194
3195
3196
3197
3198
3199
3200
3201
3202
3203
3204
3205
3206
3207
3208
3209
3210
3211
3212
3213
3214
3215
3216
3217
3218
3219
3220
3221
3222
3223
3224
3225
3226
3227
3228
3229
3230
3231
3232
3233
3234
3235
3236
3237
3238
3239
3240
3241
3242
3243
3244
3245
libcurlu_la-dict.lo: dict.c
@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-dict.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-dict.Tpo -c -o libcurlu_la-dict.lo `test -f 'dict.c' || echo '$(srcdir)/'`dict.c
@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-dict.Tpo $(DEPDIR)/libcurlu_la-dict.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='dict.c' object='libcurlu_la-dict.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-dict.lo `test -f 'dict.c' || echo '$(srcdir)/'`dict.c

libcurlu_la-doh.lo: doh.c
@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-doh.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-doh.Tpo -c -o libcurlu_la-doh.lo `test -f 'doh.c' || echo '$(srcdir)/'`doh.c
@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-doh.Tpo $(DEPDIR)/libcurlu_la-doh.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='doh.c' object='libcurlu_la-doh.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-doh.lo `test -f 'doh.c' || echo '$(srcdir)/'`doh.c

libcurlu_la-dotdot.lo: dotdot.c
@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-dotdot.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-dotdot.Tpo -c -o libcurlu_la-dotdot.lo `test -f 'dotdot.c' || echo '$(srcdir)/'`dotdot.c
@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-dotdot.Tpo $(DEPDIR)/libcurlu_la-dotdot.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='dotdot.c' object='libcurlu_la-dotdot.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-dotdot.lo `test -f 'dotdot.c' || echo '$(srcdir)/'`dotdot.c

libcurlu_la-dynbuf.lo: dynbuf.c
@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-dynbuf.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-dynbuf.Tpo -c -o libcurlu_la-dynbuf.lo `test -f 'dynbuf.c' || echo '$(srcdir)/'`dynbuf.c
@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-dynbuf.Tpo $(DEPDIR)/libcurlu_la-dynbuf.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='dynbuf.c' object='libcurlu_la-dynbuf.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-dynbuf.lo `test -f 'dynbuf.c' || echo '$(srcdir)/'`dynbuf.c

libcurlu_la-easy.lo: easy.c
@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-easy.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-easy.Tpo -c -o libcurlu_la-easy.lo `test -f 'easy.c' || echo '$(srcdir)/'`easy.c
@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-easy.Tpo $(DEPDIR)/libcurlu_la-easy.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='easy.c' object='libcurlu_la-easy.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-easy.lo `test -f 'easy.c' || echo '$(srcdir)/'`easy.c

libcurlu_la-easygetopt.lo: easygetopt.c
@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-easygetopt.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-easygetopt.Tpo -c -o libcurlu_la-easygetopt.lo `test -f 'easygetopt.c' || echo '$(srcdir)/'`easygetopt.c
@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-easygetopt.Tpo $(DEPDIR)/libcurlu_la-easygetopt.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='easygetopt.c' object='libcurlu_la-easygetopt.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-easygetopt.lo `test -f 'easygetopt.c' || echo '$(srcdir)/'`easygetopt.c

libcurlu_la-easyoptions.lo: easyoptions.c
@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-easyoptions.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-easyoptions.Tpo -c -o libcurlu_la-easyoptions.lo `test -f 'easyoptions.c' || echo '$(srcdir)/'`easyoptions.c
@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-easyoptions.Tpo $(DEPDIR)/libcurlu_la-easyoptions.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='easyoptions.c' object='libcurlu_la-easyoptions.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-easyoptions.lo `test -f 'easyoptions.c' || echo '$(srcdir)/'`easyoptions.c

libcurlu_la-escape.lo: escape.c
@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-escape.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-escape.Tpo -c -o libcurlu_la-escape.lo `test -f 'escape.c' || echo '$(srcdir)/'`escape.c
@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-escape.Tpo $(DEPDIR)/libcurlu_la-escape.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='escape.c' object='libcurlu_la-escape.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-escape.lo `test -f 'escape.c' || echo '$(srcdir)/'`escape.c

2957
2958
2959
2960
2961
2962
2963
2964
2965
2966
2967
2968
2969
2970
2971
2972
2973
2974
2975
2976
2977
libcurlu_la-ftp.lo: ftp.c
@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-ftp.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-ftp.Tpo -c -o libcurlu_la-ftp.lo `test -f 'ftp.c' || echo '$(srcdir)/'`ftp.c
@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-ftp.Tpo $(DEPDIR)/libcurlu_la-ftp.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='ftp.c' object='libcurlu_la-ftp.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-ftp.lo `test -f 'ftp.c' || echo '$(srcdir)/'`ftp.c

libcurlu_la-url.lo: url.c
@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-url.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-url.Tpo -c -o libcurlu_la-url.lo `test -f 'url.c' || echo '$(srcdir)/'`url.c
@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-url.Tpo $(DEPDIR)/libcurlu_la-url.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='url.c' object='libcurlu_la-url.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-url.lo `test -f 'url.c' || echo '$(srcdir)/'`url.c

libcurlu_la-ftplistparser.lo: ftplistparser.c
@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-ftplistparser.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-ftplistparser.Tpo -c -o libcurlu_la-ftplistparser.lo `test -f 'ftplistparser.c' || echo '$(srcdir)/'`ftplistparser.c
@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-ftplistparser.Tpo $(DEPDIR)/libcurlu_la-ftplistparser.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='ftplistparser.c' object='libcurlu_la-ftplistparser.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-ftplistparser.lo `test -f 'ftplistparser.c' || echo '$(srcdir)/'`ftplistparser.c








<
<
<
<
<
<
<







3267
3268
3269
3270
3271
3272
3273







3274
3275
3276
3277
3278
3279
3280
libcurlu_la-ftp.lo: ftp.c
@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-ftp.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-ftp.Tpo -c -o libcurlu_la-ftp.lo `test -f 'ftp.c' || echo '$(srcdir)/'`ftp.c
@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-ftp.Tpo $(DEPDIR)/libcurlu_la-ftp.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='ftp.c' object='libcurlu_la-ftp.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-ftp.lo `test -f 'ftp.c' || echo '$(srcdir)/'`ftp.c








libcurlu_la-ftplistparser.lo: ftplistparser.c
@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-ftplistparser.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-ftplistparser.Tpo -c -o libcurlu_la-ftplistparser.lo `test -f 'ftplistparser.c' || echo '$(srcdir)/'`ftplistparser.c
@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-ftplistparser.Tpo $(DEPDIR)/libcurlu_la-ftplistparser.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='ftplistparser.c' object='libcurlu_la-ftplistparser.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-ftplistparser.lo `test -f 'ftplistparser.c' || echo '$(srcdir)/'`ftplistparser.c

3048
3049
3050
3051
3052
3053
3054







3055
3056
3057
3058
3059
3060
3061
libcurlu_la-hostsyn.lo: hostsyn.c
@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-hostsyn.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-hostsyn.Tpo -c -o libcurlu_la-hostsyn.lo `test -f 'hostsyn.c' || echo '$(srcdir)/'`hostsyn.c
@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-hostsyn.Tpo $(DEPDIR)/libcurlu_la-hostsyn.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='hostsyn.c' object='libcurlu_la-hostsyn.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-hostsyn.lo `test -f 'hostsyn.c' || echo '$(srcdir)/'`hostsyn.c








libcurlu_la-http.lo: http.c
@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-http.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-http.Tpo -c -o libcurlu_la-http.lo `test -f 'http.c' || echo '$(srcdir)/'`http.c
@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-http.Tpo $(DEPDIR)/libcurlu_la-http.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='http.c' object='libcurlu_la-http.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-http.lo `test -f 'http.c' || echo '$(srcdir)/'`http.c








>
>
>
>
>
>
>







3351
3352
3353
3354
3355
3356
3357
3358
3359
3360
3361
3362
3363
3364
3365
3366
3367
3368
3369
3370
3371
libcurlu_la-hostsyn.lo: hostsyn.c
@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-hostsyn.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-hostsyn.Tpo -c -o libcurlu_la-hostsyn.lo `test -f 'hostsyn.c' || echo '$(srcdir)/'`hostsyn.c
@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-hostsyn.Tpo $(DEPDIR)/libcurlu_la-hostsyn.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='hostsyn.c' object='libcurlu_la-hostsyn.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-hostsyn.lo `test -f 'hostsyn.c' || echo '$(srcdir)/'`hostsyn.c

libcurlu_la-hsts.lo: hsts.c
@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-hsts.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-hsts.Tpo -c -o libcurlu_la-hsts.lo `test -f 'hsts.c' || echo '$(srcdir)/'`hsts.c
@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-hsts.Tpo $(DEPDIR)/libcurlu_la-hsts.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='hsts.c' object='libcurlu_la-hsts.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-hsts.lo `test -f 'hsts.c' || echo '$(srcdir)/'`hsts.c

libcurlu_la-http.lo: http.c
@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-http.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-http.Tpo -c -o libcurlu_la-http.lo `test -f 'http.c' || echo '$(srcdir)/'`http.c
@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-http.Tpo $(DEPDIR)/libcurlu_la-http.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='http.c' object='libcurlu_la-http.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-http.lo `test -f 'http.c' || echo '$(srcdir)/'`http.c

3097
3098
3099
3100
3101
3102
3103







3104
3105
3106
3107
3108
3109
3110
libcurlu_la-http_proxy.lo: http_proxy.c
@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-http_proxy.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-http_proxy.Tpo -c -o libcurlu_la-http_proxy.lo `test -f 'http_proxy.c' || echo '$(srcdir)/'`http_proxy.c
@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-http_proxy.Tpo $(DEPDIR)/libcurlu_la-http_proxy.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='http_proxy.c' object='libcurlu_la-http_proxy.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-http_proxy.lo `test -f 'http_proxy.c' || echo '$(srcdir)/'`http_proxy.c








libcurlu_la-idn_win32.lo: idn_win32.c
@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-idn_win32.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-idn_win32.Tpo -c -o libcurlu_la-idn_win32.lo `test -f 'idn_win32.c' || echo '$(srcdir)/'`idn_win32.c
@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-idn_win32.Tpo $(DEPDIR)/libcurlu_la-idn_win32.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='idn_win32.c' object='libcurlu_la-idn_win32.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-idn_win32.lo `test -f 'idn_win32.c' || echo '$(srcdir)/'`idn_win32.c








>
>
>
>
>
>
>







3407
3408
3409
3410
3411
3412
3413
3414
3415
3416
3417
3418
3419
3420
3421
3422
3423
3424
3425
3426
3427
libcurlu_la-http_proxy.lo: http_proxy.c
@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-http_proxy.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-http_proxy.Tpo -c -o libcurlu_la-http_proxy.lo `test -f 'http_proxy.c' || echo '$(srcdir)/'`http_proxy.c
@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-http_proxy.Tpo $(DEPDIR)/libcurlu_la-http_proxy.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='http_proxy.c' object='libcurlu_la-http_proxy.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-http_proxy.lo `test -f 'http_proxy.c' || echo '$(srcdir)/'`http_proxy.c

libcurlu_la-http_aws_sigv4.lo: http_aws_sigv4.c
@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-http_aws_sigv4.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-http_aws_sigv4.Tpo -c -o libcurlu_la-http_aws_sigv4.lo `test -f 'http_aws_sigv4.c' || echo '$(srcdir)/'`http_aws_sigv4.c
@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-http_aws_sigv4.Tpo $(DEPDIR)/libcurlu_la-http_aws_sigv4.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='http_aws_sigv4.c' object='libcurlu_la-http_aws_sigv4.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-http_aws_sigv4.lo `test -f 'http_aws_sigv4.c' || echo '$(srcdir)/'`http_aws_sigv4.c

libcurlu_la-idn_win32.lo: idn_win32.c
@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-idn_win32.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-idn_win32.Tpo -c -o libcurlu_la-idn_win32.lo `test -f 'idn_win32.c' || echo '$(srcdir)/'`idn_win32.c
@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-idn_win32.Tpo $(DEPDIR)/libcurlu_la-idn_win32.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='idn_win32.c' object='libcurlu_la-idn_win32.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-idn_win32.lo `test -f 'idn_win32.c' || echo '$(srcdir)/'`idn_win32.c

3265
3266
3267
3268
3269
3270
3271
3272
3273
3274
3275
3276
3277
3278
3279
3280
3281
3282
3283
3284
3285
libcurlu_la-psl.lo: psl.c
@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-psl.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-psl.Tpo -c -o libcurlu_la-psl.lo `test -f 'psl.c' || echo '$(srcdir)/'`psl.c
@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-psl.Tpo $(DEPDIR)/libcurlu_la-psl.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='psl.c' object='libcurlu_la-psl.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-psl.lo `test -f 'psl.c' || echo '$(srcdir)/'`psl.c

libcurlu_la-doh.lo: doh.c
@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-doh.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-doh.Tpo -c -o libcurlu_la-doh.lo `test -f 'doh.c' || echo '$(srcdir)/'`doh.c
@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-doh.Tpo $(DEPDIR)/libcurlu_la-doh.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='doh.c' object='libcurlu_la-doh.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-doh.lo `test -f 'doh.c' || echo '$(srcdir)/'`doh.c

libcurlu_la-rand.lo: rand.c
@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-rand.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-rand.Tpo -c -o libcurlu_la-rand.lo `test -f 'rand.c' || echo '$(srcdir)/'`rand.c
@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-rand.Tpo $(DEPDIR)/libcurlu_la-rand.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='rand.c' object='libcurlu_la-rand.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-rand.lo `test -f 'rand.c' || echo '$(srcdir)/'`rand.c








<
<
<
<
<
<
<







3582
3583
3584
3585
3586
3587
3588







3589
3590
3591
3592
3593
3594
3595
libcurlu_la-psl.lo: psl.c
@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-psl.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-psl.Tpo -c -o libcurlu_la-psl.lo `test -f 'psl.c' || echo '$(srcdir)/'`psl.c
@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-psl.Tpo $(DEPDIR)/libcurlu_la-psl.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='psl.c' object='libcurlu_la-psl.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-psl.lo `test -f 'psl.c' || echo '$(srcdir)/'`psl.c








libcurlu_la-rand.lo: rand.c
@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-rand.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-rand.Tpo -c -o libcurlu_la-rand.lo `test -f 'rand.c' || echo '$(srcdir)/'`rand.c
@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-rand.Tpo $(DEPDIR)/libcurlu_la-rand.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='rand.c' object='libcurlu_la-rand.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-rand.lo `test -f 'rand.c' || echo '$(srcdir)/'`rand.c

3461
3462
3463
3464
3465
3466
3467







3468
3469
3470
3471
3472
3473
3474
3475
3476
3477
3478
3479
3480
3481







3482
3483
3484
3485
3486
3487
3488
libcurlu_la-transfer.lo: transfer.c
@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-transfer.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-transfer.Tpo -c -o libcurlu_la-transfer.lo `test -f 'transfer.c' || echo '$(srcdir)/'`transfer.c
@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-transfer.Tpo $(DEPDIR)/libcurlu_la-transfer.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='transfer.c' object='libcurlu_la-transfer.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-transfer.lo `test -f 'transfer.c' || echo '$(srcdir)/'`transfer.c








libcurlu_la-urlapi.lo: urlapi.c
@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-urlapi.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-urlapi.Tpo -c -o libcurlu_la-urlapi.lo `test -f 'urlapi.c' || echo '$(srcdir)/'`urlapi.c
@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-urlapi.Tpo $(DEPDIR)/libcurlu_la-urlapi.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='urlapi.c' object='libcurlu_la-urlapi.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-urlapi.lo `test -f 'urlapi.c' || echo '$(srcdir)/'`urlapi.c

libcurlu_la-version.lo: version.c
@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-version.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-version.Tpo -c -o libcurlu_la-version.lo `test -f 'version.c' || echo '$(srcdir)/'`version.c
@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-version.Tpo $(DEPDIR)/libcurlu_la-version.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='version.c' object='libcurlu_la-version.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-version.lo `test -f 'version.c' || echo '$(srcdir)/'`version.c








libcurlu_la-warnless.lo: warnless.c
@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-warnless.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-warnless.Tpo -c -o libcurlu_la-warnless.lo `test -f 'warnless.c' || echo '$(srcdir)/'`warnless.c
@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-warnless.Tpo $(DEPDIR)/libcurlu_la-warnless.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='warnless.c' object='libcurlu_la-warnless.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-warnless.lo `test -f 'warnless.c' || echo '$(srcdir)/'`warnless.c








>
>
>
>
>
>
>














>
>
>
>
>
>
>







3771
3772
3773
3774
3775
3776
3777
3778
3779
3780
3781
3782
3783
3784
3785
3786
3787
3788
3789
3790
3791
3792
3793
3794
3795
3796
3797
3798
3799
3800
3801
3802
3803
3804
3805
3806
3807
3808
3809
3810
3811
3812
libcurlu_la-transfer.lo: transfer.c
@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-transfer.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-transfer.Tpo -c -o libcurlu_la-transfer.lo `test -f 'transfer.c' || echo '$(srcdir)/'`transfer.c
@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-transfer.Tpo $(DEPDIR)/libcurlu_la-transfer.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='transfer.c' object='libcurlu_la-transfer.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-transfer.lo `test -f 'transfer.c' || echo '$(srcdir)/'`transfer.c

libcurlu_la-url.lo: url.c
@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-url.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-url.Tpo -c -o libcurlu_la-url.lo `test -f 'url.c' || echo '$(srcdir)/'`url.c
@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-url.Tpo $(DEPDIR)/libcurlu_la-url.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='url.c' object='libcurlu_la-url.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-url.lo `test -f 'url.c' || echo '$(srcdir)/'`url.c

libcurlu_la-urlapi.lo: urlapi.c
@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-urlapi.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-urlapi.Tpo -c -o libcurlu_la-urlapi.lo `test -f 'urlapi.c' || echo '$(srcdir)/'`urlapi.c
@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-urlapi.Tpo $(DEPDIR)/libcurlu_la-urlapi.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='urlapi.c' object='libcurlu_la-urlapi.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-urlapi.lo `test -f 'urlapi.c' || echo '$(srcdir)/'`urlapi.c

libcurlu_la-version.lo: version.c
@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-version.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-version.Tpo -c -o libcurlu_la-version.lo `test -f 'version.c' || echo '$(srcdir)/'`version.c
@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-version.Tpo $(DEPDIR)/libcurlu_la-version.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='version.c' object='libcurlu_la-version.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-version.lo `test -f 'version.c' || echo '$(srcdir)/'`version.c

libcurlu_la-version_win32.lo: version_win32.c
@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-version_win32.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-version_win32.Tpo -c -o libcurlu_la-version_win32.lo `test -f 'version_win32.c' || echo '$(srcdir)/'`version_win32.c
@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-version_win32.Tpo $(DEPDIR)/libcurlu_la-version_win32.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='version_win32.c' object='libcurlu_la-version_win32.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-version_win32.lo `test -f 'version_win32.c' || echo '$(srcdir)/'`version_win32.c

libcurlu_la-warnless.lo: warnless.c
@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-warnless.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-warnless.Tpo -c -o libcurlu_la-warnless.lo `test -f 'warnless.c' || echo '$(srcdir)/'`warnless.c
@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-warnless.Tpo $(DEPDIR)/libcurlu_la-warnless.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='warnless.c' object='libcurlu_la-warnless.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-warnless.lo `test -f 'warnless.c' || echo '$(srcdir)/'`warnless.c

3496
3497
3498
3499
3500
3501
3502
3503
3504
3505
3506
3507
3508
3509
3510
3511
3512
3513
3514
3515
3516
3517
3518
3519
3520
3521
3522
3523
3524
3525
3526
3527
3528
3529
3530
3531
3532
3533
3534
3535
3536
3537
3538
3539
3540
3541
3542
3543
3544
libcurlu_la-x509asn1.lo: x509asn1.c
@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-x509asn1.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-x509asn1.Tpo -c -o libcurlu_la-x509asn1.lo `test -f 'x509asn1.c' || echo '$(srcdir)/'`x509asn1.c
@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-x509asn1.Tpo $(DEPDIR)/libcurlu_la-x509asn1.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='x509asn1.c' object='libcurlu_la-x509asn1.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-x509asn1.lo `test -f 'x509asn1.c' || echo '$(srcdir)/'`x509asn1.c

libcurlu_la-dynbuf.lo: dynbuf.c
@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-dynbuf.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-dynbuf.Tpo -c -o libcurlu_la-dynbuf.lo `test -f 'dynbuf.c' || echo '$(srcdir)/'`dynbuf.c
@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-dynbuf.Tpo $(DEPDIR)/libcurlu_la-dynbuf.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='dynbuf.c' object='libcurlu_la-dynbuf.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-dynbuf.lo `test -f 'dynbuf.c' || echo '$(srcdir)/'`dynbuf.c

libcurlu_la-version_win32.lo: version_win32.c
@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-version_win32.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-version_win32.Tpo -c -o libcurlu_la-version_win32.lo `test -f 'version_win32.c' || echo '$(srcdir)/'`version_win32.c
@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-version_win32.Tpo $(DEPDIR)/libcurlu_la-version_win32.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='version_win32.c' object='libcurlu_la-version_win32.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-version_win32.lo `test -f 'version_win32.c' || echo '$(srcdir)/'`version_win32.c

libcurlu_la-easyoptions.lo: easyoptions.c
@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-easyoptions.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-easyoptions.Tpo -c -o libcurlu_la-easyoptions.lo `test -f 'easyoptions.c' || echo '$(srcdir)/'`easyoptions.c
@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-easyoptions.Tpo $(DEPDIR)/libcurlu_la-easyoptions.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='easyoptions.c' object='libcurlu_la-easyoptions.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-easyoptions.lo `test -f 'easyoptions.c' || echo '$(srcdir)/'`easyoptions.c

libcurlu_la-easygetopt.lo: easygetopt.c
@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-easygetopt.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-easygetopt.Tpo -c -o libcurlu_la-easygetopt.lo `test -f 'easygetopt.c' || echo '$(srcdir)/'`easygetopt.c
@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-easygetopt.Tpo $(DEPDIR)/libcurlu_la-easygetopt.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='easygetopt.c' object='libcurlu_la-easygetopt.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-easygetopt.lo `test -f 'easygetopt.c' || echo '$(srcdir)/'`easygetopt.c

libcurlu_la-hsts.lo: hsts.c
@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-hsts.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-hsts.Tpo -c -o libcurlu_la-hsts.lo `test -f 'hsts.c' || echo '$(srcdir)/'`hsts.c
@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-hsts.Tpo $(DEPDIR)/libcurlu_la-hsts.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='hsts.c' object='libcurlu_la-hsts.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-hsts.lo `test -f 'hsts.c' || echo '$(srcdir)/'`hsts.c

vauth/libcurlu_la-cleartext.lo: vauth/cleartext.c
@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT vauth/libcurlu_la-cleartext.lo -MD -MP -MF vauth/$(DEPDIR)/libcurlu_la-cleartext.Tpo -c -o vauth/libcurlu_la-cleartext.lo `test -f 'vauth/cleartext.c' || echo '$(srcdir)/'`vauth/cleartext.c
@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) vauth/$(DEPDIR)/libcurlu_la-cleartext.Tpo vauth/$(DEPDIR)/libcurlu_la-cleartext.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='vauth/cleartext.c' object='vauth/libcurlu_la-cleartext.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o vauth/libcurlu_la-cleartext.lo `test -f 'vauth/cleartext.c' || echo '$(srcdir)/'`vauth/cleartext.c








<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







3820
3821
3822
3823
3824
3825
3826



































3827
3828
3829
3830
3831
3832
3833
libcurlu_la-x509asn1.lo: x509asn1.c
@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-x509asn1.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-x509asn1.Tpo -c -o libcurlu_la-x509asn1.lo `test -f 'x509asn1.c' || echo '$(srcdir)/'`x509asn1.c
@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-x509asn1.Tpo $(DEPDIR)/libcurlu_la-x509asn1.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='x509asn1.c' object='libcurlu_la-x509asn1.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-x509asn1.lo `test -f 'x509asn1.c' || echo '$(srcdir)/'`x509asn1.c




































vauth/libcurlu_la-cleartext.lo: vauth/cleartext.c
@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT vauth/libcurlu_la-cleartext.lo -MD -MP -MF vauth/$(DEPDIR)/libcurlu_la-cleartext.Tpo -c -o vauth/libcurlu_la-cleartext.lo `test -f 'vauth/cleartext.c' || echo '$(srcdir)/'`vauth/cleartext.c
@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) vauth/$(DEPDIR)/libcurlu_la-cleartext.Tpo vauth/$(DEPDIR)/libcurlu_la-cleartext.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='vauth/cleartext.c' object='vauth/libcurlu_la-cleartext.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o vauth/libcurlu_la-cleartext.lo `test -f 'vauth/cleartext.c' || echo '$(srcdir)/'`vauth/cleartext.c

3907
3908
3909
3910
3911
3912
3913

3914
3915
3916
3917
3918
3919
3920

distclean: distclean-am
		-rm -f ./$(DEPDIR)/libcurl_la-altsvc.Plo
	-rm -f ./$(DEPDIR)/libcurl_la-amigaos.Plo
	-rm -f ./$(DEPDIR)/libcurl_la-asyn-ares.Plo
	-rm -f ./$(DEPDIR)/libcurl_la-asyn-thread.Plo
	-rm -f ./$(DEPDIR)/libcurl_la-base64.Plo

	-rm -f ./$(DEPDIR)/libcurl_la-conncache.Plo
	-rm -f ./$(DEPDIR)/libcurl_la-connect.Plo
	-rm -f ./$(DEPDIR)/libcurl_la-content_encoding.Plo
	-rm -f ./$(DEPDIR)/libcurl_la-cookie.Plo
	-rm -f ./$(DEPDIR)/libcurl_la-curl_addrinfo.Plo
	-rm -f ./$(DEPDIR)/libcurl_la-curl_ctype.Plo
	-rm -f ./$(DEPDIR)/libcurl_la-curl_des.Plo







>







4196
4197
4198
4199
4200
4201
4202
4203
4204
4205
4206
4207
4208
4209
4210

distclean: distclean-am
		-rm -f ./$(DEPDIR)/libcurl_la-altsvc.Plo
	-rm -f ./$(DEPDIR)/libcurl_la-amigaos.Plo
	-rm -f ./$(DEPDIR)/libcurl_la-asyn-ares.Plo
	-rm -f ./$(DEPDIR)/libcurl_la-asyn-thread.Plo
	-rm -f ./$(DEPDIR)/libcurl_la-base64.Plo
	-rm -f ./$(DEPDIR)/libcurl_la-c-hyper.Plo
	-rm -f ./$(DEPDIR)/libcurl_la-conncache.Plo
	-rm -f ./$(DEPDIR)/libcurl_la-connect.Plo
	-rm -f ./$(DEPDIR)/libcurl_la-content_encoding.Plo
	-rm -f ./$(DEPDIR)/libcurl_la-cookie.Plo
	-rm -f ./$(DEPDIR)/libcurl_la-curl_addrinfo.Plo
	-rm -f ./$(DEPDIR)/libcurl_la-curl_ctype.Plo
	-rm -f ./$(DEPDIR)/libcurl_la-curl_des.Plo
3956
3957
3958
3959
3960
3961
3962

3963
3964
3965
3966
3967
3968
3969
	-rm -f ./$(DEPDIR)/libcurl_la-hostip.Plo
	-rm -f ./$(DEPDIR)/libcurl_la-hostip4.Plo
	-rm -f ./$(DEPDIR)/libcurl_la-hostip6.Plo
	-rm -f ./$(DEPDIR)/libcurl_la-hostsyn.Plo
	-rm -f ./$(DEPDIR)/libcurl_la-hsts.Plo
	-rm -f ./$(DEPDIR)/libcurl_la-http.Plo
	-rm -f ./$(DEPDIR)/libcurl_la-http2.Plo

	-rm -f ./$(DEPDIR)/libcurl_la-http_chunks.Plo
	-rm -f ./$(DEPDIR)/libcurl_la-http_digest.Plo
	-rm -f ./$(DEPDIR)/libcurl_la-http_negotiate.Plo
	-rm -f ./$(DEPDIR)/libcurl_la-http_ntlm.Plo
	-rm -f ./$(DEPDIR)/libcurl_la-http_proxy.Plo
	-rm -f ./$(DEPDIR)/libcurl_la-idn_win32.Plo
	-rm -f ./$(DEPDIR)/libcurl_la-if2ip.Plo







>







4246
4247
4248
4249
4250
4251
4252
4253
4254
4255
4256
4257
4258
4259
4260
	-rm -f ./$(DEPDIR)/libcurl_la-hostip.Plo
	-rm -f ./$(DEPDIR)/libcurl_la-hostip4.Plo
	-rm -f ./$(DEPDIR)/libcurl_la-hostip6.Plo
	-rm -f ./$(DEPDIR)/libcurl_la-hostsyn.Plo
	-rm -f ./$(DEPDIR)/libcurl_la-hsts.Plo
	-rm -f ./$(DEPDIR)/libcurl_la-http.Plo
	-rm -f ./$(DEPDIR)/libcurl_la-http2.Plo
	-rm -f ./$(DEPDIR)/libcurl_la-http_aws_sigv4.Plo
	-rm -f ./$(DEPDIR)/libcurl_la-http_chunks.Plo
	-rm -f ./$(DEPDIR)/libcurl_la-http_digest.Plo
	-rm -f ./$(DEPDIR)/libcurl_la-http_negotiate.Plo
	-rm -f ./$(DEPDIR)/libcurl_la-http_ntlm.Plo
	-rm -f ./$(DEPDIR)/libcurl_la-http_proxy.Plo
	-rm -f ./$(DEPDIR)/libcurl_la-idn_win32.Plo
	-rm -f ./$(DEPDIR)/libcurl_la-if2ip.Plo
4024
4025
4026
4027
4028
4029
4030

4031
4032
4033
4034
4035
4036
4037
	-rm -f ./$(DEPDIR)/libcurl_la-wildcard.Plo
	-rm -f ./$(DEPDIR)/libcurl_la-x509asn1.Plo
	-rm -f ./$(DEPDIR)/libcurlu_la-altsvc.Plo
	-rm -f ./$(DEPDIR)/libcurlu_la-amigaos.Plo
	-rm -f ./$(DEPDIR)/libcurlu_la-asyn-ares.Plo
	-rm -f ./$(DEPDIR)/libcurlu_la-asyn-thread.Plo
	-rm -f ./$(DEPDIR)/libcurlu_la-base64.Plo

	-rm -f ./$(DEPDIR)/libcurlu_la-conncache.Plo
	-rm -f ./$(DEPDIR)/libcurlu_la-connect.Plo
	-rm -f ./$(DEPDIR)/libcurlu_la-content_encoding.Plo
	-rm -f ./$(DEPDIR)/libcurlu_la-cookie.Plo
	-rm -f ./$(DEPDIR)/libcurlu_la-curl_addrinfo.Plo
	-rm -f ./$(DEPDIR)/libcurlu_la-curl_ctype.Plo
	-rm -f ./$(DEPDIR)/libcurlu_la-curl_des.Plo







>







4315
4316
4317
4318
4319
4320
4321
4322
4323
4324
4325
4326
4327
4328
4329
	-rm -f ./$(DEPDIR)/libcurl_la-wildcard.Plo
	-rm -f ./$(DEPDIR)/libcurl_la-x509asn1.Plo
	-rm -f ./$(DEPDIR)/libcurlu_la-altsvc.Plo
	-rm -f ./$(DEPDIR)/libcurlu_la-amigaos.Plo
	-rm -f ./$(DEPDIR)/libcurlu_la-asyn-ares.Plo
	-rm -f ./$(DEPDIR)/libcurlu_la-asyn-thread.Plo
	-rm -f ./$(DEPDIR)/libcurlu_la-base64.Plo
	-rm -f ./$(DEPDIR)/libcurlu_la-c-hyper.Plo
	-rm -f ./$(DEPDIR)/libcurlu_la-conncache.Plo
	-rm -f ./$(DEPDIR)/libcurlu_la-connect.Plo
	-rm -f ./$(DEPDIR)/libcurlu_la-content_encoding.Plo
	-rm -f ./$(DEPDIR)/libcurlu_la-cookie.Plo
	-rm -f ./$(DEPDIR)/libcurlu_la-curl_addrinfo.Plo
	-rm -f ./$(DEPDIR)/libcurlu_la-curl_ctype.Plo
	-rm -f ./$(DEPDIR)/libcurlu_la-curl_des.Plo
4073
4074
4075
4076
4077
4078
4079

4080
4081
4082
4083
4084
4085
4086
	-rm -f ./$(DEPDIR)/libcurlu_la-hostip.Plo
	-rm -f ./$(DEPDIR)/libcurlu_la-hostip4.Plo
	-rm -f ./$(DEPDIR)/libcurlu_la-hostip6.Plo
	-rm -f ./$(DEPDIR)/libcurlu_la-hostsyn.Plo
	-rm -f ./$(DEPDIR)/libcurlu_la-hsts.Plo
	-rm -f ./$(DEPDIR)/libcurlu_la-http.Plo
	-rm -f ./$(DEPDIR)/libcurlu_la-http2.Plo

	-rm -f ./$(DEPDIR)/libcurlu_la-http_chunks.Plo
	-rm -f ./$(DEPDIR)/libcurlu_la-http_digest.Plo
	-rm -f ./$(DEPDIR)/libcurlu_la-http_negotiate.Plo
	-rm -f ./$(DEPDIR)/libcurlu_la-http_ntlm.Plo
	-rm -f ./$(DEPDIR)/libcurlu_la-http_proxy.Plo
	-rm -f ./$(DEPDIR)/libcurlu_la-idn_win32.Plo
	-rm -f ./$(DEPDIR)/libcurlu_la-if2ip.Plo







>







4365
4366
4367
4368
4369
4370
4371
4372
4373
4374
4375
4376
4377
4378
4379
	-rm -f ./$(DEPDIR)/libcurlu_la-hostip.Plo
	-rm -f ./$(DEPDIR)/libcurlu_la-hostip4.Plo
	-rm -f ./$(DEPDIR)/libcurlu_la-hostip6.Plo
	-rm -f ./$(DEPDIR)/libcurlu_la-hostsyn.Plo
	-rm -f ./$(DEPDIR)/libcurlu_la-hsts.Plo
	-rm -f ./$(DEPDIR)/libcurlu_la-http.Plo
	-rm -f ./$(DEPDIR)/libcurlu_la-http2.Plo
	-rm -f ./$(DEPDIR)/libcurlu_la-http_aws_sigv4.Plo
	-rm -f ./$(DEPDIR)/libcurlu_la-http_chunks.Plo
	-rm -f ./$(DEPDIR)/libcurlu_la-http_digest.Plo
	-rm -f ./$(DEPDIR)/libcurlu_la-http_negotiate.Plo
	-rm -f ./$(DEPDIR)/libcurlu_la-http_ntlm.Plo
	-rm -f ./$(DEPDIR)/libcurlu_la-http_proxy.Plo
	-rm -f ./$(DEPDIR)/libcurlu_la-idn_win32.Plo
	-rm -f ./$(DEPDIR)/libcurlu_la-if2ip.Plo
4250
4251
4252
4253
4254
4255
4256

4257
4258
4259
4260
4261
4262
4263

maintainer-clean: maintainer-clean-am
		-rm -f ./$(DEPDIR)/libcurl_la-altsvc.Plo
	-rm -f ./$(DEPDIR)/libcurl_la-amigaos.Plo
	-rm -f ./$(DEPDIR)/libcurl_la-asyn-ares.Plo
	-rm -f ./$(DEPDIR)/libcurl_la-asyn-thread.Plo
	-rm -f ./$(DEPDIR)/libcurl_la-base64.Plo

	-rm -f ./$(DEPDIR)/libcurl_la-conncache.Plo
	-rm -f ./$(DEPDIR)/libcurl_la-connect.Plo
	-rm -f ./$(DEPDIR)/libcurl_la-content_encoding.Plo
	-rm -f ./$(DEPDIR)/libcurl_la-cookie.Plo
	-rm -f ./$(DEPDIR)/libcurl_la-curl_addrinfo.Plo
	-rm -f ./$(DEPDIR)/libcurl_la-curl_ctype.Plo
	-rm -f ./$(DEPDIR)/libcurl_la-curl_des.Plo







>







4543
4544
4545
4546
4547
4548
4549
4550
4551
4552
4553
4554
4555
4556
4557

maintainer-clean: maintainer-clean-am
		-rm -f ./$(DEPDIR)/libcurl_la-altsvc.Plo
	-rm -f ./$(DEPDIR)/libcurl_la-amigaos.Plo
	-rm -f ./$(DEPDIR)/libcurl_la-asyn-ares.Plo
	-rm -f ./$(DEPDIR)/libcurl_la-asyn-thread.Plo
	-rm -f ./$(DEPDIR)/libcurl_la-base64.Plo
	-rm -f ./$(DEPDIR)/libcurl_la-c-hyper.Plo
	-rm -f ./$(DEPDIR)/libcurl_la-conncache.Plo
	-rm -f ./$(DEPDIR)/libcurl_la-connect.Plo
	-rm -f ./$(DEPDIR)/libcurl_la-content_encoding.Plo
	-rm -f ./$(DEPDIR)/libcurl_la-cookie.Plo
	-rm -f ./$(DEPDIR)/libcurl_la-curl_addrinfo.Plo
	-rm -f ./$(DEPDIR)/libcurl_la-curl_ctype.Plo
	-rm -f ./$(DEPDIR)/libcurl_la-curl_des.Plo
4299
4300
4301
4302
4303
4304
4305

4306
4307
4308
4309
4310
4311
4312
	-rm -f ./$(DEPDIR)/libcurl_la-hostip.Plo
	-rm -f ./$(DEPDIR)/libcurl_la-hostip4.Plo
	-rm -f ./$(DEPDIR)/libcurl_la-hostip6.Plo
	-rm -f ./$(DEPDIR)/libcurl_la-hostsyn.Plo
	-rm -f ./$(DEPDIR)/libcurl_la-hsts.Plo
	-rm -f ./$(DEPDIR)/libcurl_la-http.Plo
	-rm -f ./$(DEPDIR)/libcurl_la-http2.Plo

	-rm -f ./$(DEPDIR)/libcurl_la-http_chunks.Plo
	-rm -f ./$(DEPDIR)/libcurl_la-http_digest.Plo
	-rm -f ./$(DEPDIR)/libcurl_la-http_negotiate.Plo
	-rm -f ./$(DEPDIR)/libcurl_la-http_ntlm.Plo
	-rm -f ./$(DEPDIR)/libcurl_la-http_proxy.Plo
	-rm -f ./$(DEPDIR)/libcurl_la-idn_win32.Plo
	-rm -f ./$(DEPDIR)/libcurl_la-if2ip.Plo







>







4593
4594
4595
4596
4597
4598
4599
4600
4601
4602
4603
4604
4605
4606
4607
	-rm -f ./$(DEPDIR)/libcurl_la-hostip.Plo
	-rm -f ./$(DEPDIR)/libcurl_la-hostip4.Plo
	-rm -f ./$(DEPDIR)/libcurl_la-hostip6.Plo
	-rm -f ./$(DEPDIR)/libcurl_la-hostsyn.Plo
	-rm -f ./$(DEPDIR)/libcurl_la-hsts.Plo
	-rm -f ./$(DEPDIR)/libcurl_la-http.Plo
	-rm -f ./$(DEPDIR)/libcurl_la-http2.Plo
	-rm -f ./$(DEPDIR)/libcurl_la-http_aws_sigv4.Plo
	-rm -f ./$(DEPDIR)/libcurl_la-http_chunks.Plo
	-rm -f ./$(DEPDIR)/libcurl_la-http_digest.Plo
	-rm -f ./$(DEPDIR)/libcurl_la-http_negotiate.Plo
	-rm -f ./$(DEPDIR)/libcurl_la-http_ntlm.Plo
	-rm -f ./$(DEPDIR)/libcurl_la-http_proxy.Plo
	-rm -f ./$(DEPDIR)/libcurl_la-idn_win32.Plo
	-rm -f ./$(DEPDIR)/libcurl_la-if2ip.Plo
4367
4368
4369
4370
4371
4372
4373

4374
4375
4376
4377
4378
4379
4380
	-rm -f ./$(DEPDIR)/libcurl_la-wildcard.Plo
	-rm -f ./$(DEPDIR)/libcurl_la-x509asn1.Plo
	-rm -f ./$(DEPDIR)/libcurlu_la-altsvc.Plo
	-rm -f ./$(DEPDIR)/libcurlu_la-amigaos.Plo
	-rm -f ./$(DEPDIR)/libcurlu_la-asyn-ares.Plo
	-rm -f ./$(DEPDIR)/libcurlu_la-asyn-thread.Plo
	-rm -f ./$(DEPDIR)/libcurlu_la-base64.Plo

	-rm -f ./$(DEPDIR)/libcurlu_la-conncache.Plo
	-rm -f ./$(DEPDIR)/libcurlu_la-connect.Plo
	-rm -f ./$(DEPDIR)/libcurlu_la-content_encoding.Plo
	-rm -f ./$(DEPDIR)/libcurlu_la-cookie.Plo
	-rm -f ./$(DEPDIR)/libcurlu_la-curl_addrinfo.Plo
	-rm -f ./$(DEPDIR)/libcurlu_la-curl_ctype.Plo
	-rm -f ./$(DEPDIR)/libcurlu_la-curl_des.Plo







>







4662
4663
4664
4665
4666
4667
4668
4669
4670
4671
4672
4673
4674
4675
4676
	-rm -f ./$(DEPDIR)/libcurl_la-wildcard.Plo
	-rm -f ./$(DEPDIR)/libcurl_la-x509asn1.Plo
	-rm -f ./$(DEPDIR)/libcurlu_la-altsvc.Plo
	-rm -f ./$(DEPDIR)/libcurlu_la-amigaos.Plo
	-rm -f ./$(DEPDIR)/libcurlu_la-asyn-ares.Plo
	-rm -f ./$(DEPDIR)/libcurlu_la-asyn-thread.Plo
	-rm -f ./$(DEPDIR)/libcurlu_la-base64.Plo
	-rm -f ./$(DEPDIR)/libcurlu_la-c-hyper.Plo
	-rm -f ./$(DEPDIR)/libcurlu_la-conncache.Plo
	-rm -f ./$(DEPDIR)/libcurlu_la-connect.Plo
	-rm -f ./$(DEPDIR)/libcurlu_la-content_encoding.Plo
	-rm -f ./$(DEPDIR)/libcurlu_la-cookie.Plo
	-rm -f ./$(DEPDIR)/libcurlu_la-curl_addrinfo.Plo
	-rm -f ./$(DEPDIR)/libcurlu_la-curl_ctype.Plo
	-rm -f ./$(DEPDIR)/libcurlu_la-curl_des.Plo
4416
4417
4418
4419
4420
4421
4422

4423
4424
4425
4426
4427
4428
4429
	-rm -f ./$(DEPDIR)/libcurlu_la-hostip.Plo
	-rm -f ./$(DEPDIR)/libcurlu_la-hostip4.Plo
	-rm -f ./$(DEPDIR)/libcurlu_la-hostip6.Plo
	-rm -f ./$(DEPDIR)/libcurlu_la-hostsyn.Plo
	-rm -f ./$(DEPDIR)/libcurlu_la-hsts.Plo
	-rm -f ./$(DEPDIR)/libcurlu_la-http.Plo
	-rm -f ./$(DEPDIR)/libcurlu_la-http2.Plo

	-rm -f ./$(DEPDIR)/libcurlu_la-http_chunks.Plo
	-rm -f ./$(DEPDIR)/libcurlu_la-http_digest.Plo
	-rm -f ./$(DEPDIR)/libcurlu_la-http_negotiate.Plo
	-rm -f ./$(DEPDIR)/libcurlu_la-http_ntlm.Plo
	-rm -f ./$(DEPDIR)/libcurlu_la-http_proxy.Plo
	-rm -f ./$(DEPDIR)/libcurlu_la-idn_win32.Plo
	-rm -f ./$(DEPDIR)/libcurlu_la-if2ip.Plo







>







4712
4713
4714
4715
4716
4717
4718
4719
4720
4721
4722
4723
4724
4725
4726
	-rm -f ./$(DEPDIR)/libcurlu_la-hostip.Plo
	-rm -f ./$(DEPDIR)/libcurlu_la-hostip4.Plo
	-rm -f ./$(DEPDIR)/libcurlu_la-hostip6.Plo
	-rm -f ./$(DEPDIR)/libcurlu_la-hostsyn.Plo
	-rm -f ./$(DEPDIR)/libcurlu_la-hsts.Plo
	-rm -f ./$(DEPDIR)/libcurlu_la-http.Plo
	-rm -f ./$(DEPDIR)/libcurlu_la-http2.Plo
	-rm -f ./$(DEPDIR)/libcurlu_la-http_aws_sigv4.Plo
	-rm -f ./$(DEPDIR)/libcurlu_la-http_chunks.Plo
	-rm -f ./$(DEPDIR)/libcurlu_la-http_digest.Plo
	-rm -f ./$(DEPDIR)/libcurlu_la-http_negotiate.Plo
	-rm -f ./$(DEPDIR)/libcurlu_la-http_ntlm.Plo
	-rm -f ./$(DEPDIR)/libcurlu_la-http_proxy.Plo
	-rm -f ./$(DEPDIR)/libcurlu_la-idn_win32.Plo
	-rm -f ./$(DEPDIR)/libcurlu_la-if2ip.Plo
Changes to jni/curl/lib/Makefile.inc.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23



24



25



26
27
28



29
30





31




32


33
34
35





36


37




38
39



40
41































42



43
44




















45










46






47
48
49

50
51




52
53





54
55
56
57
58












59

60

61





62






63





















































64
65
66
67
68
69
70
71









72



















73
74
75
76
77
78






79



80








81









82
83
84
85
86
87
88
89
90
#***************************************************************************
#                                  _   _ ____  _
#  Project                     ___| | | |  _ \| |
#                             / __| | | | |_) | |
#                            | (__| |_| |  _ <| |___
#                             \___|\___/|_| \_\_____|
#
# Copyright (C) 1998 - 2020, 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 https://curl.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_VAUTH_CFILES = vauth/cleartext.c vauth/cram.c vauth/digest.c             \



  vauth/digest_sspi.c vauth/krb5_gssapi.c vauth/krb5_sspi.c vauth/ntlm.c     \



  vauth/ntlm_sspi.c vauth/oauth2.c vauth/spnego_gssapi.c vauth/spnego_sspi.c \



  vauth/vauth.c

LIB_VAUTH_HFILES = vauth/digest.h vauth/ntlm.h vauth/vauth.h




LIB_VTLS_CFILES = vtls/bearssl.c vtls/gskit.c vtls/gtls.c vtls/keylog.c  \





  vtls/mbedtls.c vtls/mbedtls_threadlock.c vtls/mesalink.c vtls/nss.c    \




  vtls/openssl.c vtls/schannel.c vtls/schannel_verify.c vtls/sectransp.c \


  vtls/vtls.c vtls/wolfssl.c

LIB_VTLS_HFILES = vtls/bearssl.h vtls/gskit.h vtls/gtls.h vtls/keylog.h      \





  vtls/mbedtls.h vtls/mbedtls_threadlock.h vtls/mesalink.h vtls/nssg.h       \


  vtls/openssl.h vtls/schannel.h vtls/sectransp.h vtls/vtls.h vtls/wolfssl.h





LIB_VQUIC_CFILES = vquic/ngtcp2.c vquic/quiche.c vquic/vquic.c




LIB_VQUIC_HFILES = vquic/ngtcp2.h vquic/quiche.h vquic/vquic.h



































LIB_VSSH_CFILES = vssh/libssh.c vssh/libssh2.c vssh/wolfssh.c





















LIB_VSSH_HFILES = vssh/ssh.h

















LIB_CFILES = altsvc.c amigaos.c asyn-ares.c asyn-thread.c base64.c            \
  conncache.c connect.c content_encoding.c cookie.c curl_addrinfo.c           \
  curl_ctype.c curl_des.c curl_endian.c curl_fnmatch.c curl_get_line.c        \

  curl_gethostname.c curl_gssapi.c curl_memrchr.c curl_multibyte.c            \
  curl_ntlm_core.c curl_ntlm_wb.c curl_path.c curl_range.c curl_rtmp.c        \




  curl_sasl.c curl_sspi.c curl_threads.c dict.c dotdot.c easy.c escape.c      \
  file.c fileinfo.c formdata.c ftp.c url.c ftplistparser.c getenv.c getinfo.c \





  gopher.c hash.c hmac.c hostasyn.c hostcheck.c hostip.c hostip4.c hostip6.c  \
  hostsyn.c http.c http2.c http_chunks.c http_digest.c http_negotiate.c       \
  http_ntlm.c http_proxy.c idn_win32.c if2ip.c imap.c inet_ntop.c inet_pton.c \
  krb5.c ldap.c llist.c md4.c md5.c memdebug.c mime.c mprintf.c mqtt.c        \
  multi.c netrc.c non-ascii.c nonblock.c openldap.c parsedate.c pingpong.c    \












  pop3.c progress.c psl.c doh.c rand.c rename.c rtsp.c select.c               \

  sendf.c setopt.c sha256.c share.c slist.c smb.c smtp.c socketpair.c socks.c \

  socks_gssapi.c socks_sspi.c speedcheck.c splay.c strcase.c strdup.c         \





  strerror.c strtok.c strtoofft.c system_win32.c telnet.c tftp.c timeval.c    \






  transfer.c urlapi.c version.c warnless.c wildcard.c x509asn1.c dynbuf.c     \





















































  version_win32.c easyoptions.c easygetopt.c hsts.c

LIB_HFILES = altsvc.h amigaos.h arpa_telnet.h asyn.h conncache.h connect.h    \
  content_encoding.h cookie.h curl_addrinfo.h curl_base64.h curl_ctype.h      \
  curl_des.h curl_endian.h curl_fnmatch.h curl_get_line.h curl_gethostname.h  \
  curl_gssapi.h curl_hmac.h curl_ldap.h curl_md4.h curl_md5.h curl_memory.h   \
  curl_memrchr.h curl_multibyte.h curl_ntlm_core.h curl_ntlm_wb.h curl_path.h \
  curl_printf.h curl_range.h curl_rtmp.h curl_sasl.h curl_krb5.h curl_setup.h \









  curl_setup_once.h curl_sha256.h curl_sspi.h curl_threads.h curlx.h dict.h   \



















  dotdot.h easyif.h escape.h file.h fileinfo.h formdata.h ftp.h url.h         \
  ftplistparser.h getinfo.h gopher.h hash.h hostcheck.h hostip.h http.h       \
  http2.h http_chunks.h http_digest.h http_negotiate.h http_ntlm.h            \
  http_proxy.h if2ip.h imap.h inet_ntop.h inet_pton.h llist.h memdebug.h      \
  mime.h mqtt.h multihandle.h multiif.h netrc.h non-ascii.h nonblock.h        \
  parsedate.h pingpong.h pop3.h progress.h psl.h doh.h quic.h rand.h rename.h \






  rtsp.h select.h sendf.h setopt.h setup-vms.h share.h sigpipe.h slist.h      \



  smb.h smtp.h sockaddr.h socketpair.h socks.h speedcheck.h splay.h strcase.h \








  strdup.h strerror.h strtok.h strtoofft.h system_win32.h telnet.h tftp.h     \









  timeval.h transfer.h urlapi-int.h urldata.h warnless.h wildcard.h           \
  x509asn1.h dynbuf.h version_win32.h easyoptions.h hsts.h

LIB_RCFILES = libcurl.rc

CSOURCES = $(LIB_CFILES) $(LIB_VAUTH_CFILES) $(LIB_VTLS_CFILES) \
  $(LIB_VQUIC_CFILES) $(LIB_VSSH_CFILES)
HHEADERS = $(LIB_HFILES) $(LIB_VAUTH_HFILES) $(LIB_VTLS_HFILES) \
  $(LIB_VQUIC_HFILES) $(LIB_VSSH_HFILES)







|














|
>
>
>
|
>
>
>
|
>
>
>


|
>
>
>

|
>
>
>
>
>
|
>
>
>
>
|
>
>
|

|
>
>
>
>
>
|
>
>
|
>
>
>
>

|
>
>
>

|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
|
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
|
|
|
>
|
|
>
>
>
>
|
<
>
>
>
>
>
|
|
<
|
|
>
>
>
>
>
>
>
>
>
>
>
>
|
>
|
>
|
>
>
>
>
>
|
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
|
|
|
|
|
|
|
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
|
|
|
|
|
>
>
>
>
>
>
|
>
>
>
|
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
|
|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164

165
166
167
168
169
170
171

172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
#***************************************************************************
#                                  _   _ ____  _
#  Project                     ___| | | |  _ \| |
#                             / __| | | | |_) | |
#                            | (__| |_| |  _ <| |___
#                             \___|\___/|_| \_\_____|
#
# Copyright (C) 1998 - 2021, 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 https://curl.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_VAUTH_CFILES =      \
  vauth/cleartext.c     \
  vauth/cram.c          \
  vauth/digest.c        \
  vauth/digest_sspi.c   \
  vauth/krb5_gssapi.c   \
  vauth/krb5_sspi.c     \
  vauth/ntlm.c          \
  vauth/ntlm_sspi.c     \
  vauth/oauth2.c        \
  vauth/spnego_gssapi.c \
  vauth/spnego_sspi.c   \
  vauth/vauth.c

LIB_VAUTH_HFILES =      \
  vauth/digest.h        \
  vauth/ntlm.h          \
  vauth/vauth.h

LIB_VTLS_CFILES =           \
  vtls/bearssl.c            \
  vtls/gskit.c              \
  vtls/gtls.c               \
  vtls/keylog.c             \
  vtls/mbedtls.c            \
  vtls/mbedtls_threadlock.c \
  vtls/mesalink.c           \
  vtls/nss.c                \
  vtls/openssl.c            \
  vtls/schannel.c           \
  vtls/schannel_verify.c    \
  vtls/sectransp.c          \
  vtls/vtls.c               \
  vtls/wolfssl.c

LIB_VTLS_HFILES =           \
  vtls/bearssl.h            \
  vtls/gskit.h              \
  vtls/gtls.h               \
  vtls/keylog.h             \
  vtls/mbedtls.h            \
  vtls/mbedtls_threadlock.h \
  vtls/mesalink.h           \
  vtls/nssg.h               \
  vtls/openssl.h            \
  vtls/schannel.h           \
  vtls/sectransp.h          \
  vtls/vtls.h               \
  vtls/wolfssl.h

LIB_VQUIC_CFILES = \
  vquic/ngtcp2.c   \
  vquic/quiche.c   \
  vquic/vquic.c

LIB_VQUIC_HFILES = \
  vquic/ngtcp2.h   \
  vquic/quiche.h   \
  vquic/vquic.h

LIB_VSSH_CFILES =  \
  vssh/libssh.c    \
  vssh/libssh2.c   \
  vssh/wolfssh.c

LIB_VSSH_HFILES =  \
  vssh/ssh.h

LIB_CFILES =         \
  altsvc.c           \
  amigaos.c          \
  asyn-ares.c        \
  asyn-thread.c      \
  base64.c           \
  c-hyper.c          \
  conncache.c        \
  connect.c          \
  content_encoding.c \
  cookie.c           \
  curl_addrinfo.c    \
  curl_ctype.c       \
  curl_des.c         \
  curl_endian.c      \
  curl_fnmatch.c     \
  curl_get_line.c    \
  curl_gethostname.c \
  curl_gssapi.c      \
  curl_memrchr.c     \
  curl_multibyte.c   \
  curl_ntlm_core.c   \
  curl_ntlm_wb.c     \
  curl_path.c        \
  curl_range.c       \
  curl_rtmp.c        \
  curl_sasl.c        \
  curl_sspi.c        \
  curl_threads.c     \
  dict.c             \
  doh.c              \
  dotdot.c           \
  dynbuf.c           \
  easy.c             \
  easygetopt.c       \
  easyoptions.c      \
  escape.c           \
  file.c             \
  fileinfo.c         \
  formdata.c         \
  ftp.c              \
  ftplistparser.c    \
  getenv.c           \
  getinfo.c          \
  gopher.c           \
  hash.c             \
  hmac.c             \
  hostasyn.c         \
  hostcheck.c        \
  hostip.c           \
  hostip4.c          \
  hostip6.c          \
  hostsyn.c          \
  hsts.c             \
  http.c             \
  http2.c            \
  http_chunks.c      \
  http_digest.c      \
  http_negotiate.c   \
  http_ntlm.c        \
  http_proxy.c       \
  http_aws_sigv4.c   \
  idn_win32.c        \
  if2ip.c            \
  imap.c             \
  inet_ntop.c        \
  inet_pton.c        \
  krb5.c             \
  ldap.c             \
  llist.c            \
  md4.c              \
  md5.c              \
  memdebug.c         \
  mime.c             \

  mprintf.c          \
  mqtt.c             \
  multi.c            \
  netrc.c            \
  non-ascii.c        \
  nonblock.c         \
  openldap.c         \

  parsedate.c        \
  pingpong.c         \
  pop3.c             \
  progress.c         \
  psl.c              \
  rand.c             \
  rename.c           \
  rtsp.c             \
  select.c           \
  sendf.c            \
  setopt.c           \
  sha256.c           \
  share.c            \
  slist.c            \
  smb.c              \
  smtp.c             \
  socketpair.c       \
  socks.c            \
  socks_gssapi.c     \
  socks_sspi.c       \
  speedcheck.c       \
  splay.c            \
  strcase.c          \
  strdup.c           \
  strerror.c         \
  strtok.c           \
  strtoofft.c        \
  system_win32.c     \
  telnet.c           \
  tftp.c             \
  timeval.c          \
  transfer.c         \
  url.c              \
  urlapi.c           \
  version.c          \
  version_win32.c    \
  warnless.c         \
  wildcard.c         \
  x509asn1.c

LIB_HFILES =         \
  altsvc.h           \
  amigaos.h          \
  arpa_telnet.h      \
  asyn.h             \
  c-hyper.h          \
  conncache.h        \
  connect.h          \
  content_encoding.h \
  cookie.h           \
  curl_addrinfo.h    \
  curl_base64.h      \
  curl_ctype.h       \
  curl_des.h         \
  curl_endian.h      \
  curl_fnmatch.h     \
  curl_get_line.h    \
  curl_gethostname.h \
  curl_gssapi.h      \
  curl_hmac.h        \
  curl_krb5.h        \
  curl_ldap.h        \
  curl_md4.h         \
  curl_md5.h         \
  curl_memory.h      \
  curl_memrchr.h     \
  curl_multibyte.h   \
  curl_ntlm_core.h   \
  curl_ntlm_wb.h     \
  curl_path.h        \
  curl_printf.h      \
  curl_range.h       \
  curl_rtmp.h        \
  curl_sasl.h        \
  curl_setup.h       \
  curl_setup_once.h  \
  curl_sha256.h      \
  curl_sspi.h        \
  curl_threads.h     \
  curlx.h            \
  dict.h             \
  doh.h              \
  dotdot.h           \
  dynbuf.h           \
  easyif.h           \
  easyoptions.h      \
  escape.h           \
  file.h             \
  fileinfo.h         \
  formdata.h         \
  ftp.h              \
  ftplistparser.h    \
  getinfo.h          \
  gopher.h           \
  hash.h             \
  hostcheck.h        \
  hostip.h           \
  hsts.h             \
  http.h             \
  http2.h            \
  http_chunks.h      \
  http_digest.h      \
  http_negotiate.h   \
  http_ntlm.h        \
  http_proxy.h       \
  http_aws_sigv4.h   \
  if2ip.h            \
  imap.h             \
  inet_ntop.h        \
  inet_pton.h        \
  llist.h            \
  memdebug.h         \
  mime.h             \
  mqtt.h             \
  multihandle.h      \
  multiif.h          \
  netrc.h            \
  non-ascii.h        \
  nonblock.h         \
  parsedate.h        \
  pingpong.h         \
  pop3.h             \
  progress.h         \
  psl.h              \
  quic.h             \
  rand.h             \
  rename.h           \
  rtsp.h             \
  select.h           \
  sendf.h            \
  setopt.h           \
  setup-vms.h        \
  share.h            \
  sigpipe.h          \
  slist.h            \
  smb.h              \
  smtp.h             \
  sockaddr.h         \
  socketpair.h       \
  socks.h            \
  speedcheck.h       \
  splay.h            \
  strcase.h          \
  strdup.h           \
  strerror.h         \
  strtok.h           \
  strtoofft.h        \
  system_win32.h     \
  telnet.h           \
  tftp.h             \
  timeval.h          \
  transfer.h         \
  url.h              \
  urlapi-int.h       \
  urldata.h          \
  version_win32.h    \
  warnless.h         \
  wildcard.h         \
  x509asn1.h

LIB_RCFILES = libcurl.rc

CSOURCES = $(LIB_CFILES) $(LIB_VAUTH_CFILES) $(LIB_VTLS_CFILES) \
  $(LIB_VQUIC_CFILES) $(LIB_VSSH_CFILES)
HHEADERS = $(LIB_HFILES) $(LIB_VAUTH_HFILES) $(LIB_VTLS_HFILES) \
  $(LIB_VQUIC_HFILES) $(LIB_VSSH_HFILES)
Changes to jni/curl/lib/asyn-ares.c.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2020, 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 https://curl.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







|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2021, 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 https://curl.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
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
{
#ifdef CARES_HAVE_ARES_LIBRARY_CLEANUP
  ares_library_cleanup();
#endif
}


static void Curl_ares_sock_state_cb(void *data, ares_socket_t socket_fd,
                                    int readable, int writable)
{
  struct Curl_easy *easy = data;
  if(!readable && !writable) {
    DEBUGASSERT(easy);
    Curl_multi_closed(easy, socket_fd);
  }
}

/*
 * 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.
 */
CURLcode Curl_resolver_init(struct Curl_easy *easy, void **resolver)
{
  int status;
  struct ares_options options;
  int optmask = ARES_OPT_SOCK_STATE_CB;
  options.sock_state_cb = Curl_ares_sock_state_cb;
  options.sock_state_cb_data = easy;
  status = ares_init_options((ares_channel*)resolver, &options, optmask);
  if(status != ARES_SUCCESS) {
    if(status == ARES_ENOMEM)
      return CURLE_OUT_OF_MEMORY;
    else
      return CURLE_FAILED_INIT;







|
|




















|







129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
{
#ifdef CARES_HAVE_ARES_LIBRARY_CLEANUP
  ares_library_cleanup();
#endif
}


static void sock_state_cb(void *data, ares_socket_t socket_fd,
                          int readable, int writable)
{
  struct Curl_easy *easy = data;
  if(!readable && !writable) {
    DEBUGASSERT(easy);
    Curl_multi_closed(easy, socket_fd);
  }
}

/*
 * 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.
 */
CURLcode Curl_resolver_init(struct Curl_easy *easy, void **resolver)
{
  int status;
  struct ares_options options;
  int optmask = ARES_OPT_SOCK_STATE_CB;
  options.sock_state_cb = sock_state_cb;
  options.sock_state_cb_data = easy;
  status = ares_init_options((ares_channel*)resolver, &options, optmask);
  if(status != ARES_SUCCESS) {
    if(status == ARES_ENOMEM)
      return CURLE_OUT_OF_MEMORY;
    else
      return CURLE_FAILED_INIT;
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
}

static void destroy_async_data(struct Curl_async *async);

/*
 * Cancel all possibly still on-going resolves for this connection.
 */
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);
}

/*
 * We're equivalent to Curl_resolver_cancel() for the c-ares resolver.  We
 * never block.
 */
void Curl_resolver_kill(struct connectdata *conn)
{
  /* We don't need to check the resolver state because we can be called safely
     at any time and we always do the same thing. */
  Curl_resolver_cancel(conn);
}

/*
 * destroy_async_data() cleans up async resolver data.
 */
static void destroy_async_data(struct Curl_async *async)
{







|

|
|
|






|



|







200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
}

static void destroy_async_data(struct Curl_async *async);

/*
 * Cancel all possibly still on-going resolves for this connection.
 */
void Curl_resolver_cancel(struct Curl_easy *data)
{
  if(data && data->state.async.resolver)
    ares_cancel((ares_channel)data->state.async.resolver);
  destroy_async_data(&data->state.async);
}

/*
 * We're equivalent to Curl_resolver_cancel() for the c-ares resolver.  We
 * never block.
 */
void Curl_resolver_kill(struct Curl_easy *data)
{
  /* We don't need to check the resolver state because we can be called safely
     at any time and we always do the same thing. */
  Curl_resolver_cancel(data);
}

/*
 * destroy_async_data() cleans up async resolver data.
 */
static void destroy_async_data(struct Curl_async *async)
{
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
 * (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
 */

int Curl_resolver_getsock(struct connectdata *conn,
                          curl_socket_t *socks)
{
  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, MAX_SOCKSPEREASYHANDLE);

  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(conn->data, milli, EXPIRE_ASYNC_NAME);

  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, timediff_t timeout_ms)
{
  struct Curl_easy *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];







|






|





|




|














|

<







|







249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290

291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
 * (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
 */

int Curl_resolver_getsock(struct Curl_easy *data,
                          curl_socket_t *socks)
{
  struct timeval maxtime;
  struct timeval timebuf;
  struct timeval *timeout;
  long milli;
  int max = ares_getsock((ares_channel)data->state.async.resolver,
                         (ares_socket_t *)socks, MAX_SOCKSPEREASYHANDLE);

  maxtime.tv_sec = CURL_TIMEOUT_RESOLVE;
  maxtime.tv_usec = 0;

  timeout = ares_timeout((ares_channel)data->state.async.resolver, &maxtime,
                         &timebuf);
  milli = (timeout->tv_sec * 1000) + (timeout->tv_usec/1000);
  if(milli == 0)
    milli += 10;
  Curl_expire(data, milli, EXPIRE_ASYNC_NAME);

  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 Curl_easy *data, timediff_t timeout_ms)
{

  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.async.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];
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391

392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
    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.
 */
CURLcode Curl_resolver_is_resolved(struct connectdata *conn,
                                   struct Curl_dns_entry **dns)
{
  struct Curl_easy *data = conn->data;
  struct thread_data *res = conn->async.tdata;
  CURLcode result = CURLE_OK;

  DEBUGASSERT(dns);
  *dns = NULL;

  waitperform(conn, 0);

  /* Now that we've checked for any last minute results above, see if there are
     any responses still pending when the EXPIRE_HAPPY_EYEBALLS_DNS timer
     expires. */
  if(res
     && res->num_pending
     /* This is only set to non-zero if the timer was started. */
     && (res->happy_eyeballs_dns_time.tv_sec
         || res->happy_eyeballs_dns_time.tv_usec)
     && (Curl_timediff(Curl_now(), res->happy_eyeballs_dns_time)
         >= HAPPY_EYEBALLS_DNS_TIMEOUT)) {
    /* Remember that the EXPIRE_HAPPY_EYEBALLS_DNS timer is no longer
       running. */
    memset(
      &res->happy_eyeballs_dns_time, 0, sizeof(res->happy_eyeballs_dns_time));

    /* Cancel the raw c-ares request, which will fire query_completed_cb() with
       ARES_ECANCELLED synchronously for all pending responses.  This will
       leave us with res->num_pending == 0, which is perfect for the next
       block. */
    ares_cancel((ares_channel)data->state.resolver);
    DEBUGASSERT(res->num_pending == 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".
 *
 * 'entry' MUST be non-NULL.
 *
 * Returns CURLE_COULDNT_RESOLVE_HOST if the host was not resolved,
 * CURLE_OPERATION_TIMEDOUT if a time-out occurred, or other errors.
 */
CURLcode Curl_resolver_wait_resolv(struct connectdata *conn,
                                   struct Curl_dns_entry **entry)
{
  CURLcode result = CURLE_OK;
  struct Curl_easy *data = conn->data;
  timediff_t timeout;
  struct curltime now = Curl_now();

  DEBUGASSERT(entry);
  *entry = NULL; /* clear on entry */

  timeout = Curl_timeleft(data, &now, TRUE);
  if(timeout < 0) {
    /* already expired! */
    connclose(conn, "Timed out before name resolve started");
    return CURLE_OPERATION_TIMEDOUT;
  }
  if(!timeout)
    timeout = CURL_TIMEOUT_RESOLVE * 1000; /* default name resolve timeout */

  /* Wait for the name resolve query to complete. */
  while(!result) {
    struct timeval *tvp, tv, store;
    int itimeout;
    timediff_t timeout_ms;

#if TIMEDIFF_T_MAX > INT_MAX
    itimeout = (timeout > INT_MAX) ? INT_MAX : (int)timeout;
#else
    itimeout = (int)timeout;
#endif

    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 = (timediff_t)(tvp->tv_usec/1000);
    else
      timeout_ms = 1000;

    waitperform(conn, timeout_ms);
    result = Curl_resolver_is_resolved(conn, entry);

    if(result || conn->async.done)
      break;

    if(Curl_pgrsUpdate(conn))
      result = CURLE_ABORTED_BY_CALLBACK;
    else {
      struct curltime now2 = Curl_now();
      timediff_t timediff = Curl_timediff(now2, now); /* spent time */
      if(timediff <= 0)
        timeout -= 1; /* always deduct at least 1 */
      else if(timediff > timeout)
        timeout = -1;
      else
        timeout -= timediff;
      now = now2; /* for next loop */
    }
    if(timeout < 0)
      result = CURLE_OPERATION_TIMEDOUT;
  }
  if(result)
    /* failure, so we cancel the ares operation */
    ares_cancel((ares_channel)data->state.resolver);

  /* 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. */
    connclose(conn, "c-ares resolve failed");

  return result;
}

/* Connects results to the list */
static void compound_results(struct thread_data *res,
                             struct Curl_addrinfo *ai)







|




|















|


<
|





|




















|




|




|

|
>
|



|

|
















|



<









|




















|









|
|

|


|

















|




|




|







319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349

350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417

418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
    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.async.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.async.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.
 */
CURLcode Curl_resolver_is_resolved(struct Curl_easy *data,
                                   struct Curl_dns_entry **dns)
{

  struct thread_data *res = data->state.async.tdata;
  CURLcode result = CURLE_OK;

  DEBUGASSERT(dns);
  *dns = NULL;

  waitperform(data, 0);

  /* Now that we've checked for any last minute results above, see if there are
     any responses still pending when the EXPIRE_HAPPY_EYEBALLS_DNS timer
     expires. */
  if(res
     && res->num_pending
     /* This is only set to non-zero if the timer was started. */
     && (res->happy_eyeballs_dns_time.tv_sec
         || res->happy_eyeballs_dns_time.tv_usec)
     && (Curl_timediff(Curl_now(), res->happy_eyeballs_dns_time)
         >= HAPPY_EYEBALLS_DNS_TIMEOUT)) {
    /* Remember that the EXPIRE_HAPPY_EYEBALLS_DNS timer is no longer
       running. */
    memset(
      &res->happy_eyeballs_dns_time, 0, sizeof(res->happy_eyeballs_dns_time));

    /* Cancel the raw c-ares request, which will fire query_completed_cb() with
       ARES_ECANCELLED synchronously for all pending responses.  This will
       leave us with res->num_pending == 0, which is perfect for the next
       block. */
    ares_cancel((ares_channel)data->state.async.resolver);
    DEBUGASSERT(res->num_pending == 0);
  }

  if(res && !res->num_pending) {
    (void)Curl_addrinfo_callback(data, 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(!data->state.async.dns) {
      failf(data, "Could not resolve: %s (%s)",
            data->state.async.hostname,
            ares_strerror(data->state.async.status));
      result = data->conn->bits.proxy?CURLE_COULDNT_RESOLVE_PROXY:
        CURLE_COULDNT_RESOLVE_HOST;
    }
    else
      *dns = data->state.async.dns;

    destroy_async_data(&data->state.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".
 *
 * 'entry' MUST be non-NULL.
 *
 * Returns CURLE_COULDNT_RESOLVE_HOST if the host was not resolved,
 * CURLE_OPERATION_TIMEDOUT if a time-out occurred, or other errors.
 */
CURLcode Curl_resolver_wait_resolv(struct Curl_easy *data,
                                   struct Curl_dns_entry **entry)
{
  CURLcode result = CURLE_OK;

  timediff_t timeout;
  struct curltime now = Curl_now();

  DEBUGASSERT(entry);
  *entry = NULL; /* clear on entry */

  timeout = Curl_timeleft(data, &now, TRUE);
  if(timeout < 0) {
    /* already expired! */
    connclose(data->conn, "Timed out before name resolve started");
    return CURLE_OPERATION_TIMEDOUT;
  }
  if(!timeout)
    timeout = CURL_TIMEOUT_RESOLVE * 1000; /* default name resolve timeout */

  /* Wait for the name resolve query to complete. */
  while(!result) {
    struct timeval *tvp, tv, store;
    int itimeout;
    timediff_t timeout_ms;

#if TIMEDIFF_T_MAX > INT_MAX
    itimeout = (timeout > INT_MAX) ? INT_MAX : (int)timeout;
#else
    itimeout = (int)timeout;
#endif

    store.tv_sec = itimeout/1000;
    store.tv_usec = (itimeout%1000)*1000;

    tvp = ares_timeout((ares_channel)data->state.async.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 = (timediff_t)(tvp->tv_usec/1000);
    else
      timeout_ms = 1000;

    waitperform(data, timeout_ms);
    result = Curl_resolver_is_resolved(data, entry);

    if(result || data->state.async.done)
      break;

    if(Curl_pgrsUpdate(data))
      result = CURLE_ABORTED_BY_CALLBACK;
    else {
      struct curltime now2 = Curl_now();
      timediff_t timediff = Curl_timediff(now2, now); /* spent time */
      if(timediff <= 0)
        timeout -= 1; /* always deduct at least 1 */
      else if(timediff > timeout)
        timeout = -1;
      else
        timeout -= timediff;
      now = now2; /* for next loop */
    }
    if(timeout < 0)
      result = CURLE_OPERATION_TIMEDOUT;
  }
  if(result)
    /* failure, so we cancel the ares operation */
    ares_cancel((ares_channel)data->state.async.resolver);

  /* Operation complete, if the lookup was successful we now have the entry
     in the cache. */
  if(entry)
    *entry = data->state.async.dns;

  if(result)
    /* close the connection, since we can't return failure here without
       cleaning up this connection properly. */
    connclose(data->conn, "c-ares resolve failed");

  return result;
}

/* Connects results to the list */
static void compound_results(struct thread_data *res,
                             struct Curl_addrinfo *ai)
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
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 thread_data *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 = conn->async.tdata;
  if(res) {
    res->num_pending--;

    if(CURL_ASYNC_SUCCESS == status) {
      struct 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;







|











|




|







519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
static void query_completed_cb(void *arg,  /* (struct connectdata *) */
                               int status,
#ifdef HAVE_CARES_CALLBACK_TIMEOUTS
                               int timeouts,
#endif
                               struct hostent *hostent)
{
  struct Curl_easy *data = (struct Curl_easy *)arg;
  struct thread_data *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 = data->state.async.tdata;
  if(res) {
    res->num_pending--;

    if(CURL_ASYNC_SUCCESS == status) {
      struct Curl_addrinfo *ai = Curl_he2ai(hostent, data->state.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;
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697

698
699
700
701
702
703
704
705
         request, which seems bearable.  The downside is that c-ares might race
         with us to issue one more retry just before we give up, but it seems
         better to "waste" that request instead of trying to guess the perfect
         timeout to prevent it.  After all, we don't even know where in the
         c-ares retry cycle each request is.
      */
      res->happy_eyeballs_dns_time = Curl_now();
      Curl_expire(
        conn->data, HAPPY_EYEBALLS_DNS_TIMEOUT, EXPIRE_HAPPY_EYEBALLS_DNS);
    }
  }
}

/*
 * 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.
 */
struct Curl_addrinfo *Curl_resolver_getaddrinfo(struct connectdata *conn,
                                                const char *hostname,
                                                int port,
                                                int *waitp)
{
  char *bufp;
  struct Curl_easy *data = conn->data;
  int family = PF_INET;

  *waitp = 0; /* default to synchronous response */

#ifdef ENABLE_IPV6
  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 /* ENABLE_IPV6 */

  bufp = strdup(hostname);
  if(bufp) {
    struct thread_data *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 thread_data), 1);
    if(!res) {
      free(conn->async.hostname);
      conn->async.hostname = NULL;
      return NULL;
    }
    conn->async.tdata = res;

    /* initial status - failed */
    res->last_status = ARES_ENOTFOUND;
#ifdef ENABLE_IPV6
    if(family == PF_UNSPEC) {
      if(Curl_ipv6works(conn)) {
        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 /* ENABLE_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 */
}








|
|












|





<





|



















|
|
|
|
|
|


|
|


|





|



|
|
|
|





|
|








|
>
|







601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627

628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
         request, which seems bearable.  The downside is that c-ares might race
         with us to issue one more retry just before we give up, but it seems
         better to "waste" that request instead of trying to guess the perfect
         timeout to prevent it.  After all, we don't even know where in the
         c-ares retry cycle each request is.
      */
      res->happy_eyeballs_dns_time = Curl_now();
      Curl_expire(data, HAPPY_EYEBALLS_DNS_TIMEOUT,
                  EXPIRE_HAPPY_EYEBALLS_DNS);
    }
  }
}

/*
 * 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.
 */
struct Curl_addrinfo *Curl_resolver_getaddrinfo(struct Curl_easy *data,
                                                const char *hostname,
                                                int port,
                                                int *waitp)
{
  char *bufp;

  int family = PF_INET;

  *waitp = 0; /* default to synchronous response */

#ifdef ENABLE_IPV6
  switch(data->set.ipver) {
  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 /* ENABLE_IPV6 */

  bufp = strdup(hostname);
  if(bufp) {
    struct thread_data *res = NULL;
    free(data->state.async.hostname);
    data->state.async.hostname = bufp;
    data->state.async.port = port;
    data->state.async.done = FALSE;   /* not done */
    data->state.async.status = 0;     /* clear */
    data->state.async.dns = NULL;     /* clear */
    res = calloc(sizeof(struct thread_data), 1);
    if(!res) {
      free(data->state.async.hostname);
      data->state.async.hostname = NULL;
      return NULL;
    }
    data->state.async.tdata = res;

    /* initial status - failed */
    res->last_status = ARES_ENOTFOUND;
#ifdef ENABLE_IPV6
    if(family == PF_UNSPEC) {
      if(Curl_ipv6works(data)) {
        res->num_pending = 2;

        /* areschannel is already setup in the Curl_open() function */
        ares_gethostbyname((ares_channel)data->state.async.resolver, hostname,
                            PF_INET, query_completed_cb, data);
        ares_gethostbyname((ares_channel)data->state.async.resolver, hostname,
                            PF_INET6, query_completed_cb, data);
      }
      else {
        res->num_pending = 1;

        /* areschannel is already setup in the Curl_open() function */
        ares_gethostbyname((ares_channel)data->state.async.resolver, hostname,
                            PF_INET, query_completed_cb, data);
      }
    }
    else
#endif /* ENABLE_IPV6 */
    {
      res->num_pending = 1;

      /* areschannel is already setup in the Curl_open() function */
      ares_gethostbyname((ares_channel)data->state.async.resolver,
                         hostname, family,
                         query_completed_cb, data);
    }

    *waitp = 1; /* expect asynchronous response */
  }
  return NULL; /* no struct yet */
}

716
717
718
719
720
721
722
723

724
725
726
727
728
729
730
731
732
   * it gets from the OS (for instance from /etc/resolv.conf on Linux).
   */
  if(!(servers && servers[0]))
    return CURLE_OK;

#if (ARES_VERSION >= 0x010704)
#if (ARES_VERSION >= 0x010b00)
  ares_result = ares_set_servers_ports_csv(data->state.resolver, servers);

#else
  ares_result = ares_set_servers_csv(data->state.resolver, servers);
#endif
  switch(ares_result) {
  case ARES_SUCCESS:
    result = CURLE_OK;
    break;
  case ARES_ENOMEM:
    result = CURLE_OUT_OF_MEMORY;







|
>

|







714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
   * it gets from the OS (for instance from /etc/resolv.conf on Linux).
   */
  if(!(servers && servers[0]))
    return CURLE_OK;

#if (ARES_VERSION >= 0x010704)
#if (ARES_VERSION >= 0x010b00)
  ares_result = ares_set_servers_ports_csv(data->state.async.resolver,
                                           servers);
#else
  ares_result = ares_set_servers_csv(data->state.async.resolver, servers);
#endif
  switch(ares_result) {
  case ARES_SUCCESS:
    result = CURLE_OK;
    break;
  case ARES_ENOMEM:
    result = CURLE_OUT_OF_MEMORY;
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
CURLcode Curl_set_dns_interface(struct Curl_easy *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







|







747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
CURLcode Curl_set_dns_interface(struct Curl_easy *data,
                                const char *interf)
{
#if (ARES_VERSION >= 0x010704)
  if(!interf)
    interf = "";

  ares_set_local_dev((ares_channel)data->state.async.resolver, interf);

  return CURLE_OK;
#else /* c-ares version too old! */
  (void)data;
  (void)interf;
  return CURLE_NOT_BUILT_IN;
#endif
773
774
775
776
777
778
779
780

781
782
783
784
785
786
787
  }
  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







|
>







772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
  }
  else {
    if(Curl_inet_pton(AF_INET, local_ip4, &a4) != 1) {
      return CURLE_BAD_FUNCTION_ARGUMENT;
    }
  }

  ares_set_local_ip4((ares_channel)data->state.async.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
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
  }
  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 */







|









799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
  }
  else {
    if(Curl_inet_pton(AF_INET6, local_ip6, a6) != 1) {
      return CURLE_BAD_FUNCTION_ARGUMENT;
    }
  }

  ares_set_local_ip6((ares_channel)data->state.async.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 */
Changes to jni/curl/lib/asyn-thread.c.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2020, 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 https://curl.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







|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2021, 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 https://curl.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
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
}

static void destroy_async_data(struct Curl_async *);

/*
 * Cancel all possibly still on-going resolves for this connection.
 */
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;
#ifdef USE_SOCKETPAIR
  struct connectdata *conn;
  curl_socket_t sock_pair[2]; /* socket pair */
#endif
  int sock_error;
  struct 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;
  timediff_t interval_end;
  struct thread_sync_data tsd;
};

static struct thread_sync_data *conn_thread_sync_data(struct connectdata *conn)
{
  return &(conn->async.tdata->tsd);
}

/* Destroy resolver thread synchronization data */
static
void destroy_thread_sync_data(struct thread_sync_data *tsd)
{
  if(tsd->mtx) {







|

|



|








|


<

|

















|

|







141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165

166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
}

static void destroy_async_data(struct Curl_async *);

/*
 * Cancel all possibly still on-going resolves for this connection.
 */
void Curl_resolver_cancel(struct Curl_easy *data)
{
  destroy_async_data(&data->state.async);
}

/* This function is used to init a threaded resolve */
static bool init_resolve_thread(struct Curl_easy *data,
                                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;
  int port;
  char *hostname;        /* hostname to resolve, Curl_async.hostname
                            duplicate */

#ifdef USE_SOCKETPAIR
  struct Curl_easy *data;
  curl_socket_t sock_pair[2]; /* socket pair */
#endif
  int sock_error;
  struct 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;
  timediff_t interval_end;
  struct thread_sync_data tsd;
};

static struct thread_sync_data *conn_thread_sync_data(struct Curl_easy *data)
{
  return &(data->state.async.tdata->tsd);
}

/* Destroy resolver thread synchronization data */
static
void destroy_thread_sync_data(struct thread_sync_data *tsd)
{
  if(tsd->mtx) {
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284

 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;
}







|

|


|







264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283

 err_exit:
  /* Memory allocation failed */
  destroy_thread_sync_data(tsd);
  return 0;
}

static int getaddrinfo_complete(struct Curl_easy *data)
{
  struct thread_sync_data *tsd = conn_thread_sync_data(data);
  int rc;

  rc = Curl_addrinfo_callback(data, 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;
}
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
static void destroy_async_data(struct Curl_async *async)
{
  if(async->tdata) {
    struct thread_data *td = async->tdata;
    int done;
#ifdef USE_SOCKETPAIR
    curl_socket_t sock_rd = td->tsd.sock_pair[0];
    struct connectdata *conn = td->tsd.conn;
#endif

    /*
     * 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);







|







380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
static void destroy_async_data(struct Curl_async *async)
{
  if(async->tdata) {
    struct thread_data *td = async->tdata;
    int done;
#ifdef USE_SOCKETPAIR
    curl_socket_t sock_rd = td->tsd.sock_pair[0];
    struct Curl_easy *data = td->tsd.data;
#endif

    /*
     * 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);
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438

439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
      free(async->tdata);
    }
#ifdef USE_SOCKETPAIR
    /*
     * ensure CURLMOPT_SOCKETFUNCTION fires CURL_POLL_REMOVE
     * before the FD is invalidated to avoid EBADF on EPOLL_CTL_DEL
     */
    if(conn)
      Curl_multi_closed(conn->data, sock_rd);
    sclose(sock_rd);
#endif
  }
  async->tdata = 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 = ENOMEM;


  conn->async.tdata = td;
  if(!td)
    goto errno_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)) {
    conn->async.tdata = NULL;
    free(td);
    goto errno_exit;
  }

  free(conn->async.hostname);
  conn->async.hostname = strdup(hostname);
  if(!conn->async.hostname)
    goto err_exit;

  /* The thread will set this to 1 when complete. */
  td->tsd.done = 0;

#ifdef HAVE_GETADDRINFO
  td->thread_hnd = Curl_thread_create(getaddrinfo_thread, &td->tsd);







<
|















|





>

|



|
|
|
|



|




|
|
|







408
409
410
411
412
413
414

415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
      free(async->tdata);
    }
#ifdef USE_SOCKETPAIR
    /*
     * ensure CURLMOPT_SOCKETFUNCTION fires CURL_POLL_REMOVE
     * before the FD is invalidated to avoid EBADF on EPOLL_CTL_DEL
     */

    Curl_multi_closed(data, sock_rd);
    sclose(sock_rd);
#endif
  }
  async->tdata = 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 Curl_easy *data,
                                const char *hostname, int port,
                                const struct addrinfo *hints)
{
  struct thread_data *td = calloc(1, sizeof(struct thread_data));
  int err = ENOMEM;
  struct Curl_async *asp = &data->state.async;

  data->state.async.tdata = td;
  if(!td)
    goto errno_exit;

  asp->port = port;
  asp->done = FALSE;
  asp->status = 0;
  asp->dns = NULL;
  td->thread_hnd = curl_thread_t_null;

  if(!init_thread_sync_data(td, hostname, port, hints)) {
    asp->tdata = NULL;
    free(td);
    goto errno_exit;
  }

  free(asp->hostname);
  asp->hostname = strdup(hostname);
  if(!asp->hostname)
    goto err_exit;

  /* The thread will set this to 1 when complete. */
  td->tsd.done = 0;

#ifdef HAVE_GETADDRINFO
  td->thread_hnd = Curl_thread_create(getaddrinfo_thread, &td->tsd);
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497

498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524


525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
    err = errno;
    goto err_exit;
  }

  return TRUE;

 err_exit:
  destroy_async_data(&conn->async);

 errno_exit:
  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;

#ifndef CURL_DISABLE_PROXY

  if(conn->bits.httpproxy) {
    host_or_proxy = "proxy";
    result = CURLE_COULDNT_RESOLVE_PROXY;
  }
  else
#endif
  {
    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;
}

/*
 * 'entry' may be NULL and then no data is returned
 */
static CURLcode thread_wait_resolv(struct connectdata *conn,
                                   struct Curl_dns_entry **entry,
                                   bool report)
{
  struct thread_data *td = conn->async.tdata;
  CURLcode result = CURLE_OK;



  DEBUGASSERT(conn && td);
  DEBUGASSERT(td->thread_hnd != curl_thread_t_null);

  /* wait for the thread to resolve the name */
  if(Curl_thread_join(&td->thread_hnd)) {
    if(entry)
      result = getaddrinfo_complete(conn);
  }
  else
    DEBUGASSERT(0);

  conn->async.done = TRUE;

  if(entry)
    *entry = conn->async.dns;

  if(!conn->async.dns && report)
    /* a name was not resolved, report error */
    result = resolver_error(conn);

  destroy_async_data(&conn->async);

  if(!conn->async.dns && report)
    connclose(conn, "asynch resolve failed");

  return result;
}


/*
 * Until we gain a way to signal the resolver threads to stop early, we must
 * simply wait for them and ignore their results.
 */
void Curl_resolver_kill(struct connectdata *conn)
{
  struct thread_data *td = conn->async.tdata;

  /* If we're still resolving, we must wait for the threads to fully clean up,
     unfortunately.  Otherwise, we can simply cancel to clean up any resolver
     data. */
  if(td && td->thread_hnd != curl_thread_t_null)
    (void)thread_wait_resolv(conn, NULL, FALSE);
  else
    Curl_resolver_cancel(conn);
}

/*
 * 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,
 * CURLE_OPERATION_TIMEDOUT if a time-out occurred, or other errors.
 *
 * This is the version for resolves-in-a-thread.
 */
CURLcode Curl_resolver_wait_resolv(struct connectdata *conn,
                                   struct Curl_dns_entry **entry)
{
  return thread_wait_resolv(conn, entry, TRUE);
}

/*
 * 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.
 */
CURLcode Curl_resolver_is_resolved(struct connectdata *conn,
                                   struct Curl_dns_entry **entry)
{
  struct Curl_easy *data = conn->data;
  struct thread_data *td = conn->async.tdata;
  int done = 0;

  DEBUGASSERT(entry);
  *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 */
    /* should be fine even if this converts to 32 bit */
    timediff_t elapsed = Curl_timediff(Curl_now(),
                                       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, EXPIRE_ASYNC_NAME);
  }

  return CURLE_OK;
}

int Curl_resolver_getsock(struct connectdata *conn,
                          curl_socket_t *socks)
{
  int ret_val = 0;
  timediff_t milli;
  timediff_t ms;
  struct Curl_easy *data = conn->data;
  struct resdata *reslv = (struct resdata *)data->state.resolver;
#ifdef USE_SOCKETPAIR
  struct thread_data *td = conn->async.tdata;
#else
  (void)socks;
#endif

#ifdef USE_SOCKETPAIR
  if(td) {
    /* return read fd to client for polling the DNS resolution status */
    socks[0] = td->tsd.sock_pair[0];
    DEBUGASSERT(td->tsd.conn == conn || !td->tsd.conn);
    td->tsd.conn = conn;
    ret_val = GETSOCK_READSOCK(0);
  }
  else {
#endif
    ms = Curl_timediff(Curl_now(), reslv->start);
    if(ms < 3)
      milli = 0;







|











|





>











|
|







|



|


>
>
|





|




|


|

|

|

|

|
|









|

|





|

|















|


|







|


<
|















|

|
|
|


|
|




















|





|
<




<
|

|








<
|







472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599

600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651

652
653
654
655

656
657
658
659
660
661
662
663
664
665
666

667
668
669
670
671
672
673
674
    err = errno;
    goto err_exit;
  }

  return TRUE;

 err_exit:
  destroy_async_data(asp);

 errno_exit:
  errno = err;
  return FALSE;
}

/*
 * resolver_error() calls failf() with the appropriate message after a resolve
 * error
 */

static CURLcode resolver_error(struct Curl_easy *data)
{
  const char *host_or_proxy;
  CURLcode result;

#ifndef CURL_DISABLE_PROXY
  struct connectdata *conn = data->conn;
  if(conn->bits.httpproxy) {
    host_or_proxy = "proxy";
    result = CURLE_COULDNT_RESOLVE_PROXY;
  }
  else
#endif
  {
    host_or_proxy = "host";
    result = CURLE_COULDNT_RESOLVE_HOST;
  }

  failf(data, "Could not resolve %s: %s", host_or_proxy,
        data->state.async.hostname);

  return result;
}

/*
 * 'entry' may be NULL and then no data is returned
 */
static CURLcode thread_wait_resolv(struct Curl_easy *data,
                                   struct Curl_dns_entry **entry,
                                   bool report)
{
  struct thread_data *td;
  CURLcode result = CURLE_OK;

  DEBUGASSERT(data);
  td = data->state.async.tdata;
  DEBUGASSERT(td);
  DEBUGASSERT(td->thread_hnd != curl_thread_t_null);

  /* wait for the thread to resolve the name */
  if(Curl_thread_join(&td->thread_hnd)) {
    if(entry)
      result = getaddrinfo_complete(data);
  }
  else
    DEBUGASSERT(0);

  data->state.async.done = TRUE;

  if(entry)
    *entry = data->state.async.dns;

  if(!data->state.async.dns && report)
    /* a name was not resolved, report error */
    result = resolver_error(data);

  destroy_async_data(&data->state.async);

  if(!data->state.async.dns && report)
    connclose(data->conn, "asynch resolve failed");

  return result;
}


/*
 * Until we gain a way to signal the resolver threads to stop early, we must
 * simply wait for them and ignore their results.
 */
void Curl_resolver_kill(struct Curl_easy *data)
{
  struct thread_data *td = data->state.async.tdata;

  /* If we're still resolving, we must wait for the threads to fully clean up,
     unfortunately.  Otherwise, we can simply cancel to clean up any resolver
     data. */
  if(td && td->thread_hnd != curl_thread_t_null)
    (void)thread_wait_resolv(data, NULL, FALSE);
  else
    Curl_resolver_cancel(data);
}

/*
 * 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,
 * CURLE_OPERATION_TIMEDOUT if a time-out occurred, or other errors.
 *
 * This is the version for resolves-in-a-thread.
 */
CURLcode Curl_resolver_wait_resolv(struct Curl_easy *data,
                                   struct Curl_dns_entry **entry)
{
  return thread_wait_resolv(data, entry, TRUE);
}

/*
 * 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.
 */
CURLcode Curl_resolver_is_resolved(struct Curl_easy *data,
                                   struct Curl_dns_entry **entry)
{

  struct thread_data *td = data->state.async.tdata;
  int done = 0;

  DEBUGASSERT(entry);
  *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(data);

    if(!data->state.async.dns) {
      CURLcode result = resolver_error(data);
      destroy_async_data(&data->state.async);
      return result;
    }
    destroy_async_data(&data->state.async);
    *entry = data->state.async.dns;
  }
  else {
    /* poll for name lookup done with exponential backoff up to 250ms */
    /* should be fine even if this converts to 32 bit */
    timediff_t elapsed = Curl_timediff(Curl_now(),
                                       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(data, td->poll_interval, EXPIRE_ASYNC_NAME);
  }

  return CURLE_OK;
}

int Curl_resolver_getsock(struct Curl_easy *data, curl_socket_t *socks)

{
  int ret_val = 0;
  timediff_t milli;
  timediff_t ms;

  struct resdata *reslv = (struct resdata *)data->state.async.resolver;
#ifdef USE_SOCKETPAIR
  struct thread_data *td = data->state.async.tdata;
#else
  (void)socks;
#endif

#ifdef USE_SOCKETPAIR
  if(td) {
    /* return read fd to client for polling the DNS resolution status */
    socks[0] = td->tsd.sock_pair[0];

    td->tsd.data = data;
    ret_val = GETSOCK_READSOCK(0);
  }
  else {
#endif
    ms = Curl_timediff(Curl_now(), reslv->start);
    if(ms < 3)
      milli = 0;
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
  return ret_val;
}

#ifndef HAVE_GETADDRINFO
/*
 * Curl_getaddrinfo() - for platforms without getaddrinfo
 */
struct Curl_addrinfo *Curl_resolver_getaddrinfo(struct connectdata *conn,
                                                const char *hostname,
                                                int port,
                                                int *waitp)
{
  struct Curl_easy *data = conn->data;
  struct resdata *reslv = (struct resdata *)data->state.resolver;

  *waitp = 0; /* default to synchronous response */

  reslv->start = Curl_now();

  /* fire up a new resolver thread! */
  if(init_resolve_thread(conn, hostname, port, NULL)) {
    *waitp = 1; /* expect asynchronous response */
    return NULL;
  }

  failf(conn->data, "getaddrinfo() thread failed\n");

  return NULL;
}

#else /* !HAVE_GETADDRINFO */

/*
 * Curl_resolver_getaddrinfo() - for getaddrinfo
 */
struct Curl_addrinfo *Curl_resolver_getaddrinfo(struct connectdata *conn,
                                                const char *hostname,
                                                int port,
                                                int *waitp)
{
  struct addrinfo hints;
  int pf = PF_INET;
  struct Curl_easy *data = conn->data;
  struct resdata *reslv = (struct resdata *)data->state.resolver;

  *waitp = 0; /* default to synchronous response */

#ifdef CURLRES_IPV6
  /*
   * 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(conn))
    /* 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->transport == TRNSPRT_TCP)?
    SOCK_STREAM : SOCK_DGRAM;

  reslv->start = Curl_now();
  /* fire up a new resolver thread! */
  if(init_resolve_thread(conn, hostname, port, &hints)) {
    *waitp = 1; /* expect asynchronous response */
    return NULL;
  }

  failf(data, "getaddrinfo() thread failed to start\n");
  return NULL;

}

#endif /* !HAVE_GETADDRINFO */

CURLcode Curl_set_dns_servers(struct Curl_easy *data,







|




<
|






|




|









|






<
|







|











|






|




|




|







687
688
689
690
691
692
693
694
695
696
697
698

699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727

728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
  return ret_val;
}

#ifndef HAVE_GETADDRINFO
/*
 * Curl_getaddrinfo() - for platforms without getaddrinfo
 */
struct Curl_addrinfo *Curl_resolver_getaddrinfo(struct Curl_easy *data,
                                                const char *hostname,
                                                int port,
                                                int *waitp)
{

  struct resdata *reslv = (struct resdata *)data->state.async.resolver;

  *waitp = 0; /* default to synchronous response */

  reslv->start = Curl_now();

  /* fire up a new resolver thread! */
  if(init_resolve_thread(data, hostname, port, NULL)) {
    *waitp = 1; /* expect asynchronous response */
    return NULL;
  }

  failf(data, "getaddrinfo() thread failed");

  return NULL;
}

#else /* !HAVE_GETADDRINFO */

/*
 * Curl_resolver_getaddrinfo() - for getaddrinfo
 */
struct Curl_addrinfo *Curl_resolver_getaddrinfo(struct Curl_easy *data,
                                                const char *hostname,
                                                int port,
                                                int *waitp)
{
  struct addrinfo hints;
  int pf = PF_INET;

  struct resdata *reslv = (struct resdata *)data->state.async.resolver;

  *waitp = 0; /* default to synchronous response */

#ifdef CURLRES_IPV6
  /*
   * Check if a limited name resolve has been requested.
   */
  switch(data->set.ipver) {
  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(data))
    /* 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 = (data->conn->transport == TRNSPRT_TCP)?
    SOCK_STREAM : SOCK_DGRAM;

  reslv->start = Curl_now();
  /* fire up a new resolver thread! */
  if(init_resolve_thread(data, hostname, port, &hints)) {
    *waitp = 1; /* expect asynchronous response */
    return NULL;
  }

  failf(data, "getaddrinfo() thread failed to start");
  return NULL;

}

#endif /* !HAVE_GETADDRINFO */

CURLcode Curl_set_dns_servers(struct Curl_easy *data,
Changes to jni/curl/lib/asyn.h.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#ifndef HEADER_CURL_ASYN_H
#define HEADER_CURL_ASYN_H
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2020, 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 https://curl.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









|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#ifndef HEADER_CURL_ASYN_H
#define HEADER_CURL_ASYN_H
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2021, 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 https://curl.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
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
 *
 * It is called from inside other functions to cancel currently performing
 * resolver request. Should also free any temporary resources allocated to
 * perform a request.  This never waits for resolver threads to complete.
 *
 * It is safe to call this when conn is in any state.
 */
void Curl_resolver_cancel(struct connectdata *conn);

/*
 * Curl_resolver_kill().
 *
 * This acts like Curl_resolver_cancel() except it will block until any threads
 * associated with the resolver are complete.  This never blocks for resolvers
 * that do not use threads.  This is intended to be the "last chance" function
 * that cleans up an in-progress resolver completely (before its owner is about
 * to die).
 *
 * It is safe to call this when conn is in any state.
 */
void Curl_resolver_kill(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.
 */
int Curl_resolver_getsock(struct connectdata *conn, curl_socket_t *sock);

/*
 * 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.
 */
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,
 * CURLE_OPERATION_TIMEDOUT if a time-out occurred, or other errors.
 */
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.
 */
struct 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







|












|









|










|













|













|







87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
 *
 * It is called from inside other functions to cancel currently performing
 * resolver request. Should also free any temporary resources allocated to
 * perform a request.  This never waits for resolver threads to complete.
 *
 * It is safe to call this when conn is in any state.
 */
void Curl_resolver_cancel(struct Curl_easy *data);

/*
 * Curl_resolver_kill().
 *
 * This acts like Curl_resolver_cancel() except it will block until any threads
 * associated with the resolver are complete.  This never blocks for resolvers
 * that do not use threads.  This is intended to be the "last chance" function
 * that cleans up an in-progress resolver completely (before its owner is about
 * to die).
 *
 * It is safe to call this when conn is in any state.
 */
void Curl_resolver_kill(struct Curl_easy *data);

/* 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.
 */
int Curl_resolver_getsock(struct Curl_easy *data, curl_socket_t *sock);

/*
 * 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.
 */
CURLcode Curl_resolver_is_resolved(struct Curl_easy *data,
                                   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,
 * CURLE_OPERATION_TIMEDOUT if a time-out occurred, or other errors.
 */
CURLcode Curl_resolver_wait_resolv(struct Curl_easy *data,
                                   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.
 */
struct Curl_addrinfo *Curl_resolver_getaddrinfo(struct Curl_easy *data,
                                                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
Added jni/curl/lib/c-hyper.c.
























































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2021, 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 https://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_HYPER)

#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 <hyper.h>
#include "urldata.h"
#include "sendf.h"
#include "transfer.h"
#include "multiif.h"
#include "progress.h"

/* The last 3 #include files should be in this order */
#include "curl_printf.h"
#include "curl_memory.h"
#include "memdebug.h"

size_t Curl_hyper_recv(void *userp, hyper_context *ctx,
                       uint8_t *buf, size_t buflen)
{
  struct Curl_easy *data = userp;
  struct connectdata *conn = data->conn;
  CURLcode result;
  ssize_t nread;
  DEBUGASSERT(conn);
  (void)ctx;

  result = Curl_read(data, conn->sockfd, (char *)buf, buflen, &nread);
  if(result == CURLE_AGAIN) {
    /* would block, register interest */
    if(data->hyp.read_waker)
      hyper_waker_free(data->hyp.read_waker);
    data->hyp.read_waker = hyper_context_waker(ctx);
    if(!data->hyp.read_waker) {
      failf(data, "Couldn't make the read hyper_context_waker");
      return HYPER_IO_ERROR;
    }
    return HYPER_IO_PENDING;
  }
  else if(result) {
    failf(data, "Curl_read failed");
    return HYPER_IO_ERROR;
  }
  return (size_t)nread;
}

size_t Curl_hyper_send(void *userp, hyper_context *ctx,
                       const uint8_t *buf, size_t buflen)
{
  struct Curl_easy *data = userp;
  struct connectdata *conn = data->conn;
  CURLcode result;
  ssize_t nwrote;

  result = Curl_write(data, conn->sockfd, (void *)buf, buflen, &nwrote);
  if(result == CURLE_AGAIN) {
    /* would block, register interest */
    if(data->hyp.write_waker)
      hyper_waker_free(data->hyp.write_waker);
    data->hyp.write_waker = hyper_context_waker(ctx);
    if(!data->hyp.write_waker) {
      failf(data, "Couldn't make the write hyper_context_waker");
      return HYPER_IO_ERROR;
    }
    return HYPER_IO_PENDING;
  }
  else if(result) {
    failf(data, "Curl_write failed");
    return HYPER_IO_ERROR;
  }
  return (size_t)nwrote;
}

static int hyper_each_header(void *userdata,
                             const uint8_t *name,
                             size_t name_len,
                             const uint8_t *value,
                             size_t value_len)
{
  struct Curl_easy *data = (struct Curl_easy *)userdata;
  size_t len;
  char *headp;
  CURLcode result;
  Curl_dyn_reset(&data->state.headerb);
  if(name_len) {
    if(Curl_dyn_addf(&data->state.headerb, "%.*s: %.*s\r\n",
                     (int) name_len, name, (int) value_len, value))
      return HYPER_ITER_BREAK;
  }
  else {
    if(Curl_dyn_add(&data->state.headerb, "\r\n"))
      return HYPER_ITER_BREAK;
  }
  len = Curl_dyn_len(&data->state.headerb);
  headp = Curl_dyn_ptr(&data->state.headerb);

  result = Curl_http_header(data, data->conn, headp);
  if(result) {
    data->state.hresult = result;
    return HYPER_ITER_BREAK;
  }

  Curl_debug(data, CURLINFO_HEADER_IN, headp, len);

  result = Curl_client_write(data, CLIENTWRITE_HEADER, headp, len);
  if(result) {
    data->state.hresult = CURLE_ABORTED_BY_CALLBACK;
    return HYPER_ITER_BREAK;
  }

  data->info.header_size += (long)len;
  data->req.headerbytecount += (long)len;
  return HYPER_ITER_CONTINUE;
}

static int hyper_body_chunk(void *userdata, const hyper_buf *chunk)
{
  char *buf = (char *)hyper_buf_bytes(chunk);
  size_t len = hyper_buf_len(chunk);
  struct Curl_easy *data = (struct Curl_easy *)userdata;
  struct SingleRequest *k = &data->req;
  CURLcode result;

  if(0 == k->bodywrites++) {
    bool done = FALSE;
    result = Curl_http_firstwrite(data, data->conn, &done);
    if(result || done) {
      infof(data, "Return early from hyper_body_chunk\n");
      data->state.hresult = result;
      return HYPER_ITER_BREAK;
    }
  }
  if(k->ignorebody)
    return HYPER_ITER_CONTINUE;
  Curl_debug(data, CURLINFO_DATA_IN, buf, len);
  result = Curl_client_write(data, CLIENTWRITE_BODY, buf, len);

  if(result) {
    data->state.hresult = result;
    return HYPER_ITER_BREAK;
  }

  data->req.bytecount += len;
  Curl_pgrsSetDownloadCounter(data, data->req.bytecount);
  return HYPER_ITER_CONTINUE;
}

/*
 * Hyper does not consider the status line, the first line in a HTTP/1
 * response, to be a header. The libcurl API does. This function sends the
 * status line in the header callback. */
static CURLcode status_line(struct Curl_easy *data,
                            struct connectdata *conn,
                            uint16_t http_status,
                            int http_version,
                            const uint8_t *reason, size_t rlen)
{
  CURLcode result;
  size_t wrote;
  size_t len;
  const char *vstr;
  curl_write_callback writeheader =
    data->set.fwrite_header? data->set.fwrite_header: data->set.fwrite_func;
  vstr = http_version == HYPER_HTTP_VERSION_1_1 ? "1.1" :
    (http_version == HYPER_HTTP_VERSION_2 ? "2" : "1.0");
  conn->httpversion =
    http_version == HYPER_HTTP_VERSION_1_1 ? 11 :
    (http_version == HYPER_HTTP_VERSION_2 ? 20 : 10);
  data->req.httpcode = http_status;

  result = Curl_http_statusline(data, conn);
  if(result)
    return result;

  Curl_dyn_reset(&data->state.headerb);

  result = Curl_dyn_addf(&data->state.headerb, "HTTP/%s %03d %.*s\r\n",
                         vstr,
                         (int)http_status,
                         (int)rlen, reason);
  if(result)
    return result;
  len = Curl_dyn_len(&data->state.headerb);
  Curl_debug(data, CURLINFO_HEADER_IN, Curl_dyn_ptr(&data->state.headerb),
             len);
  Curl_set_in_callback(data, true);
  wrote = writeheader(Curl_dyn_ptr(&data->state.headerb), 1, len,
                      data->set.writeheader);
  Curl_set_in_callback(data, false);
  if(wrote != len)
    return CURLE_WRITE_ERROR;

  data->info.header_size += (long)len;
  data->req.headerbytecount += (long)len;
  data->req.httpcode = http_status;
  return CURLE_OK;
}

/*
 * Hyper does not pass on the last empty response header. The libcurl API
 * does. This function sends an empty header in the header callback.
 */
static CURLcode empty_header(struct Curl_easy *data)
{
  return hyper_each_header(data, NULL, 0, NULL, 0) ?
    CURLE_WRITE_ERROR : CURLE_OK;
}

CURLcode Curl_hyper_stream(struct Curl_easy *data,
                           struct connectdata *conn,
                           int *didwhat,
                           bool *done,
                           int select_res)
{
  hyper_response *resp = NULL;
  uint16_t http_status;
  int http_version;
  hyper_headers *headers = NULL;
  hyper_body *resp_body = NULL;
  struct hyptransfer *h = &data->hyp;
  hyper_task *task;
  hyper_task *foreach;
  hyper_error *hypererr = NULL;
  const uint8_t *reasonp;
  size_t reason_len;
  CURLcode result = CURLE_OK;
  (void)conn;

  if(select_res & CURL_CSELECT_IN) {
    if(h->read_waker)
      hyper_waker_wake(h->read_waker);
    h->read_waker = NULL;
  }
  if(select_res & CURL_CSELECT_OUT) {
    if(h->write_waker)
      hyper_waker_wake(h->write_waker);
    h->write_waker = NULL;
  }

  *done = FALSE;
  do {
    hyper_task_return_type t;
    task = hyper_executor_poll(h->exec);
    if(!task) {
      *didwhat = KEEP_RECV;
      break;
    }
    t = hyper_task_type(task);
    switch(t) {
    case HYPER_TASK_ERROR:
      hypererr = hyper_task_value(task);
      break;
    case HYPER_TASK_RESPONSE:
      resp = hyper_task_value(task);
      break;
    default:
      break;
    }
    hyper_task_free(task);

    if(t == HYPER_TASK_ERROR) {
      hyper_code errnum = hyper_error_code(hypererr);
      if(errnum == HYPERE_ABORTED_BY_CALLBACK) {
        /* override Hyper's view, might not even be an error */
        result = data->state.hresult;
        infof(data, "hyperstream is done (by early callback)\n");
      }
      else {
        uint8_t errbuf[256];
        size_t errlen = hyper_error_print(hypererr, errbuf, sizeof(errbuf));
        hyper_code code = hyper_error_code(hypererr);
        failf(data, "Hyper: [%d] %.*s", (int)code, (int)errlen, errbuf);
        if((code == HYPERE_UNEXPECTED_EOF) && !data->req.bytecount)
          result = CURLE_GOT_NOTHING;
        else
          result = CURLE_RECV_ERROR;
      }
      *done = TRUE;
      hyper_error_free(hypererr);
      break;
    }
    else if(h->endtask == task) {
      /* end of transfer */
      *done = TRUE;
      infof(data, "hyperstream is done!\n");
      break;
    }
    else if(t != HYPER_TASK_RESPONSE) {
      *didwhat = KEEP_RECV;
      break;
    }
    /* HYPER_TASK_RESPONSE */

    *didwhat = KEEP_RECV;
    if(!resp) {
      failf(data, "hyperstream: couldn't get response");
      return CURLE_RECV_ERROR;
    }

    http_status = hyper_response_status(resp);
    http_version = hyper_response_version(resp);
    reasonp = hyper_response_reason_phrase(resp);
    reason_len = hyper_response_reason_phrase_len(resp);

    result = status_line(data, conn,
                         http_status, http_version, reasonp, reason_len);
    if(result)
      break;

    headers = hyper_response_headers(resp);
    if(!headers) {
      failf(data, "hyperstream: couldn't get response headers");
      result = CURLE_RECV_ERROR;
      break;
    }

    /* the headers are already received */
    hyper_headers_foreach(headers, hyper_each_header, data);
    if(data->state.hresult) {
      result = data->state.hresult;
      break;
    }

    if(empty_header(data)) {
      failf(data, "hyperstream: couldn't pass blank header");
      result = CURLE_OUT_OF_MEMORY;
      break;
    }

    /* 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(data);
    if(result)
      break;

    resp_body = hyper_response_body(resp);
    if(!resp_body) {
      failf(data, "hyperstream: couldn't get response body");
      result = CURLE_RECV_ERROR;
      break;
    }
    foreach = hyper_body_foreach(resp_body, hyper_body_chunk, data);
    if(!foreach) {
      failf(data, "hyperstream: body foreach failed");
      result = CURLE_OUT_OF_MEMORY;
      break;
    }
    DEBUGASSERT(hyper_task_type(foreach) == HYPER_TASK_EMPTY);
    if(HYPERE_OK != hyper_executor_push(h->exec, foreach)) {
      failf(data, "Couldn't hyper_executor_push the body-foreach");
      result = CURLE_OUT_OF_MEMORY;
      break;
    }
    h->endtask = foreach;

    hyper_response_free(resp);
    resp = NULL;
  } while(1);
  if(resp)
    hyper_response_free(resp);
  return result;
}

static CURLcode debug_request(struct Curl_easy *data,
                              const char *method,
                              const char *path,
                              bool h2)
{
  char *req = aprintf("%s %s HTTP/%s\r\n", method, path,
                      h2?"2":"1.1");
  if(!req)
    return CURLE_OUT_OF_MEMORY;
  Curl_debug(data, CURLINFO_HEADER_OUT, req, strlen(req));
  free(req);
  return CURLE_OK;
}

/*
 * Given a full header line "name: value" (optional CRLF in the input, should
 * be in the output), add to Hyper and send to the debug callback.
 *
 * Supports multiple headers.
 */

CURLcode Curl_hyper_header(struct Curl_easy *data, hyper_headers *headers,
                           const char *line)
{
  const char *p;
  const char *n;
  size_t nlen;
  const char *v;
  size_t vlen;
  bool newline = TRUE;
  int numh = 0;

  if(!line)
    return CURLE_OK;
  n = line;
  do {
    size_t linelen = 0;

    p = strchr(n, ':');
    if(!p)
      /* this is fine if we already added at least one header */
      return numh ? CURLE_OK : CURLE_BAD_FUNCTION_ARGUMENT;
    nlen = p - n;
    p++; /* move past the colon */
    while(*p == ' ')
      p++;
    v = p;
    p = strchr(v, '\r');
    if(!p) {
      p = strchr(v, '\n');
      if(p)
        linelen = 1; /* LF only */
      else {
        p = strchr(v, '\0');
        newline = FALSE; /* no newline */
      }
    }
    else
      linelen = 2; /* CRLF ending */
    linelen += (p - n);
    if(!n)
      return CURLE_BAD_FUNCTION_ARGUMENT;
    vlen = p - v;

    if(HYPERE_OK != hyper_headers_add(headers, (uint8_t *)n, nlen,
                                      (uint8_t *)v, vlen)) {
      failf(data, "hyper_headers_add host");
      return CURLE_OUT_OF_MEMORY;
    }
    if(data->set.verbose) {
      char *ptr = NULL;
      if(!newline) {
        ptr = aprintf("%.*s\r\n", (int)linelen, line);
        if(!ptr)
          return CURLE_OUT_OF_MEMORY;
        Curl_debug(data, CURLINFO_HEADER_OUT, ptr, linelen + 2);
        free(ptr);
      }
      else
        Curl_debug(data, CURLINFO_HEADER_OUT, (char *)line, linelen);
    }
    numh++;
    n += linelen;
  } while(newline);
  return CURLE_OK;
}

static CURLcode request_target(struct Curl_easy *data,
                               struct connectdata *conn,
                               const char *method,
                               bool h2,
                               hyper_request *req)
{
  CURLcode result;
  struct dynbuf r;

  Curl_dyn_init(&r, DYN_HTTP_REQUEST);

  result = Curl_http_target(data, conn, &r);
  if(result)
    return result;

  if(hyper_request_set_uri(req, (uint8_t *)Curl_dyn_uptr(&r),
                           Curl_dyn_len(&r))) {
    failf(data, "error setting path");
    result = CURLE_OUT_OF_MEMORY;
  }
  else
    result = debug_request(data, method, Curl_dyn_ptr(&r), h2);

  Curl_dyn_free(&r);

  return result;
}

static int uploadpostfields(void *userdata, hyper_context *ctx,
                            hyper_buf **chunk)
{
  struct Curl_easy *data = (struct Curl_easy *)userdata;
  (void)ctx;
  if(data->req.upload_done)
    *chunk = NULL; /* nothing more to deliver */
  else {
    /* send everything off in a single go */
    *chunk = hyper_buf_copy(data->set.postfields,
                            (size_t)data->req.p.http->postsize);
    data->req.upload_done = TRUE;
  }
  return HYPER_POLL_READY;
}

static int uploadstreamed(void *userdata, hyper_context *ctx,
                          hyper_buf **chunk)
{
  size_t fillcount;
  struct Curl_easy *data = (struct Curl_easy *)userdata;
  CURLcode result =
    Curl_fillreadbuffer(data, data->set.upload_buffer_size, &fillcount);
  (void)ctx;
  if(result)
    return HYPER_POLL_ERROR;
  if(!fillcount)
    /* done! */
    *chunk = NULL;
  else
    *chunk = hyper_buf_copy((uint8_t *)data->state.ulbuf, fillcount);
  return HYPER_POLL_READY;
}

/*
 * bodysend() sets up headers in the outgoing request for a HTTP transfer that
 * sends a body
 */

static CURLcode bodysend(struct Curl_easy *data,
                         struct connectdata *conn,
                         hyper_headers *headers,
                         hyper_request *hyperreq,
                         Curl_HttpReq httpreq)
{
  CURLcode result = CURLE_OK;
  struct dynbuf req;
  if((httpreq == HTTPREQ_GET) || (httpreq == HTTPREQ_HEAD))
    Curl_pgrsSetUploadSize(data, 0); /* no request body */
  else {
    hyper_body *body;
    Curl_dyn_init(&req, DYN_HTTP_REQUEST);
    result = Curl_http_bodysend(data, conn, &req, httpreq);

    if(!result)
      result = Curl_hyper_header(data, headers, Curl_dyn_ptr(&req));

    Curl_dyn_free(&req);

    body = hyper_body_new();
    hyper_body_set_userdata(body, data);
    if(data->set.postfields)
      hyper_body_set_data_func(body, uploadpostfields);
    else {
      result = Curl_get_upload_buffer(data);
      if(result)
        return result;
      /* init the "upload from here" pointer */
      data->req.upload_fromhere = data->state.ulbuf;
      hyper_body_set_data_func(body, uploadstreamed);
    }
    if(HYPERE_OK != hyper_request_set_body(hyperreq, body)) {
      /* fail */
      hyper_body_free(body);
      result = CURLE_OUT_OF_MEMORY;
    }
  }
  return result;
}

static CURLcode cookies(struct Curl_easy *data,
                        struct connectdata *conn,
                        hyper_headers *headers)
{
  struct dynbuf req;
  CURLcode result;
  Curl_dyn_init(&req, DYN_HTTP_REQUEST);

  result = Curl_http_cookies(data, conn, &req);
  if(!result)
    result = Curl_hyper_header(data, headers, Curl_dyn_ptr(&req));
  Curl_dyn_free(&req);
  return result;
}

/*
 * Curl_http() gets called from the generic multi_do() function when a HTTP
 * request is to be performed. This creates and sends a properly constructed
 * HTTP request.
 */
CURLcode Curl_http(struct Curl_easy *data, bool *done)
{
  struct connectdata *conn = data->conn;
  struct hyptransfer *h = &data->hyp;
  hyper_io *io = NULL;
  hyper_clientconn_options *options = NULL;
  hyper_task *task = NULL; /* for the handshake */
  hyper_task *sendtask = NULL; /* for the send */
  hyper_clientconn *client = NULL;
  hyper_request *req = NULL;
  hyper_headers *headers = NULL;
  hyper_task *handshake = NULL;
  hyper_error *hypererr = NULL;
  CURLcode result;
  const char *p_accept; /* Accept: string */
  const char *method;
  Curl_HttpReq httpreq;
  bool h2 = FALSE;
  const char *te = NULL; /* transfer-encoding */

  /* 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;

  infof(data, "Time for the Hyper dance\n");
  memset(h, 0, sizeof(struct hyptransfer));

  result = Curl_http_host(data, conn);
  if(result)
    return result;

  Curl_http_method(data, conn, &method, &httpreq);

  /* setup the authentication headers */
  {
    char *pq = NULL;
    if(data->state.up.query) {
      pq = aprintf("%s?%s", data->state.up.path, data->state.up.query);
      if(!pq)
        return CURLE_OUT_OF_MEMORY;
    }
    result = Curl_http_output_auth(data, conn, method, httpreq,
                                   (pq ? pq : data->state.up.path), FALSE);
    free(pq);
    if(result)
      return result;
  }

  result = Curl_http_resume(data, conn, httpreq);
  if(result)
    return result;

  result = Curl_http_range(data, httpreq);
  if(result)
    return result;

  result = Curl_http_useragent(data);
  if(result)
    return result;

  io = hyper_io_new();
  if(!io) {
    failf(data, "Couldn't create hyper IO");
    goto error;
  }
  /* tell Hyper how to read/write network data */
  hyper_io_set_userdata(io, data);
  hyper_io_set_read(io, Curl_hyper_recv);
  hyper_io_set_write(io, Curl_hyper_send);

  /* create an executor to poll futures */
  if(!h->exec) {
    h->exec = hyper_executor_new();
    if(!h->exec) {
      failf(data, "Couldn't create hyper executor");
      goto error;
    }
  }

  options = hyper_clientconn_options_new();
  if(!options) {
    failf(data, "Couldn't create hyper client options");
    goto error;
  }
  if(conn->negnpn == CURL_HTTP_VERSION_2) {
    hyper_clientconn_options_http2(options, 1);
    h2 = TRUE;
  }

  hyper_clientconn_options_exec(options, h->exec);

  /* "Both the `io` and the `options` are consumed in this function call" */
  handshake = hyper_clientconn_handshake(io, options);
  if(!handshake) {
    failf(data, "Couldn't create hyper client handshake");
    goto error;
  }
  io = NULL;
  options = NULL;

  if(HYPERE_OK != hyper_executor_push(h->exec, handshake)) {
    failf(data, "Couldn't hyper_executor_push the handshake");
    goto error;
  }
  handshake = NULL; /* ownership passed on */

  task = hyper_executor_poll(h->exec);
  if(!task) {
    failf(data, "Couldn't hyper_executor_poll the handshake");
    goto error;
  }

  client = hyper_task_value(task);
  hyper_task_free(task);

  req = hyper_request_new();
  if(!req) {
    failf(data, "Couldn't hyper_request_new");
    goto error;
  }

  if(data->set.httpversion == CURL_HTTP_VERSION_1_0) {
    if(HYPERE_OK != hyper_request_set_version(req,
                                              HYPER_HTTP_VERSION_1_0)) {
      failf(data, "error setting HTTP version");
      goto error;
    }
  }

  if(hyper_request_set_method(req, (uint8_t *)method, strlen(method))) {
    failf(data, "error setting method");
    goto error;
  }

  result = request_target(data, conn, method, h2, req);
  if(result)
    goto error;

  headers = hyper_request_headers(req);
  if(!headers) {
    failf(data, "hyper_request_headers");
    goto error;
  }

  result = Curl_http_body(data, conn, httpreq, &te);
  if(result)
    return result;

  if(data->state.aptr.host &&
     Curl_hyper_header(data, headers, data->state.aptr.host))
    goto error;

  if(data->state.aptr.proxyuserpwd &&
     Curl_hyper_header(data, headers, data->state.aptr.proxyuserpwd))
    goto error;

  if(data->state.aptr.userpwd &&
     Curl_hyper_header(data, headers, data->state.aptr.userpwd))
    goto error;

  if((data->state.use_range && data->state.aptr.rangeline) &&
     Curl_hyper_header(data, headers, data->state.aptr.rangeline))
    goto error;

  if(data->set.str[STRING_USERAGENT] &&
     *data->set.str[STRING_USERAGENT] &&
     data->state.aptr.uagent &&
     Curl_hyper_header(data, headers, data->state.aptr.uagent))
    goto error;

  p_accept = Curl_checkheaders(data, "Accept")?NULL:"Accept: */*\r\n";
  if(p_accept && Curl_hyper_header(data, headers, p_accept))
    goto error;

  if(te && Curl_hyper_header(data, headers, te))
    goto error;

#ifndef CURL_DISABLE_PROXY
  if(conn->bits.httpproxy && !conn->bits.tunnel_proxy &&
     !Curl_checkheaders(data, "Proxy-Connection") &&
     !Curl_checkProxyheaders(data, conn, "Proxy-Connection")) {
    if(Curl_hyper_header(data, headers, "Proxy-Connection: Keep-Alive"))
      goto error;
  }
#endif

  Curl_safefree(data->state.aptr.ref);
  if(data->change.referer && !Curl_checkheaders(data, "Referer")) {
    data->state.aptr.ref = aprintf("Referer: %s\r\n", data->change.referer);
    if(!data->state.aptr.ref)
      return CURLE_OUT_OF_MEMORY;
    if(Curl_hyper_header(data, headers, data->state.aptr.ref))
      goto error;
  }

  result = cookies(data, conn, headers);
  if(result)
    return result;

  result = Curl_add_timecondition(data, headers);
  if(result)
    return result;

  result = Curl_add_custom_headers(data, FALSE, headers);
  if(result)
    return result;

  result = bodysend(data, conn, headers, req, httpreq);
  if(result)
    return result;

  Curl_debug(data, CURLINFO_HEADER_OUT, (char *)"\r\n", 2);

  data->req.upload_chunky = FALSE;
  sendtask = hyper_clientconn_send(client, req);
  if(!sendtask) {
    failf(data, "hyper_clientconn_send");
    goto error;
  }

  if(HYPERE_OK != hyper_executor_push(h->exec, sendtask)) {
    failf(data, "Couldn't hyper_executor_push the send");
    goto error;
  }

  hyper_clientconn_free(client);

  do {
    task = hyper_executor_poll(h->exec);
    if(task) {
      bool error = hyper_task_type(task) == HYPER_TASK_ERROR;
      if(error)
        hypererr = hyper_task_value(task);
      hyper_task_free(task);
      if(error)
        goto error;
    }
  } while(task);

  if((httpreq == HTTPREQ_GET) || (httpreq == HTTPREQ_HEAD)) {
    /* HTTP GET/HEAD download */
    Curl_pgrsSetUploadSize(data, 0); /* nothing */
    Curl_setup_transfer(data, FIRSTSOCKET, -1, TRUE, -1);
  }
  conn->datastream = Curl_hyper_stream;

  return CURLE_OK;
  error:

  if(io)
    hyper_io_free(io);

  if(options)
    hyper_clientconn_options_free(options);

  if(handshake)
    hyper_task_free(handshake);

  if(hypererr) {
    uint8_t errbuf[256];
    size_t errlen = hyper_error_print(hypererr, errbuf, sizeof(errbuf));
    hyper_code code = hyper_error_code(hypererr);
    failf(data, "Hyper: [%d] %.*s", (int)code, (int)errlen, errbuf);
    hyper_error_free(hypererr);
  }
  return CURLE_OUT_OF_MEMORY;
}

void Curl_hyper_done(struct Curl_easy *data)
{
  struct hyptransfer *h = &data->hyp;
  if(h->exec) {
    hyper_executor_free(h->exec);
    h->exec = NULL;
  }
  if(h->read_waker) {
    hyper_waker_free(h->read_waker);
    h->read_waker = NULL;
  }
  if(h->write_waker) {
    hyper_waker_free(h->write_waker);
    h->write_waker = NULL;
  }
}

#endif /* !defined(CURL_DISABLE_HTTP) && defined(USE_HYPER) */
Added jni/curl/lib/c-hyper.h.
















































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
#ifndef HEADER_CURL_HYPER_H
#define HEADER_CURL_HYPER_H
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2021, 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 https://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_HYPER)

#include <hyper.h>

/* per-transfer data for the Hyper backend */
struct hyptransfer {
  hyper_waker *write_waker;
  hyper_waker *read_waker;
  const hyper_executor *exec;
  hyper_task *endtask;
};

size_t Curl_hyper_recv(void *userp, hyper_context *ctx,
                       uint8_t *buf, size_t buflen);
size_t Curl_hyper_send(void *userp, hyper_context *ctx,
                       const uint8_t *buf, size_t buflen);
CURLcode Curl_hyper_stream(struct Curl_easy *data,
                           struct connectdata *conn,
                           int *didwhat,
                           bool *done,
                           int select_res);

CURLcode Curl_hyper_header(struct Curl_easy *data, hyper_headers *headers,
                           const char *line);
void Curl_hyper_done(struct Curl_easy *);

#else
#define Curl_hyper_done(x)

#endif /* !defined(CURL_DISABLE_HTTP) && defined(USE_HYPER) */
#endif /* HEADER_CURL_HYPER_H */
Changes to jni/curl/lib/conncache.c.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 2012 - 2016, Linus Nielsen Feltzing, <linus@haxx.se>
 * Copyright (C) 2012 - 2020, 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 https://curl.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








|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 2012 - 2016, Linus Nielsen Feltzing, <linus@haxx.se>
 * Copyright (C) 2012 - 2021, 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 https://curl.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
175
176
177
178
179
180
181
182


183
184
185
186
187
188
189
190
191
192
193
194
  return num;
}

/* Look up the bundle with all the connections to the same host this
   connectdata struct is setup to use.

   **NOTE**: When it returns, it holds the connection cache lock! */
struct connectbundle *Curl_conncache_find_bundle(struct connectdata *conn,


                                                 struct conncache *connc,
                                                 const char **hostp)
{
  struct connectbundle *bundle = NULL;
  CONNCACHE_LOCK(conn->data);
  if(connc) {
    char key[HASHKEY_SIZE];
    hashkey(conn, key, sizeof(key), hostp);
    bundle = Curl_hash_pick(&connc->hash, key, strlen(key));
  }

  return bundle;







|
>
>
|
|


|







175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
  return num;
}

/* Look up the bundle with all the connections to the same host this
   connectdata struct is setup to use.

   **NOTE**: When it returns, it holds the connection cache lock! */
struct connectbundle *
Curl_conncache_find_bundle(struct Curl_easy *data,
                           struct connectdata *conn,
                           struct conncache *connc,
                           const char **hostp)
{
  struct connectbundle *bundle = NULL;
  CONNCACHE_LOCK(data);
  if(connc) {
    char key[HASHKEY_SIZE];
    hashkey(conn, key, sizeof(key), hostp);
    bundle = Curl_hash_pick(&connc->hash, key, strlen(key));
  }

  return bundle;
223
224
225
226
227
228
229
230
231
232
233
234
235


236
237
238

239
240
241
242
243
244
245
      return;
    }

    he = Curl_hash_next_element(&iter);
  }
}

CURLcode Curl_conncache_add_conn(struct conncache *connc,
                                 struct connectdata *conn)
{
  CURLcode result = CURLE_OK;
  struct connectbundle *bundle = NULL;
  struct Curl_easy *data = conn->data;



  /* *find_bundle() locks the connection cache */
  bundle = Curl_conncache_find_bundle(conn, data->state.conn_cache, NULL);

  if(!bundle) {
    int rc;
    char key[HASHKEY_SIZE];

    result = bundle_create(&bundle);
    if(result) {
      goto unlock;







|
<



|
>
>


|
>







225
226
227
228
229
230
231
232

233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
      return;
    }

    he = Curl_hash_next_element(&iter);
  }
}

CURLcode Curl_conncache_add_conn(struct Curl_easy *data)

{
  CURLcode result = CURLE_OK;
  struct connectbundle *bundle = NULL;
  struct connectdata *conn = data->conn;
  struct conncache *connc = data->state.conn_cache;
  DEBUGASSERT(conn);

  /* *find_bundle() locks the connection cache */
  bundle = Curl_conncache_find_bundle(data, conn, data->state.conn_cache,
                                      NULL);
  if(!bundle) {
    int rc;
    char key[HASHKEY_SIZE];

    result = bundle_create(&bundle);
    if(result) {
      goto unlock;
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
    }
  }

  bundle_add_conn(bundle, conn);
  conn->connection_id = connc->next_connection_id++;
  connc->num_conn++;

  DEBUGF(infof(conn->data, "Added connection %ld. "
               "The cache now contains %zu members\n",
               conn->connection_id, connc->num_conn));

  unlock:
  CONNCACHE_UNLOCK(data);

  return result;
}

/*
 * Removes the connectdata object from the connection cache, but does *not*
 * clear the conn->data association. The transfer still owns this connection.
 *
 * Pass TRUE/FALSE in the 'lock' argument depending on if the parent function
 * already holds the lock or not.
 */
void Curl_conncache_remove_conn(struct Curl_easy *data,
                                struct connectdata *conn, bool lock)
{







|










|
|







259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
    }
  }

  bundle_add_conn(bundle, conn);
  conn->connection_id = connc->next_connection_id++;
  connc->num_conn++;

  DEBUGF(infof(data, "Added connection %ld. "
               "The cache now contains %zu members\n",
               conn->connection_id, connc->num_conn));

  unlock:
  CONNCACHE_UNLOCK(data);

  return result;
}

/*
 * Removes the connectdata object from the connection cache, but the transfer
 * still owns this connection.
 *
 * Pass TRUE/FALSE in the 'lock' argument depending on if the parent function
 * already holds the lock or not.
 */
void Curl_conncache_remove_conn(struct Curl_easy *data,
                                struct connectdata *conn, bool lock)
{
314
315
316
317
318
319
320

321
322
323
324
325
326
327
328
   Returns 1 if the loop was aborted due to the callback's return code.

   Return 0 from func() to continue the loop, return 1 to abort it.
 */
bool Curl_conncache_foreach(struct Curl_easy *data,
                            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 FALSE;







>
|







318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
   Returns 1 if the loop was aborted due to the callback's return code.

   Return 0 from func() to continue the loop, return 1 to abort it.
 */
bool Curl_conncache_foreach(struct Curl_easy *data,
                            struct conncache *connc,
                            void *param,
                            int (*func)(struct Curl_easy *data,
                                        struct connectdata *conn, void *param))
{
  struct Curl_hash_iterator iter;
  struct Curl_llist_element *curr;
  struct Curl_hash_element *he;

  if(!connc)
    return FALSE;
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
    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)) {
        CONNCACHE_UNLOCK(data);
        return TRUE;
      }
    }
  }
  CONNCACHE_UNLOCK(data);
  return FALSE;







|







345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
    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(data, conn, param)) {
        CONNCACHE_UNLOCK(data);
        return TRUE;
      }
    }
  }
  CONNCACHE_UNLOCK(data);
  return FALSE;
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454

  now = Curl_now();

  curr = bundle->conn_list.head;
  while(curr) {
    conn = curr->ptr;

    if(!CONN_INUSE(conn) && !conn->data) {
      /* Set higher score for the age passed since the connection was used */
      score = Curl_timediff(now, conn->lastused);

      if(score > highscore) {
        highscore = score;
        conn_candidate = conn;
      }







|







445
446
447
448
449
450
451
452
453
454
455
456
457
458
459

  now = Curl_now();

  curr = bundle->conn_list.head;
  while(curr) {
    conn = curr->ptr;

    if(!CONN_INUSE(conn)) {
      /* Set higher score for the age passed since the connection was used */
      score = Curl_timediff(now, conn->lastused);

      if(score > highscore) {
        highscore = score;
        conn_candidate = conn;
      }
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512

    bundle = he->ptr;

    curr = bundle->conn_list.head;
    while(curr) {
      conn = curr->ptr;

      if(!CONN_INUSE(conn) && !conn->data && !conn->bits.close &&
         !conn->bits.connect_only) {
        /* Set higher score for the age passed since the connection was used */
        score = Curl_timediff(now, conn->lastused);

        if(score > highscore) {
          highscore = score;
          conn_candidate = conn;







|







503
504
505
506
507
508
509
510
511
512
513
514
515
516
517

    bundle = he->ptr;

    curr = bundle->conn_list.head;
    while(curr) {
      conn = curr->ptr;

      if(!CONN_INUSE(conn) && !conn->bits.close &&
         !conn->bits.connect_only) {
        /* Set higher score for the age passed since the connection was used */
        score = Curl_timediff(now, conn->lastused);

        if(score > highscore) {
          highscore = score;
          conn_candidate = conn;
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
    return;
  connc->closure_handle->state.buffer = buffer;
  connc->closure_handle->set.buffer_size = READBUFFER_MIN;

  conn = conncache_find_first_connection(connc);
  while(conn) {
    SIGPIPE_VARIABLE(pipe_st);
    conn->data = connc->closure_handle;

    sigpipe_ignore(conn->data, &pipe_st);
    /* This will remove the connection from the cache */
    connclose(conn, "kill all");
    Curl_conncache_remove_conn(conn->data, conn, TRUE);
    (void)Curl_disconnect(connc->closure_handle, conn, FALSE);
    sigpipe_restore(&pipe_st);

    conn = conncache_find_first_connection(connc);
  }

  connc->closure_handle->state.buffer = NULL;







<
<
|


|







544
545
546
547
548
549
550


551
552
553
554
555
556
557
558
559
560
561
    return;
  connc->closure_handle->state.buffer = buffer;
  connc->closure_handle->set.buffer_size = READBUFFER_MIN;

  conn = conncache_find_first_connection(connc);
  while(conn) {
    SIGPIPE_VARIABLE(pipe_st);


    sigpipe_ignore(connc->closure_handle, &pipe_st);
    /* This will remove the connection from the cache */
    connclose(conn, "kill all");
    Curl_conncache_remove_conn(connc->closure_handle, conn, TRUE);
    (void)Curl_disconnect(connc->closure_handle, conn, FALSE);
    sigpipe_restore(&pipe_st);

    conn = conncache_find_first_connection(connc);
  }

  connc->closure_handle->state.buffer = NULL;
Changes to jni/curl/lib/conncache.h.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#ifndef HEADER_CURL_CONNCACHE_H
#define HEADER_CURL_CONNCACHE_H
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 2015 - 2020, 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 https://curl.se/docs/copyright.html.
 *
 * You may opt to use, copy, modify, merge, publish, distribute and/or sell









|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#ifndef HEADER_CURL_CONNCACHE_H
#define HEADER_CURL_CONNCACHE_H
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 2015 - 2021, 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 https://curl.se/docs/copyright.html.
 *
 * You may opt to use, copy, modify, merge, publish, distribute and/or sell
25
26
27
28
29
30
31




32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47


48
49

50
51


52
53

54
55
56
57

58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77

78
79
80
81
82
83
84
85
86
87
88
89
90
91
92

93
94
95
96
97
98
99
100

/*
 * All accesses to struct fields and changing of data in the connection cache
 * and connectbundles must be done with the conncache LOCKED. The cache might
 * be shared.
 */





struct conncache {
  struct Curl_hash hash;
  size_t num_conn;
  long next_connection_id;
  struct curltime last_cleanup;
  /* handle used for closing cached connections */
  struct Curl_easy *closure_handle;
};

#define BUNDLE_NO_MULTIUSE -1
#define BUNDLE_UNKNOWN     0  /* initial value */
#define BUNDLE_MULTIPLEX   2

#ifdef CURLDEBUG
/* the debug versions of these macros make extra certain that the lock is
   never doubly locked or unlocked */


#define CONNCACHE_LOCK(x) if((x)->share) {                              \
    Curl_share_lock((x), CURL_LOCK_DATA_CONNECT, CURL_LOCK_ACCESS_SINGLE); \

    DEBUGASSERT(!(x)->state.conncache_lock);                            \
    (x)->state.conncache_lock = TRUE;                                   \


  }


#define CONNCACHE_UNLOCK(x) if((x)->share) {                            \
    DEBUGASSERT((x)->state.conncache_lock);                             \
    (x)->state.conncache_lock = FALSE;                                  \
    Curl_share_unlock((x), CURL_LOCK_DATA_CONNECT);                     \

  }
#else
#define CONNCACHE_LOCK(x) if((x)->share)                                \
    Curl_share_lock((x), CURL_LOCK_DATA_CONNECT, CURL_LOCK_ACCESS_SINGLE)
#define CONNCACHE_UNLOCK(x) if((x)->share)              \
    Curl_share_unlock((x), CURL_LOCK_DATA_CONNECT)
#endif

struct connectbundle {
  int multiuse;                 /* supports multi-use */
  size_t num_connections;       /* Number of connections in the bundle */
  struct Curl_llist conn_list;  /* The connectdata members of the bundle */
};

/* returns 1 on error, 0 is fine */
int Curl_conncache_init(struct conncache *, int size);
void Curl_conncache_destroy(struct conncache *connc);

/* return the correct bundle, to a host or a proxy */
struct connectbundle *Curl_conncache_find_bundle(struct connectdata *conn,

                                                 struct conncache *connc,
                                                 const char **hostp);
/* returns number of connections currently held in the connection cache */
size_t Curl_conncache_size(struct Curl_easy *data);

bool Curl_conncache_return_conn(struct Curl_easy *data,
                                struct connectdata *conn);
CURLcode Curl_conncache_add_conn(struct conncache *connc,
                                 struct connectdata *conn) WARN_UNUSED_RESULT;
void Curl_conncache_remove_conn(struct Curl_easy *data,
                                struct connectdata *conn,
                                bool lock);
bool Curl_conncache_foreach(struct Curl_easy *data,
                            struct conncache *connc,
                            void *param,

                            int (*func)(struct connectdata *conn,
                                        void *param));

struct connectdata *
Curl_conncache_find_first_connection(struct conncache *connc);

struct connectdata *
Curl_conncache_extract_bundle(struct Curl_easy *data,







>
>
>
>
















>
>
|
|
>
|
|
>
>
|
|
>
|
|
|
|
>
|


















|
>







|
<






>
|







25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97

98
99
100
101
102
103
104
105
106
107
108
109
110
111
112

/*
 * All accesses to struct fields and changing of data in the connection cache
 * and connectbundles must be done with the conncache LOCKED. The cache might
 * be shared.
 */

#include "timeval.h"

struct connectdata;

struct conncache {
  struct Curl_hash hash;
  size_t num_conn;
  long next_connection_id;
  struct curltime last_cleanup;
  /* handle used for closing cached connections */
  struct Curl_easy *closure_handle;
};

#define BUNDLE_NO_MULTIUSE -1
#define BUNDLE_UNKNOWN     0  /* initial value */
#define BUNDLE_MULTIPLEX   2

#ifdef CURLDEBUG
/* the debug versions of these macros make extra certain that the lock is
   never doubly locked or unlocked */
#define CONNCACHE_LOCK(x)                                               \
  do {                                                                  \
    if((x)->share) {                                                    \
      Curl_share_lock((x), CURL_LOCK_DATA_CONNECT,                      \
                      CURL_LOCK_ACCESS_SINGLE);                         \
      DEBUGASSERT(!(x)->state.conncache_lock);                          \
      (x)->state.conncache_lock = TRUE;                                 \
    }                                                                   \
  } while(0)

#define CONNCACHE_UNLOCK(x)                                             \
  do {                                                                  \
    if((x)->share) {                                                    \
      DEBUGASSERT((x)->state.conncache_lock);                           \
      (x)->state.conncache_lock = FALSE;                                \
      Curl_share_unlock((x), CURL_LOCK_DATA_CONNECT);                   \
    }                                                                   \
  } while(0)
#else
#define CONNCACHE_LOCK(x) if((x)->share)                                \
    Curl_share_lock((x), CURL_LOCK_DATA_CONNECT, CURL_LOCK_ACCESS_SINGLE)
#define CONNCACHE_UNLOCK(x) if((x)->share)              \
    Curl_share_unlock((x), CURL_LOCK_DATA_CONNECT)
#endif

struct connectbundle {
  int multiuse;                 /* supports multi-use */
  size_t num_connections;       /* Number of connections in the bundle */
  struct Curl_llist conn_list;  /* The connectdata members of the bundle */
};

/* returns 1 on error, 0 is fine */
int Curl_conncache_init(struct conncache *, int size);
void Curl_conncache_destroy(struct conncache *connc);

/* return the correct bundle, to a host or a proxy */
struct connectbundle *Curl_conncache_find_bundle(struct Curl_easy *data,
                                                 struct connectdata *conn,
                                                 struct conncache *connc,
                                                 const char **hostp);
/* returns number of connections currently held in the connection cache */
size_t Curl_conncache_size(struct Curl_easy *data);

bool Curl_conncache_return_conn(struct Curl_easy *data,
                                struct connectdata *conn);
CURLcode Curl_conncache_add_conn(struct Curl_easy *data) WARN_UNUSED_RESULT;

void Curl_conncache_remove_conn(struct Curl_easy *data,
                                struct connectdata *conn,
                                bool lock);
bool Curl_conncache_foreach(struct Curl_easy *data,
                            struct conncache *connc,
                            void *param,
                            int (*func)(struct Curl_easy *data,
                                        struct connectdata *conn,
                                        void *param));

struct connectdata *
Curl_conncache_find_first_connection(struct conncache *connc);

struct connectdata *
Curl_conncache_extract_bundle(struct Curl_easy *data,
Changes to jni/curl/lib/connect.c.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2020, 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 https://curl.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







|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2021, 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 https://curl.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
156
157
158
159
160
161
162
163

164
165
166
167
168
169
170
    }
#endif
#endif
  }
}

static CURLcode
singleipconnect(struct connectdata *conn,

                const struct Curl_addrinfo *ai, /* start connecting to this */
                int tempindex);          /* 0 or 1 among the temp ones */

/*
 * Curl_timeleft() returns the amount of milliseconds left allowed for the
 * transfer/connection. If the value is 0, there's no timeout (ie there's
 * infinite time left). If the value is negative, the timeout time has already







|
>







156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
    }
#endif
#endif
  }
}

static CURLcode
singleipconnect(struct Curl_easy *data,
                struct connectdata *conn,
                const struct Curl_addrinfo *ai, /* start connecting to this */
                int tempindex);          /* 0 or 1 among the temp ones */

/*
 * Curl_timeleft() returns the amount of milliseconds left allowed for the
 * transfer/connection. If the value is 0, there's no timeout (ie there's
 * infinite time left). If the value is negative, the timeout time has already
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258



259
260
261
262
263
264
265
  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 Curl_easy *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;







|


<
|















>
>
>







233
234
235
236
237
238
239
240
241
242

243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
  if(!timeout_ms)
    /* avoid returning 0 as that means no timeout! */
    return -1;

  return timeout_ms;
}

static CURLcode bindlocal(struct Curl_easy *data,
                          curl_socket_t sockfd, int af, unsigned int scope)
{

  struct connectdata *conn = data->conn;
  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;
#ifdef IP_BIND_ADDRESS_NO_PORT
  int on = 1;
#endif

  /*************************************************************
   * Select device to bind socket to
   *************************************************************/
  if(!dev && !port)
    /* no local kind of binding was requested */
    return CURLE_OK;
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
       * 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, FALSE, &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);







|









|

|







344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
       * 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.
       */
      unsigned char 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(data, dev, 0, FALSE, &h);
      if(rc == CURLRESOLV_PENDING)
        (void)Curl_resolver_wait_resolv(data, &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);
437
438
439
440
441
442
443
444


445
446
447
448
449
450
451
#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) {







|
>
>







440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
#endif
    if(af == AF_INET) {
      si4->sin_family = AF_INET;
      si4->sin_port = htons(port);
      sizeof_sa = sizeof(struct sockaddr_in);
    }
  }
#ifdef IP_BIND_ADDRESS_NO_PORT
  (void)setsockopt(sockfd, SOL_IP, IP_BIND_ADDRESS_NO_PORT, &on, sizeof(on));
#endif
  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) {
564
565
566
567
568
569
570
571

572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607

608
609



610
611
612
613
614
615
616
617
618
619
620
621
    ai = ai->ai_next;
  conn->tempaddr[tempindex] = ai;
  return ai;
}

/* Used within the multi interface. Try next IP address, returns error if no
   more address exists or error */
static CURLcode trynextip(struct connectdata *conn,

                          int sockindex,
                          int tempindex)
{
  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) {
    struct Curl_addrinfo *ai = conn->tempaddr[tempindex];

    while(ai) {
      if(ai) {
        result = singleipconnect(conn, ai, tempindex);
        if(result == CURLE_COULDNT_CONNECT) {
          ai = ainext(conn, tempindex, TRUE);
          continue;
        }
      }
      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. */
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_scheme = conn->handler->scheme;
  conn->data->info.conn_protocol = conn->handler->protocol;
  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.
   note it calls Curl_inet_ntop which sets errno on fail, not SOCKERRNO. */
bool Curl_addr2string(struct sockaddr *sa, curl_socklen_t salen,
                      char *addr, long *port)
{







|
>

















|










|




|
|
|
>

|
>
>
>
|
|
|
|
|







569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
    ai = ai->ai_next;
  conn->tempaddr[tempindex] = ai;
  return ai;
}

/* Used within the multi interface. Try next IP address, returns error if no
   more address exists or error */
static CURLcode trynextip(struct Curl_easy *data,
                          struct connectdata *conn,
                          int sockindex,
                          int tempindex)
{
  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) {
    struct Curl_addrinfo *ai = conn->tempaddr[tempindex];

    while(ai) {
      if(ai) {
        result = singleipconnect(data, conn, ai, tempindex);
        if(result == CURLE_COULDNT_CONNECT) {
          ai = ainext(conn, tempindex, TRUE);
          continue;
        }
      }
      break;
    }
  }

  if(fd_to_close != CURL_SOCKET_BAD)
    Curl_closesocket(data, conn, fd_to_close);

  return result;
}

/* Copies connection info into the transfer handle to make it available when
   the transfer handle is no longer associated with the connection. */
void Curl_persistconninfo(struct Curl_easy *data, struct connectdata *conn,
                          char *local_ip, long local_port)
{
  memcpy(data->info.conn_primary_ip, conn->primary_ip, MAX_IPADR_LEN);
  if(local_ip && local_ip[0])
    memcpy(data->info.conn_local_ip, local_ip, MAX_IPADR_LEN);
  else
    data->info.conn_local_ip[0] = 0;
  data->info.conn_scheme = conn->handler->scheme;
  data->info.conn_protocol = conn->handler->protocol;
  data->info.conn_primary_port = conn->port;
  data->info.conn_local_port = local_port;
}

/* retrieves ip address and port from a sockaddr structure.
   note it calls Curl_inet_ntop which sets errno on fail, not SOCKERRNO. */
bool Curl_addr2string(struct sockaddr *sa, curl_socklen_t salen,
                      char *addr, long *port)
{
669
670
671
672
673
674
675
676

677
678
679
680
681

682

683
684
685
686
687
688
689
690
691
692
693
694
695
696

697
698
699
700
701
702
703
704

705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726


727
728
729
730
731

732
733






734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757

758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810

811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828

829
830
831
832
833
834
835
836
837
838
839
  *port = 0;
  errno = EAFNOSUPPORT;
  return FALSE;
}

/* retrieves the start/end point information of a socket of an established
   connection */
void Curl_conninfo_remote(struct connectdata *conn, curl_socket_t sockfd)

{
#ifdef HAVE_GETPEERNAME
  char buffer[STRERROR_LEN];
  struct Curl_sockaddr_storage ssrem;
  curl_socklen_t plen;

  plen = sizeof(struct Curl_sockaddr_storage);

  if(getpeername(sockfd, (struct sockaddr*) &ssrem, &plen)) {
    int error = SOCKERRNO;
    failf(conn->data, "getpeername() failed with errno %d: %s",
          error, Curl_strerror(error, buffer, sizeof(buffer)));
    return;
  }
  if(!Curl_addr2string((struct sockaddr*)&ssrem, plen,
                       conn->primary_ip, &conn->primary_port)) {
    failf(conn->data, "ssrem inet_ntop() failed with errno %d: %s",
          errno, Curl_strerror(errno, buffer, sizeof(buffer)));
    return;
  }
  memcpy(conn->ip_addr_str, conn->primary_ip, MAX_IPADR_LEN);
#else

  (void)conn;
  (void)sockfd;
#endif
}

/* retrieves the start/end point information of a socket of an established
   connection */
void Curl_conninfo_local(struct connectdata *conn, curl_socket_t sockfd)

{
#ifdef HAVE_GETSOCKNAME
  char buffer[STRERROR_LEN];
  struct Curl_sockaddr_storage ssloc;
  curl_socklen_t slen;
  slen = sizeof(struct Curl_sockaddr_storage);
  memset(&ssloc, 0, sizeof(ssloc));
  if(getsockname(sockfd, (struct sockaddr*) &ssloc, &slen)) {
    int error = SOCKERRNO;
    failf(conn->data, "getsockname() failed with errno %d: %s",
          error, Curl_strerror(error, buffer, sizeof(buffer)));
    return;
  }
  if(!Curl_addr2string((struct sockaddr*)&ssloc, slen,
                       conn->local_ip, &conn->local_port)) {
    failf(conn->data, "ssloc inet_ntop() failed with errno %d: %s",
          errno, Curl_strerror(errno, buffer, sizeof(buffer)));
    return;
  }
#else
  (void)conn;
  (void)sockfd;


#endif
}

/* retrieves the start/end point information of a socket of an established
   connection */

void Curl_updateconninfo(struct connectdata *conn, curl_socket_t sockfd)
{






  if(conn->transport == TRNSPRT_TCP) {
    if(!conn->bits.reuse && !conn->bits.tcp_fastopen) {
      Curl_conninfo_remote(conn, sockfd);
      Curl_conninfo_local(conn, sockfd);
    }
  } /* end of TCP-only section */

  /* persist connection info in session handle */
  Curl_persistconninfo(conn);
}

/* After a TCP connection to the proxy has been verified, this function does
   the next magic steps. If 'done' isn't set TRUE, it is not done yet and
   must be called again.

   Note: this function's sub-functions call failf()

*/
static CURLcode connect_SOCKS(struct connectdata *conn, int sockindex,
                              bool *done)
{
  CURLcode result = CURLE_OK;
#ifndef CURL_DISABLE_PROXY
  CURLproxycode pxresult = CURLPX_OK;

  if(conn->bits.socksproxy) {
    /* for the secondary socket (FTP), use the "connect to host"
     * but ignore the "connect to port" (use the secondary port)
     */
    const char * const host =
      conn->bits.httpproxy ?
      conn->http_proxy.host.name :
      conn->bits.conn_to_host ?
      conn->conn_to_host.name :
      sockindex == SECONDARYSOCKET ?
      conn->secondaryhostname : conn->host.name;
    const int port =
      conn->bits.httpproxy ? (int)conn->http_proxy.port :
      sockindex == SECONDARYSOCKET ? conn->secondary_port :
      conn->bits.conn_to_port ? conn->conn_to_port :
      conn->remote_port;
    switch(conn->socks_proxy.proxytype) {
    case CURLPROXY_SOCKS5:
    case CURLPROXY_SOCKS5_HOSTNAME:
      pxresult = Curl_SOCKS5(conn->socks_proxy.user, conn->socks_proxy.passwd,
                             host, port, sockindex, conn, done);
      break;

    case CURLPROXY_SOCKS4:
    case CURLPROXY_SOCKS4A:
      pxresult = Curl_SOCKS4(conn->socks_proxy.user, host, port, sockindex,
                             conn, done);
      break;

    default:
      failf(conn->data, "unknown proxytype option given");
      result = CURLE_COULDNT_CONNECT;
    } /* switch proxytype */
    if(pxresult) {
      result = CURLE_PROXY;
      conn->data->info.pxcode = pxresult;
    }
  }
  else
#else
    (void)conn;
    (void)sockindex;
#endif /* CURL_DISABLE_PROXY */
    *done = TRUE; /* no SOCKS proxy, so consider us connected */

  return result;
}

/*
 * post_SOCKS() is called after a successful connect to the peer, which
 * *could* be a SOCKS proxy
 */
static void post_SOCKS(struct connectdata *conn,

                       int sockindex,
                       bool *connected)
{
  conn->bits.tcpconnect[sockindex] = TRUE;

  *connected = TRUE;
  if(sockindex == FIRSTSOCKET)
    Curl_pgrsTime(conn->data, TIMER_CONNECT); /* connect done */
  Curl_updateconninfo(conn, conn->sock[sockindex]);
  Curl_verboseconnect(conn);
  conn->data->info.numconnects++; /* to track the number of connections made */
}

/*
 * Curl_is_connected() checks if the socket has connected.
 */

CURLcode Curl_is_connected(struct connectdata *conn,

                           int sockindex,
                           bool *connected)
{
  struct Curl_easy *data = conn->data;
  CURLcode result = CURLE_OK;
  timediff_t allow;
  int error = 0;
  struct curltime now;
  int rc = 0;
  unsigned int i;








|
>





>

>


|




|
|



<

>







|
>









|




|
|




|

>
>





>
|

>
>
>
>
>
>


|
|




|









|





>




















|





|



|




|




|











|
>







|
|
|
|






|
>



<







679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707

708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857

858
859
860
861
862
863
864
  *port = 0;
  errno = EAFNOSUPPORT;
  return FALSE;
}

/* retrieves the start/end point information of a socket of an established
   connection */
void Curl_conninfo_remote(struct Curl_easy *data,
                          struct connectdata *conn, curl_socket_t sockfd)
{
#ifdef HAVE_GETPEERNAME
  char buffer[STRERROR_LEN];
  struct Curl_sockaddr_storage ssrem;
  curl_socklen_t plen;
  long port;
  plen = sizeof(struct Curl_sockaddr_storage);
  memset(&ssrem, 0, sizeof(ssrem));
  if(getpeername(sockfd, (struct sockaddr*) &ssrem, &plen)) {
    int error = SOCKERRNO;
    failf(data, "getpeername() failed with errno %d: %s",
          error, Curl_strerror(error, buffer, sizeof(buffer)));
    return;
  }
  if(!Curl_addr2string((struct sockaddr*)&ssrem, plen,
                       conn->primary_ip, &port)) {
    failf(data, "ssrem inet_ntop() failed with errno %d: %s",
          errno, Curl_strerror(errno, buffer, sizeof(buffer)));
    return;
  }

#else
  (void)data;
  (void)conn;
  (void)sockfd;
#endif
}

/* retrieves the start/end point information of a socket of an established
   connection */
void Curl_conninfo_local(struct Curl_easy *data, curl_socket_t sockfd,
                         char *local_ip, long *local_port)
{
#ifdef HAVE_GETSOCKNAME
  char buffer[STRERROR_LEN];
  struct Curl_sockaddr_storage ssloc;
  curl_socklen_t slen;
  slen = sizeof(struct Curl_sockaddr_storage);
  memset(&ssloc, 0, sizeof(ssloc));
  if(getsockname(sockfd, (struct sockaddr*) &ssloc, &slen)) {
    int error = SOCKERRNO;
    failf(data, "getsockname() failed with errno %d: %s",
          error, Curl_strerror(error, buffer, sizeof(buffer)));
    return;
  }
  if(!Curl_addr2string((struct sockaddr*)&ssloc, slen,
                       local_ip, local_port)) {
    failf(data, "ssloc inet_ntop() failed with errno %d: %s",
          errno, Curl_strerror(errno, buffer, sizeof(buffer)));
    return;
  }
#else
  (void)data;
  (void)sockfd;
  (void)local_ip;
  (void)local_port;
#endif
}

/* retrieves the start/end point information of a socket of an established
   connection */
void Curl_updateconninfo(struct Curl_easy *data, struct connectdata *conn,
                         curl_socket_t sockfd)
{
  /* '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 = -1;

  if(conn->transport == TRNSPRT_TCP) {
    if(!conn->bits.reuse && !conn->bits.tcp_fastopen) {
      Curl_conninfo_remote(data, conn, sockfd);
      Curl_conninfo_local(data, sockfd, local_ip, &local_port);
    }
  } /* end of TCP-only section */

  /* persist connection info in session handle */
  Curl_persistconninfo(data, conn, local_ip, local_port);
}

/* After a TCP connection to the proxy has been verified, this function does
   the next magic steps. If 'done' isn't set TRUE, it is not done yet and
   must be called again.

   Note: this function's sub-functions call failf()

*/
static CURLcode connect_SOCKS(struct Curl_easy *data, int sockindex,
                              bool *done)
{
  CURLcode result = CURLE_OK;
#ifndef CURL_DISABLE_PROXY
  CURLproxycode pxresult = CURLPX_OK;
  struct connectdata *conn = data->conn;
  if(conn->bits.socksproxy) {
    /* for the secondary socket (FTP), use the "connect to host"
     * but ignore the "connect to port" (use the secondary port)
     */
    const char * const host =
      conn->bits.httpproxy ?
      conn->http_proxy.host.name :
      conn->bits.conn_to_host ?
      conn->conn_to_host.name :
      sockindex == SECONDARYSOCKET ?
      conn->secondaryhostname : conn->host.name;
    const int port =
      conn->bits.httpproxy ? (int)conn->http_proxy.port :
      sockindex == SECONDARYSOCKET ? conn->secondary_port :
      conn->bits.conn_to_port ? conn->conn_to_port :
      conn->remote_port;
    switch(conn->socks_proxy.proxytype) {
    case CURLPROXY_SOCKS5:
    case CURLPROXY_SOCKS5_HOSTNAME:
      pxresult = Curl_SOCKS5(conn->socks_proxy.user, conn->socks_proxy.passwd,
                             host, port, sockindex, data, done);
      break;

    case CURLPROXY_SOCKS4:
    case CURLPROXY_SOCKS4A:
      pxresult = Curl_SOCKS4(conn->socks_proxy.user, host, port, sockindex,
                             data, done);
      break;

    default:
      failf(data, "unknown proxytype option given");
      result = CURLE_COULDNT_CONNECT;
    } /* switch proxytype */
    if(pxresult) {
      result = CURLE_PROXY;
      data->info.pxcode = pxresult;
    }
  }
  else
#else
    (void)data;
    (void)sockindex;
#endif /* CURL_DISABLE_PROXY */
    *done = TRUE; /* no SOCKS proxy, so consider us connected */

  return result;
}

/*
 * post_SOCKS() is called after a successful connect to the peer, which
 * *could* be a SOCKS proxy
 */
static void post_SOCKS(struct Curl_easy *data,
                       struct connectdata *conn,
                       int sockindex,
                       bool *connected)
{
  conn->bits.tcpconnect[sockindex] = TRUE;

  *connected = TRUE;
  if(sockindex == FIRSTSOCKET)
    Curl_pgrsTime(data, TIMER_CONNECT); /* connect done */
  Curl_updateconninfo(data, conn, conn->sock[sockindex]);
  Curl_verboseconnect(data, conn);
  data->info.numconnects++; /* to track the number of connections made */
}

/*
 * Curl_is_connected() checks if the socket has connected.
 */

CURLcode Curl_is_connected(struct Curl_easy *data,
                           struct connectdata *conn,
                           int sockindex,
                           bool *connected)
{

  CURLcode result = CURLE_OK;
  timediff_t allow;
  int error = 0;
  struct curltime now;
  int rc = 0;
  unsigned int i;

856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
    /* time-out, bail out, go home */
    failf(data, "Connection time-out");
    return CURLE_OPERATION_TIMEDOUT;
  }

  if(SOCKS_STATE(conn->cnnct.state)) {
    /* still doing SOCKS */
    result = connect_SOCKS(conn, sockindex, connected);
    if(!result && *connected)
      post_SOCKS(conn, sockindex, connected);
    return result;
  }

  for(i = 0; i<2; i++) {
    const int other = i ^ 1;
    if(conn->tempsock[i] == CURL_SOCKET_BAD)
      continue;
    error = 0;
#ifdef ENABLE_QUIC
    if(conn->transport == TRNSPRT_QUIC) {
      result = Curl_quic_is_connected(conn, i, connected);
      if(!result && *connected) {
        /* use this socket from now on */
        conn->sock[sockindex] = conn->tempsock[i];
        conn->ip_addr = conn->tempaddr[i];
        conn->tempsock[i] = CURL_SOCKET_BAD;
        post_SOCKS(conn, sockindex, connected);
        connkeep(conn, "HTTP/3 default");
        return CURLE_OK;
      }
      if(result)
        error = SOCKERRNO;
    }
    else







|

|










|





|







881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
    /* time-out, bail out, go home */
    failf(data, "Connection time-out");
    return CURLE_OPERATION_TIMEDOUT;
  }

  if(SOCKS_STATE(conn->cnnct.state)) {
    /* still doing SOCKS */
    result = connect_SOCKS(data, sockindex, connected);
    if(!result && *connected)
      post_SOCKS(data, conn, sockindex, connected);
    return result;
  }

  for(i = 0; i<2; i++) {
    const int other = i ^ 1;
    if(conn->tempsock[i] == CURL_SOCKET_BAD)
      continue;
    error = 0;
#ifdef ENABLE_QUIC
    if(conn->transport == TRNSPRT_QUIC) {
      result = Curl_quic_is_connected(data, conn, i, connected);
      if(!result && *connected) {
        /* use this socket from now on */
        conn->sock[sockindex] = conn->tempsock[i];
        conn->ip_addr = conn->tempaddr[i];
        conn->tempsock[i] = CURL_SOCKET_BAD;
        post_SOCKS(data, conn, sockindex, connected);
        connkeep(conn, "HTTP/3 default");
        return CURLE_OK;
      }
      if(result)
        error = SOCKERRNO;
    }
    else
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
      }

      /* should we try another protocol family? */
      if(i == 0 && !conn->bits.parallel_connect &&
         (Curl_timediff(now, conn->connecttime) >=
          data->set.happy_eyeballs_timeout)) {
        conn->bits.parallel_connect = TRUE; /* starting now */
        trynextip(conn, sockindex, 1);
      }
    }
    else if(rc == CURL_CSELECT_OUT || conn->bits.tcp_fastopen) {
      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;
#ifdef ENABLE_IPV6
        conn->bits.ipv6 = (conn->ip_addr->ai_family == AF_INET6)?TRUE:FALSE;
#endif

        /* 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 kick off any SOCKS proxy magic once we
           connected */
        result = connect_SOCKS(conn, sockindex, connected);
        if(result || !*connected)
          return result;

        post_SOCKS(conn, sockindex, connected);

        return CURLE_OK;
      }
    }
    else if(rc & CURL_CSELECT_ERR) {
      (void)verifyconnect(conn->tempsock[i], &error);
    }







|
















|





|



|







935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
      }

      /* should we try another protocol family? */
      if(i == 0 && !conn->bits.parallel_connect &&
         (Curl_timediff(now, conn->connecttime) >=
          data->set.happy_eyeballs_timeout)) {
        conn->bits.parallel_connect = TRUE; /* starting now */
        trynextip(data, conn, sockindex, 1);
      }
    }
    else if(rc == CURL_CSELECT_OUT || conn->bits.tcp_fastopen) {
      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;
#ifdef ENABLE_IPV6
        conn->bits.ipv6 = (conn->ip_addr->ai_family == AF_INET6)?TRUE:FALSE;
#endif

        /* close the other socket, if open */
        if(conn->tempsock[other] != CURL_SOCKET_BAD) {
          Curl_closesocket(data, conn, conn->tempsock[other]);
          conn->tempsock[other] = CURL_SOCKET_BAD;
        }

        /* see if we need to kick off any SOCKS proxy magic once we
           connected */
        result = connect_SOCKS(data, sockindex, connected);
        if(result || !*connected)
          return result;

        post_SOCKS(data, conn, sockindex, connected);

        return CURLE_OK;
      }
    }
    else if(rc & CURL_CSELECT_ERR) {
      (void)verifyconnect(conn->tempsock[i], &error);
    }
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
              ipaddress, conn->port,
              Curl_strerror(error, buffer, sizeof(buffer)));
#endif

        conn->timeoutms_per_addr[i] = conn->tempaddr[i]->ai_next == NULL ?
          allow : allow / 2;
        ainext(conn, i, TRUE);
        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 &&
     (conn->tempsock[0] == CURL_SOCKET_BAD) &&
     (conn->tempsock[1] == CURL_SOCKET_BAD)) {
    /* no more addresses to try */
    const char *hostname;
    char buffer[STRERROR_LEN];

    /* if the first address family runs out of addresses to try before the
       happy eyeball timeout, go ahead and try the next family now */
    result = trynextip(conn, sockindex, 1);
    if(!result)
      return result;

#ifndef CURL_DISABLE_PROXY
    if(conn->bits.socksproxy)
      hostname = conn->socks_proxy.host.name;
    else if(conn->bits.httpproxy)
      hostname = conn->http_proxy.host.name;
    else
#endif
      if(conn->bits.conn_to_host)
        hostname = conn->conn_to_host.name;
    else
      hostname = conn->host.name;

    failf(data, "Failed to connect to %s port %ld: %s",
          hostname, conn->port,
          Curl_strerror(error, buffer, sizeof(buffer)));

    Curl_quic_disconnect(conn, 0);
    Curl_quic_disconnect(conn, 1);

#ifdef WSAETIMEDOUT
    if(WSAETIMEDOUT == data->state.os_errno)
      result = CURLE_OPERATION_TIMEDOUT;
#elif defined(ETIMEDOUT)
    if(ETIMEDOUT == data->state.os_errno)
      result = CURLE_OPERATION_TIMEDOUT;
#endif
  }
  else
    result = CURLE_OK; /* still trying */

  return result;
}

static void tcpnodelay(struct connectdata *conn, curl_socket_t sockfd)
{
#if defined(TCP_NODELAY)
  curl_socklen_t onoff = (curl_socklen_t) 1;
  int level = IPPROTO_TCP;
#if !defined(CURL_DISABLE_VERBOSE_STRINGS)
  struct Curl_easy *data = conn->data;
  char buffer[STRERROR_LEN];
#else
  (void) conn;
#endif

  if(setsockopt(sockfd, level, TCP_NODELAY, (void *)&onoff,
                sizeof(onoff)) < 0)
    infof(data, "Could not set TCP_NODELAY: %s\n",
          Curl_strerror(SOCKERRNO, buffer, sizeof(buffer)));
#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 Curl_easy *data = conn->data;
  int onoff = 1;
  if(setsockopt(sockfd, SOL_SOCKET, SO_NOSIGPIPE, (void *)&onoff,
                sizeof(onoff)) < 0) {
    char buffer[STRERROR_LEN];
    infof(data, "Could not set SO_NOSIGPIPE: %s\n",
          Curl_strerror(SOCKERRNO, buffer, sizeof(buffer)));
  }







|

















|



















|
|















|





<


|







|









|


<







993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060

1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083

1084
1085
1086
1087
1088
1089
1090
              ipaddress, conn->port,
              Curl_strerror(error, buffer, sizeof(buffer)));
#endif

        conn->timeoutms_per_addr[i] = conn->tempaddr[i]->ai_next == NULL ?
          allow : allow / 2;
        ainext(conn, i, TRUE);
        status = trynextip(data, 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 &&
     (conn->tempsock[0] == CURL_SOCKET_BAD) &&
     (conn->tempsock[1] == CURL_SOCKET_BAD)) {
    /* no more addresses to try */
    const char *hostname;
    char buffer[STRERROR_LEN];

    /* if the first address family runs out of addresses to try before the
       happy eyeball timeout, go ahead and try the next family now */
    result = trynextip(data, conn, sockindex, 1);
    if(!result)
      return result;

#ifndef CURL_DISABLE_PROXY
    if(conn->bits.socksproxy)
      hostname = conn->socks_proxy.host.name;
    else if(conn->bits.httpproxy)
      hostname = conn->http_proxy.host.name;
    else
#endif
      if(conn->bits.conn_to_host)
        hostname = conn->conn_to_host.name;
    else
      hostname = conn->host.name;

    failf(data, "Failed to connect to %s port %ld: %s",
          hostname, conn->port,
          Curl_strerror(error, buffer, sizeof(buffer)));

    Curl_quic_disconnect(data, conn, 0);
    Curl_quic_disconnect(data, conn, 1);

#ifdef WSAETIMEDOUT
    if(WSAETIMEDOUT == data->state.os_errno)
      result = CURLE_OPERATION_TIMEDOUT;
#elif defined(ETIMEDOUT)
    if(ETIMEDOUT == data->state.os_errno)
      result = CURLE_OPERATION_TIMEDOUT;
#endif
  }
  else
    result = CURLE_OK; /* still trying */

  return result;
}

static void tcpnodelay(struct Curl_easy *data, curl_socket_t sockfd)
{
#if defined(TCP_NODELAY)
  curl_socklen_t onoff = (curl_socklen_t) 1;
  int level = IPPROTO_TCP;
#if !defined(CURL_DISABLE_VERBOSE_STRINGS)

  char buffer[STRERROR_LEN];
#else
  (void) data;
#endif

  if(setsockopt(sockfd, level, TCP_NODELAY, (void *)&onoff,
                sizeof(onoff)) < 0)
    infof(data, "Could not set TCP_NODELAY: %s\n",
          Curl_strerror(SOCKERRNO, buffer, sizeof(buffer)));
#else
  (void)data;
  (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 Curl_easy *data,
                      curl_socket_t sockfd)
{

  int onoff = 1;
  if(setsockopt(sockfd, SOL_SOCKET, SO_NOSIGPIPE, (void *)&onoff,
                sizeof(onoff)) < 0) {
    char buffer[STRERROR_LEN];
    infof(data, "Could not set SO_NOSIGPIPE: %s\n",
          Curl_strerror(SOCKERRNO, buffer, sizeof(buffer)));
  }
1119
1120
1121
1122
1123
1124
1125
1126

1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
 *
 * 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 struct Curl_addrinfo *ai,
                                int tempindex)
{
  struct Curl_sockaddr_ex addr;
  int rc = -1;
  int error = 0;
  bool isconnected = FALSE;
  struct Curl_easy *data = conn->data;
  curl_socket_t sockfd;
  CURLcode result;
  char ipaddress[MAX_IPADR_LEN];
  long port;
  bool is_tcp;
#ifdef TCP_FASTOPEN_CONNECT
  int optval = 1;
#endif
  char buffer[STRERROR_LEN];
  curl_socket_t *sockp = &conn->tempsock[tempindex];
  *sockp = CURL_SOCKET_BAD;

  result = Curl_socket(conn, ai, &addr, &sockfd);
  if(result)
    return result;

  /* store remote address and port used in this connection attempt */
  if(!Curl_addr2string((struct sockaddr*)&addr.sa_addr, addr.addrlen,
                       ipaddress, &port)) {
    /* malformed address or bug in inet_ntop, try next address */
    failf(data, "sa_addr inet_ntop() failed with errno %d: %s",
          errno, Curl_strerror(errno, buffer, sizeof(buffer)));
    Curl_closesocket(conn, sockfd);
    return CURLE_OK;
  }
  infof(data, "  Trying %s:%ld...\n", ipaddress, port);

#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 */
    Curl_set_in_callback(data, true);
    error = data->set.fsockopt(data->set.sockopt_client,
                               sockfd,
                               CURLSOCKTYPE_IPCXN);
    Curl_set_in_callback(data, false);

    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;
    }







|
>







<












|









|











|

|

















|










|


|







1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157

1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
 *
 * 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 Curl_easy *data,
                                struct connectdata *conn,
                                const struct Curl_addrinfo *ai,
                                int tempindex)
{
  struct Curl_sockaddr_ex addr;
  int rc = -1;
  int error = 0;
  bool isconnected = FALSE;

  curl_socket_t sockfd;
  CURLcode result;
  char ipaddress[MAX_IPADR_LEN];
  long port;
  bool is_tcp;
#ifdef TCP_FASTOPEN_CONNECT
  int optval = 1;
#endif
  char buffer[STRERROR_LEN];
  curl_socket_t *sockp = &conn->tempsock[tempindex];
  *sockp = CURL_SOCKET_BAD;

  result = Curl_socket(data, ai, &addr, &sockfd);
  if(result)
    return result;

  /* store remote address and port used in this connection attempt */
  if(!Curl_addr2string((struct sockaddr*)&addr.sa_addr, addr.addrlen,
                       ipaddress, &port)) {
    /* malformed address or bug in inet_ntop, try next address */
    failf(data, "sa_addr inet_ntop() failed with errno %d: %s",
          errno, Curl_strerror(errno, buffer, sizeof(buffer)));
    Curl_closesocket(data, conn, sockfd);
    return CURLE_OK;
  }
  infof(data, "  Trying %s:%ld...\n", ipaddress, port);

#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(data, sockfd);

  nosigpipe(data, sockfd);

  Curl_sndbufset(sockfd);

  if(is_tcp && data->set.tcp_keepalive)
    tcpkeepalive(data, sockfd);

  if(data->set.fsockopt) {
    /* activate callback for setting socket options */
    Curl_set_in_callback(data, true);
    error = data->set.fsockopt(data->set.sockopt_client,
                               sockfd,
                               CURLSOCKTYPE_IPCXN);
    Curl_set_in_callback(data, false);

    if(error == CURL_SOCKOPT_ALREADY_CONNECTED)
      isconnected = TRUE;
    else if(error) {
      Curl_closesocket(data, 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(data, sockfd, addr.family,
                       Curl_ipv6_scope((struct sockaddr*)&addr.sa_addr));
    if(result) {
      Curl_closesocket(data, 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;
    }
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278

    if(-1 == rc)
      error = SOCKERRNO;
#ifdef ENABLE_QUIC
    else if(conn->transport == TRNSPRT_QUIC) {
      /* pass in 'sockfd' separately since it hasn't been put into the
         tempsock array at this point */
      result = Curl_quic_connect(conn, sockfd, tempindex,
                                 &addr.sa_addr, addr.addrlen);
      if(result)
        error = SOCKERRNO;
    }
#endif
  }
  else {







|







1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301

    if(-1 == rc)
      error = SOCKERRNO;
#ifdef ENABLE_QUIC
    else if(conn->transport == TRNSPRT_QUIC) {
      /* pass in 'sockfd' separately since it hasn't been put into the
         tempsock array at this point */
      result = Curl_quic_connect(data, conn, sockfd, tempindex,
                                 &addr.sa_addr, addr.addrlen);
      if(result)
        error = SOCKERRNO;
    }
#endif
  }
  else {
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323

1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
    default:
      /* unknown error, fallthrough and try another address! */
      infof(data, "Immediate connect fail for %s: %s\n",
            ipaddress, Curl_strerror(error, buffer, sizeof(buffer)));
      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.
 */

CURLcode Curl_connecthost(struct connectdata *conn,  /* context */

                          const struct Curl_dns_entry *remotehost)
{
  struct Curl_easy *data = conn->data;
  CURLcode result = CURLE_COULDNT_CONNECT;
  int i;
  timediff_t timeout_ms = Curl_timeleft(data, NULL, TRUE);

  if(timeout_ms < 0) {
    /* a precaution, no need to continue if time already is up */
    failf(data, "Connection time-out");







|
















|
>


<







1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349

1350
1351
1352
1353
1354
1355
1356
    default:
      /* unknown error, fallthrough and try another address! */
      infof(data, "Immediate connect fail for %s: %s\n",
            ipaddress, Curl_strerror(error, buffer, sizeof(buffer)));
      data->state.os_errno = error;

      /* connect failed */
      Curl_closesocket(data, 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.
 */

CURLcode Curl_connecthost(struct Curl_easy *data,
                          struct connectdata *conn,  /* context */
                          const struct Curl_dns_entry *remotehost)
{

  CURLcode result = CURLE_COULDNT_CONNECT;
  int i;
  timediff_t timeout_ms = Curl_timeleft(data, NULL, TRUE);

  if(timeout_ms < 0) {
    /* a precaution, no need to continue if time already is up */
    failf(data, "Connection time-out");
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384

1385
1386

1387
1388
1389
1390
1391
1392
1393
  DEBUGF(infof(data, "family0 == %s, family1 == %s\n",
               conn->tempfamily[0] == AF_INET ? "v4" : "v6",
               conn->tempfamily[1] == AF_INET ? "v4" : "v6"));

  /* get through the list in family order in case of quick failures */
  for(i = 0; (i < 2) && result; i++) {
    while(conn->tempaddr[i]) {
      result = singleipconnect(conn, conn->tempaddr[i], i);
      if(!result)
        break;
      ainext(conn, i, TRUE);
    }
  }
  if(result)
    return result;

  Curl_expire(conn->data, data->set.happy_eyeballs_timeout,
              EXPIRE_HAPPY_EYEBALLS);

  return CURLE_OK;
}

struct connfind {
  long id_tofind;
  struct connectdata *found;
};

static int conn_is_conn(struct connectdata *conn, void *param)

{
  struct connfind *f = (struct connfind *)param;

  if(conn->connection_id == f->id_tofind) {
    f->found = conn;
    return 1;
  }
  return 0;
}








|








|










|
>


>







1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
  DEBUGF(infof(data, "family0 == %s, family1 == %s\n",
               conn->tempfamily[0] == AF_INET ? "v4" : "v6",
               conn->tempfamily[1] == AF_INET ? "v4" : "v6"));

  /* get through the list in family order in case of quick failures */
  for(i = 0; (i < 2) && result; i++) {
    while(conn->tempaddr[i]) {
      result = singleipconnect(data, conn, conn->tempaddr[i], i);
      if(!result)
        break;
      ainext(conn, i, TRUE);
    }
  }
  if(result)
    return result;

  Curl_expire(data, data->set.happy_eyeballs_timeout,
              EXPIRE_HAPPY_EYEBALLS);

  return CURLE_OK;
}

struct connfind {
  long id_tofind;
  struct connectdata *found;
};

static int conn_is_conn(struct Curl_easy *data,
                        struct connectdata *conn, void *param)
{
  struct connfind *f = (struct connfind *)param;
  (void)data;
  if(conn->connection_id == f->id_tofind) {
    f->found = conn;
    return 1;
  }
  return 0;
}

1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
}

/*
 * Close a socket.
 *
 * 'conn' can be NULL, beware!
 */
int Curl_closesocket(struct connectdata *conn,
                      curl_socket_t sock)
{
  if(conn && conn->fclosesocket) {
    if((sock == conn->sock[SECONDARYSOCKET]) && conn->bits.sock_accepted)
      /* 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->bits.sock_accepted = FALSE;
    else {
      int rc;
      Curl_multi_closed(conn->data, sock);
      Curl_set_in_callback(conn->data, true);
      rc = conn->fclosesocket(conn->closesocket_client, sock);
      Curl_set_in_callback(conn->data, false);
      return rc;
    }
  }

  if(conn)
    /* tell the multi-socket code about this */
    Curl_multi_closed(conn->data, 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!
 *
 */
CURLcode Curl_socket(struct connectdata *conn,
                     const struct Curl_addrinfo *ai,
                     struct Curl_sockaddr_ex *addr,
                     curl_socket_t *sockfd)
{
  struct Curl_easy *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;

  /*







|
|









|
|

|






|















|




|







1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
}

/*
 * Close a socket.
 *
 * 'conn' can be NULL, beware!
 */
int Curl_closesocket(struct Curl_easy *data, struct connectdata *conn,
                     curl_socket_t sock)
{
  if(conn && conn->fclosesocket) {
    if((sock == conn->sock[SECONDARYSOCKET]) && conn->bits.sock_accepted)
      /* 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->bits.sock_accepted = FALSE;
    else {
      int rc;
      Curl_multi_closed(data, sock);
      Curl_set_in_callback(data, true);
      rc = conn->fclosesocket(conn->closesocket_client, sock);
      Curl_set_in_callback(data, false);
      return rc;
    }
  }

  if(conn)
    /* tell the multi-socket code about this */
    Curl_multi_closed(data, 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!
 *
 */
CURLcode Curl_socket(struct Curl_easy *data,
                     const struct Curl_addrinfo *ai,
                     struct Curl_sockaddr_ex *addr,
                     curl_socket_t *sockfd)
{
  struct connectdata *conn = data->conn;
  struct Curl_sockaddr_ex dummy;

  if(!addr)
    /* if the caller doesn't want info back, use a local temp copy */
    addr = &dummy;

  /*
1564
1565
1566
1567
1568
1569
1570






1571



1572




1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585







1586
1587
1588
1589
1590
1591

1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
#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;








}

/*
 * Curl_conncontrol() marks streams or connection for closure.
 */
void Curl_conncontrol(struct connectdata *conn,
                      int ctrl /* see defines in header */
#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
                      , const char *reason
#endif
  )
{
  /* close if a connection, or a stream that isn't multiplexed */







  bool closeit = (ctrl == CONNCTRL_CONNECTION) ||
    ((ctrl == CONNCTRL_STREAM) && !(conn->handler->flags & PROTOPT_STREAM));
  DEBUGASSERT(conn);
  if((ctrl == CONNCTRL_STREAM) &&
     (conn->handler->flags & PROTOPT_STREAM))
    DEBUGF(infof(conn->data, "Kill stream: %s\n", reason));

  else if((bit)closeit != conn->bits.close) {
    DEBUGF(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 */
  }
}

/* Data received can be cached at various levels, so check them all here. */
bool Curl_conn_data_pending(struct connectdata *conn, int sockindex)







>
>
>
>
>
>
|
>
>
>
|
>
>
>
>












|
>
>
>
>
>
>
>
|

<


<
>

<
<







1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632

1633
1634

1635
1636


1637
1638
1639
1640
1641
1642
1643
#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

#if defined(__linux__) && defined(IP_RECVERR)
  if(addr->socktype == SOCK_DGRAM) {
    int one = 1;
    switch(addr->family) {
    case AF_INET:
      (void)setsockopt(*sockfd, SOL_IP, IP_RECVERR, &one, sizeof(one));
      break;
    case AF_INET6:
      (void)setsockopt(*sockfd, SOL_IPV6, IPV6_RECVERR, &one, sizeof(one));
      break;
    }
  }
#endif

  return CURLE_OK;
}

/*
 * Curl_conncontrol() marks streams or connection for closure.
 */
void Curl_conncontrol(struct connectdata *conn,
                      int ctrl /* see defines in header */
#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
                      , const char *reason
#endif
  )
{
  /* close if a connection, or a stream that isn't multiplexed. */
  /* This function will be called both before and after this connection is
     associated with a transfer. */
  bool closeit;
  DEBUGASSERT(conn);
#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
  (void)reason; /* useful for debugging */
#endif
  closeit = (ctrl == CONNCTRL_CONNECTION) ||
    ((ctrl == CONNCTRL_STREAM) && !(conn->handler->flags & PROTOPT_STREAM));

  if((ctrl == CONNCTRL_STREAM) &&
     (conn->handler->flags & PROTOPT_STREAM))

    ;
  else if((bit)closeit != conn->bits.close) {


    conn->bits.close = closeit; /* the only place in the source code that
                                   should assign this bit */
  }
}

/* Data received can be cached at various levels, so check them all here. */
bool Curl_conn_data_pending(struct connectdata *conn, int sockindex)
Changes to jni/curl/lib/connect.h.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30

31
32
33
34

35
36
37
38
39
40
41
#ifndef HEADER_CURL_CONNECT_H
#define HEADER_CURL_CONNECT_H
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2020, 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 https://curl.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"
#include "timeval.h"

CURLcode Curl_is_connected(struct connectdata *conn,

                           int sockindex,
                           bool *connected);

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 */
timediff_t Curl_timeleft(struct Curl_easy *data,
                         struct curltime *nowp,
                         bool duringconnect);









|



















|
>



|
>







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
#ifndef HEADER_CURL_CONNECT_H
#define HEADER_CURL_CONNECT_H
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2021, 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 https://curl.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"
#include "timeval.h"

CURLcode Curl_is_connected(struct Curl_easy *data,
                           struct connectdata *conn,
                           int sockindex,
                           bool *connected);

CURLcode Curl_connecthost(struct Curl_easy *data,
                          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 */
timediff_t Curl_timeleft(struct Curl_easy *data,
                         struct curltime *nowp,
                         bool duringconnect);
70
71
72
73
74
75
76

77
78
79


80


81
82
83
84
85
86
87
88

*/
void Curl_sndbufset(curl_socket_t sockfd);
#else
#define Curl_sndbufset(y) Curl_nop_stmt
#endif


void Curl_updateconninfo(struct connectdata *conn, curl_socket_t sockfd);
void Curl_conninfo_remote(struct connectdata *conn, curl_socket_t sockfd);
void Curl_conninfo_local(struct connectdata *conn, curl_socket_t sockfd);


void Curl_persistconninfo(struct connectdata *conn);


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.







>
|
|
|
>
>
|
>
>
|







72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95

*/
void Curl_sndbufset(curl_socket_t sockfd);
#else
#define Curl_sndbufset(y) Curl_nop_stmt
#endif

void Curl_updateconninfo(struct Curl_easy *data, struct connectdata *conn,
                         curl_socket_t sockfd);
void Curl_conninfo_remote(struct Curl_easy *data, struct connectdata *conn,
                          curl_socket_t sockfd);
void Curl_conninfo_local(struct Curl_easy *data, curl_socket_t sockfd,
                         char *local_ip, long *local_port);
void Curl_persistconninfo(struct Curl_easy *data, struct connectdata *conn,
                          char *local_ip, long local_port);
int Curl_closesocket(struct Curl_easy *data, 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.
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
/*
 * 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!
 *
 */
CURLcode Curl_socket(struct connectdata *conn,
                     const struct Curl_addrinfo *ai,
                     struct Curl_sockaddr_ex *addr,
                     curl_socket_t *sockfd);

/*
 * Curl_conncontrol() marks the end of a connection/stream. The 'closeit'
 * argument specifies if it is the end of a connection or a stream.







|







109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
/*
 * 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!
 *
 */
CURLcode Curl_socket(struct Curl_easy *data,
                     const struct Curl_addrinfo *ai,
                     struct Curl_sockaddr_ex *addr,
                     curl_socket_t *sockfd);

/*
 * Curl_conncontrol() marks the end of a connection/stream. The 'closeit'
 * argument specifies if it is the end of a connection or a stream.
Changes to jni/curl/lib/content_encoding.c.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2020, 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 https://curl.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







|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2021, 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 https://curl.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
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
zfree_cb(voidpf opaque, voidpf ptr)
{
  (void) opaque;
  free(ptr);
}

static CURLcode
process_zlib_error(struct connectdata *conn, z_stream *z)
{
  struct Curl_easy *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(struct connectdata *conn,
          z_stream *z, zlibInitState *zlib_init, CURLcode result)
{
  if(*zlib_init == ZLIB_GZIP_HEADER)
    Curl_safefree(z->next_in);

  if(*zlib_init != ZLIB_UNINIT) {
    if(inflateEnd(z) != Z_OK && result == CURLE_OK)
      result = process_zlib_error(conn, z);
    *zlib_init = ZLIB_UNINIT;
  }

  return result;
}

static CURLcode process_trailer(struct connectdata *conn,
                                struct zlib_params *zp)
{
  z_stream *z = &zp->z;
  CURLcode result = CURLE_OK;
  uInt len = z->avail_in < zp->trailerlen? z->avail_in: zp->trailerlen;

  /* Consume expected trailer bytes. Terminate stream if exhausted.
     Issue an error if unexpected bytes follow. */

  zp->trailerlen -= len;
  z->avail_in -= len;
  z->next_in += len;
  if(z->avail_in)
    result = CURLE_WRITE_ERROR;
  if(result || !zp->trailerlen)
    result = exit_zlib(conn, z, &zp->zlib_init, result);
  else {
    /* Only occurs for gzip with zlib < 1.2.0.4 or raw deflate. */
    zp->zlib_init = ZLIB_EXTERNAL_TRAILER;
  }
  return result;
}

static CURLcode inflate_stream(struct connectdata *conn,
                               struct contenc_writer *writer,
                               zlibInitState started)
{
  struct zlib_params *zp = (struct zlib_params *) &writer->params;
  z_stream *z = &zp->z;         /* zlib state structure */
  uInt nread = z->avail_in;
  Bytef *orig_in = z->next_in;
  bool done = FALSE;
  CURLcode result = CURLE_OK;   /* Curl_client_write status */
  char *decomp;                 /* Put the decompressed data here. */

  /* Check state. */
  if(zp->zlib_init != ZLIB_INIT &&
     zp->zlib_init != ZLIB_INFLATING &&
     zp->zlib_init != ZLIB_INIT_GZIP &&
     zp->zlib_init != ZLIB_GZIP_INFLATING)
    return exit_zlib(conn, z, &zp->zlib_init, CURLE_WRITE_ERROR);

  /* 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(conn, z, &zp->zlib_init, CURLE_OUT_OF_MEMORY);

  /* because the buffer size is fixed, iteratively decompress and transfer to
     the client via downstream_write function. */
  while(!done) {
    int status;                   /* zlib status */
    done = TRUE;








|

<











|







|






|















|







|
















|





|







100
101
102
103
104
105
106
107
108

109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
zfree_cb(voidpf opaque, voidpf ptr)
{
  (void) opaque;
  free(ptr);
}

static CURLcode
process_zlib_error(struct Curl_easy *data, z_stream *z)
{

  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(struct Curl_easy *data,
          z_stream *z, zlibInitState *zlib_init, CURLcode result)
{
  if(*zlib_init == ZLIB_GZIP_HEADER)
    Curl_safefree(z->next_in);

  if(*zlib_init != ZLIB_UNINIT) {
    if(inflateEnd(z) != Z_OK && result == CURLE_OK)
      result = process_zlib_error(data, z);
    *zlib_init = ZLIB_UNINIT;
  }

  return result;
}

static CURLcode process_trailer(struct Curl_easy *data,
                                struct zlib_params *zp)
{
  z_stream *z = &zp->z;
  CURLcode result = CURLE_OK;
  uInt len = z->avail_in < zp->trailerlen? z->avail_in: zp->trailerlen;

  /* Consume expected trailer bytes. Terminate stream if exhausted.
     Issue an error if unexpected bytes follow. */

  zp->trailerlen -= len;
  z->avail_in -= len;
  z->next_in += len;
  if(z->avail_in)
    result = CURLE_WRITE_ERROR;
  if(result || !zp->trailerlen)
    result = exit_zlib(data, z, &zp->zlib_init, result);
  else {
    /* Only occurs for gzip with zlib < 1.2.0.4 or raw deflate. */
    zp->zlib_init = ZLIB_EXTERNAL_TRAILER;
  }
  return result;
}

static CURLcode inflate_stream(struct Curl_easy *data,
                               struct contenc_writer *writer,
                               zlibInitState started)
{
  struct zlib_params *zp = (struct zlib_params *) &writer->params;
  z_stream *z = &zp->z;         /* zlib state structure */
  uInt nread = z->avail_in;
  Bytef *orig_in = z->next_in;
  bool done = FALSE;
  CURLcode result = CURLE_OK;   /* Curl_client_write status */
  char *decomp;                 /* Put the decompressed data here. */

  /* Check state. */
  if(zp->zlib_init != ZLIB_INIT &&
     zp->zlib_init != ZLIB_INFLATING &&
     zp->zlib_init != ZLIB_INIT_GZIP &&
     zp->zlib_init != ZLIB_GZIP_INFLATING)
    return exit_zlib(data, z, &zp->zlib_init, CURLE_WRITE_ERROR);

  /* 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(data, z, &zp->zlib_init, CURLE_OUT_OF_MEMORY);

  /* because the buffer size is fixed, iteratively decompress and transfer to
     the client via downstream_write function. */
  while(!done) {
    int status;                   /* zlib status */
    done = TRUE;

200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
    status = inflate(z, Z_SYNC_FLUSH);
#endif

    /* Flush output data if some. */
    if(z->avail_out != DSIZ) {
      if(status == Z_OK || status == Z_STREAM_END) {
        zp->zlib_init = started;      /* Data started. */
        result = Curl_unencode_write(conn, writer->downstream, decomp,
                                     DSIZ - z->avail_out);
        if(result) {
          exit_zlib(conn, z, &zp->zlib_init, result);
          break;
        }
      }
    }

    /* Dispatch by inflate() status. */
    switch(status) {
    case Z_OK:
      /* Always loop: there may be unflushed latched data in zlib state. */
      done = FALSE;
      break;
    case Z_BUF_ERROR:
      /* No more data to flush: just exit loop. */
      break;
    case Z_STREAM_END:
      result = process_trailer(conn, zp);
      break;
    case Z_DATA_ERROR:
      /* some servers seem to not generate zlib headers, so this is an attempt
         to fix and continue anyway */
      if(zp->zlib_init == ZLIB_INIT) {
        /* Do not use inflateReset2(): only available since zlib 1.2.3.4. */
        (void) inflateEnd(z);     /* don't care about the return code */
        if(inflateInit2(z, -MAX_WBITS) == Z_OK) {
          z->next_in = orig_in;
          z->avail_in = nread;
          zp->zlib_init = ZLIB_INFLATING;
          zp->trailerlen = 4; /* Tolerate up to 4 unknown trailer bytes. */
          done = FALSE;
          break;
        }
        zp->zlib_init = ZLIB_UNINIT;    /* inflateEnd() already called. */
      }
      /* FALLTHROUGH */
    default:
      result = exit_zlib(conn, z, &zp->zlib_init, process_zlib_error(conn, z));
      break;
    }
  }
  free(decomp);

  /* We're about to leave this call so the `nread' data bytes won't be seen
     again. If we are in a state that would wrongly allow restart in raw mode
     at the next call, assume output has already started. */
  if(nread && zp->zlib_init == ZLIB_INIT)
    zp->zlib_init = started;      /* Cannot restart anymore. */

  return result;
}


/* Deflate handler. */
static CURLcode deflate_init_writer(struct connectdata *conn,
                                    struct contenc_writer *writer)
{
  struct zlib_params *zp = (struct zlib_params *) &writer->params;
  z_stream *z = &zp->z;     /* zlib state structure */

  if(!writer->downstream)
    return CURLE_WRITE_ERROR;

  /* Initialize zlib */
  z->zalloc = (alloc_func) zalloc_cb;
  z->zfree = (free_func) zfree_cb;

  if(inflateInit(z) != Z_OK)
    return process_zlib_error(conn, z);
  zp->zlib_init = ZLIB_INIT;
  return CURLE_OK;
}

static CURLcode deflate_unencode_write(struct connectdata *conn,
                                       struct contenc_writer *writer,
                                       const char *buf, size_t nbytes)
{
  struct zlib_params *zp = (struct zlib_params *) &writer->params;
  z_stream *z = &zp->z;     /* zlib state structure */

  /* Set the compressed input when this function is called */
  z->next_in = (Bytef *) buf;
  z->avail_in = (uInt) nbytes;

  if(zp->zlib_init == ZLIB_EXTERNAL_TRAILER)
    return process_trailer(conn, zp);

  /* Now uncompress the data */
  return inflate_stream(conn, writer, ZLIB_INFLATING);
}

static void deflate_close_writer(struct connectdata *conn,
                                 struct contenc_writer *writer)
{
  struct zlib_params *zp = (struct zlib_params *) &writer->params;
  z_stream *z = &zp->z;     /* zlib state structure */

  exit_zlib(conn, z, &zp->zlib_init, CURLE_OK);
}

static const struct content_encoding deflate_encoding = {
  "deflate",
  NULL,
  deflate_init_writer,
  deflate_unencode_write,
  deflate_close_writer,
  sizeof(struct zlib_params)
};


/* Gzip handler. */
static CURLcode gzip_init_writer(struct connectdata *conn,
                                 struct contenc_writer *writer)
{
  struct zlib_params *zp = (struct zlib_params *) &writer->params;
  z_stream *z = &zp->z;     /* zlib state structure */

  if(!writer->downstream)
    return CURLE_WRITE_ERROR;

  /* Initialize zlib */
  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);
    }
    zp->zlib_init = ZLIB_INIT_GZIP; /* Transparent gzip decompress state */
  }
  else {
    /* we must parse the gzip header and trailer ourselves */
    if(inflateInit2(z, -MAX_WBITS) != Z_OK) {
      return process_zlib_error(conn, z);
    }
    zp->trailerlen = 8; /* A CRC-32 and a 32-bit input size (RFC 1952, 2.2) */
    zp->zlib_init = ZLIB_INIT; /* Initial call state */
  }

  return CURLE_OK;
}







|


|















|



















|
















|













|




|











|


|


|





|













|















|






|







199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
    status = inflate(z, Z_SYNC_FLUSH);
#endif

    /* Flush output data if some. */
    if(z->avail_out != DSIZ) {
      if(status == Z_OK || status == Z_STREAM_END) {
        zp->zlib_init = started;      /* Data started. */
        result = Curl_unencode_write(data, writer->downstream, decomp,
                                     DSIZ - z->avail_out);
        if(result) {
          exit_zlib(data, z, &zp->zlib_init, result);
          break;
        }
      }
    }

    /* Dispatch by inflate() status. */
    switch(status) {
    case Z_OK:
      /* Always loop: there may be unflushed latched data in zlib state. */
      done = FALSE;
      break;
    case Z_BUF_ERROR:
      /* No more data to flush: just exit loop. */
      break;
    case Z_STREAM_END:
      result = process_trailer(data, zp);
      break;
    case Z_DATA_ERROR:
      /* some servers seem to not generate zlib headers, so this is an attempt
         to fix and continue anyway */
      if(zp->zlib_init == ZLIB_INIT) {
        /* Do not use inflateReset2(): only available since zlib 1.2.3.4. */
        (void) inflateEnd(z);     /* don't care about the return code */
        if(inflateInit2(z, -MAX_WBITS) == Z_OK) {
          z->next_in = orig_in;
          z->avail_in = nread;
          zp->zlib_init = ZLIB_INFLATING;
          zp->trailerlen = 4; /* Tolerate up to 4 unknown trailer bytes. */
          done = FALSE;
          break;
        }
        zp->zlib_init = ZLIB_UNINIT;    /* inflateEnd() already called. */
      }
      /* FALLTHROUGH */
    default:
      result = exit_zlib(data, z, &zp->zlib_init, process_zlib_error(data, z));
      break;
    }
  }
  free(decomp);

  /* We're about to leave this call so the `nread' data bytes won't be seen
     again. If we are in a state that would wrongly allow restart in raw mode
     at the next call, assume output has already started. */
  if(nread && zp->zlib_init == ZLIB_INIT)
    zp->zlib_init = started;      /* Cannot restart anymore. */

  return result;
}


/* Deflate handler. */
static CURLcode deflate_init_writer(struct Curl_easy *data,
                                    struct contenc_writer *writer)
{
  struct zlib_params *zp = (struct zlib_params *) &writer->params;
  z_stream *z = &zp->z;     /* zlib state structure */

  if(!writer->downstream)
    return CURLE_WRITE_ERROR;

  /* Initialize zlib */
  z->zalloc = (alloc_func) zalloc_cb;
  z->zfree = (free_func) zfree_cb;

  if(inflateInit(z) != Z_OK)
    return process_zlib_error(data, z);
  zp->zlib_init = ZLIB_INIT;
  return CURLE_OK;
}

static CURLcode deflate_unencode_write(struct Curl_easy *data,
                                       struct contenc_writer *writer,
                                       const char *buf, size_t nbytes)
{
  struct zlib_params *zp = (struct zlib_params *) &writer->params;
  z_stream *z = &zp->z;     /* zlib state structure */

  /* Set the compressed input when this function is called */
  z->next_in = (Bytef *) buf;
  z->avail_in = (uInt) nbytes;

  if(zp->zlib_init == ZLIB_EXTERNAL_TRAILER)
    return process_trailer(data, zp);

  /* Now uncompress the data */
  return inflate_stream(data, writer, ZLIB_INFLATING);
}

static void deflate_close_writer(struct Curl_easy *data,
                                 struct contenc_writer *writer)
{
  struct zlib_params *zp = (struct zlib_params *) &writer->params;
  z_stream *z = &zp->z;     /* zlib state structure */

  exit_zlib(data, z, &zp->zlib_init, CURLE_OK);
}

static const struct content_encoding deflate_encoding = {
  "deflate",
  NULL,
  deflate_init_writer,
  deflate_unencode_write,
  deflate_close_writer,
  sizeof(struct zlib_params)
};


/* Gzip handler. */
static CURLcode gzip_init_writer(struct Curl_easy *data,
                                 struct contenc_writer *writer)
{
  struct zlib_params *zp = (struct zlib_params *) &writer->params;
  z_stream *z = &zp->z;     /* zlib state structure */

  if(!writer->downstream)
    return CURLE_WRITE_ERROR;

  /* Initialize zlib */
  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(data, z);
    }
    zp->zlib_init = ZLIB_INIT_GZIP; /* Transparent gzip decompress state */
  }
  else {
    /* we must parse the gzip header and trailer ourselves */
    if(inflateInit2(z, -MAX_WBITS) != Z_OK) {
      return process_zlib_error(data, z);
    }
    zp->trailerlen = 8; /* A CRC-32 and a 32-bit input size (RFC 1952, 2.2) */
    zp->zlib_init = ZLIB_INIT; /* Initial call state */
  }

  return CURLE_OK;
}
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
  }

  *headerlen = totallen - len;
  return GZIP_OK;
}
#endif

static CURLcode gzip_unencode_write(struct connectdata *conn,
                                    struct contenc_writer *writer,
                                    const char *buf, size_t nbytes)
{
  struct zlib_params *zp = (struct zlib_params *) &writer->params;
  z_stream *z = &zp->z;     /* zlib state structure */

  if(zp->zlib_init == ZLIB_INIT_GZIP) {
    /* Let zlib handle the gzip decompression entirely */
    z->next_in = (Bytef *) buf;
    z->avail_in = (uInt) nbytes;
    /* Now uncompress the data */
    return inflate_stream(conn, writer, ZLIB_INIT_GZIP);
  }

#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(conn, z, &zp->zlib_init, CURLE_WRITE_ERROR);

#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.







|











|





|







428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
  }

  *headerlen = totallen - len;
  return GZIP_OK;
}
#endif

static CURLcode gzip_unencode_write(struct Curl_easy *data,
                                    struct contenc_writer *writer,
                                    const char *buf, size_t nbytes)
{
  struct zlib_params *zp = (struct zlib_params *) &writer->params;
  z_stream *z = &zp->z;     /* zlib state structure */

  if(zp->zlib_init == ZLIB_INIT_GZIP) {
    /* Let zlib handle the gzip decompression entirely */
    z->next_in = (Bytef *) buf;
    z->avail_in = (uInt) nbytes;
    /* Now uncompress the data */
    return inflate_stream(data, writer, ZLIB_INIT_GZIP);
  }

#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(data, z, &zp->zlib_init, CURLE_WRITE_ERROR);

#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.
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
       * 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) nbytes;
      z->next_in = malloc(z->avail_in);
      if(z->next_in == NULL) {
        return exit_zlib(conn, z, &zp->zlib_init, CURLE_OUT_OF_MEMORY);
      }
      memcpy(z->next_in, buf, z->avail_in);
      zp->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(conn, z, &zp->zlib_init, process_zlib_error(conn, z));
    }

  }
  break;

  case ZLIB_GZIP_HEADER:
  {
    /* Need more gzip header data state */
    ssize_t hlen;
    z->avail_in += (uInt) nbytes;
    z->next_in = Curl_saferealloc(z->next_in, z->avail_in);
    if(z->next_in == NULL) {
      return exit_zlib(conn, z, &zp->zlib_init, CURLE_OUT_OF_MEMORY);
    }
    /* Append the new block of data to the previous one */
    memcpy(z->next_in + z->avail_in - nbytes, buf, nbytes);

    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 *) buf + hlen + nbytes - z->avail_in;
      z->avail_in = (uInt) (z->avail_in - hlen);
      zp->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:
      return exit_zlib(conn, z, &zp->zlib_init, process_zlib_error(conn, z));
    }

  }
  break;

  case ZLIB_EXTERNAL_TRAILER:
    z->next_in = (Bytef *) buf;
    z->avail_in = (uInt) nbytes;
    return process_trailer(conn, zp);

  case ZLIB_GZIP_INFLATING:
  default:
    /* Inflating stream state */
    z->next_in = (Bytef *) buf;
    z->avail_in = (uInt) nbytes;
    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, writer, ZLIB_GZIP_INFLATING);
#endif
}

static void gzip_close_writer(struct connectdata *conn,
                              struct contenc_writer *writer)
{
  struct zlib_params *zp = (struct zlib_params *) &writer->params;
  z_stream *z = &zp->z;     /* zlib state structure */

  exit_zlib(conn, z, &zp->zlib_init, CURLE_OK);
}

static const struct content_encoding gzip_encoding = {
  "gzip",
  "x-gzip",
  gzip_init_writer,
  gzip_unencode_write,







|








|












|




















|








|















|



|





|







484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
       * 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) nbytes;
      z->next_in = malloc(z->avail_in);
      if(z->next_in == NULL) {
        return exit_zlib(data, z, &zp->zlib_init, CURLE_OUT_OF_MEMORY);
      }
      memcpy(z->next_in, buf, z->avail_in);
      zp->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(data, z, &zp->zlib_init, process_zlib_error(data, z));
    }

  }
  break;

  case ZLIB_GZIP_HEADER:
  {
    /* Need more gzip header data state */
    ssize_t hlen;
    z->avail_in += (uInt) nbytes;
    z->next_in = Curl_saferealloc(z->next_in, z->avail_in);
    if(z->next_in == NULL) {
      return exit_zlib(data, z, &zp->zlib_init, CURLE_OUT_OF_MEMORY);
    }
    /* Append the new block of data to the previous one */
    memcpy(z->next_in + z->avail_in - nbytes, buf, nbytes);

    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 *) buf + hlen + nbytes - z->avail_in;
      z->avail_in = (uInt) (z->avail_in - hlen);
      zp->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:
      return exit_zlib(data, z, &zp->zlib_init, process_zlib_error(data, z));
    }

  }
  break;

  case ZLIB_EXTERNAL_TRAILER:
    z->next_in = (Bytef *) buf;
    z->avail_in = (uInt) nbytes;
    return process_trailer(data, zp);

  case ZLIB_GZIP_INFLATING:
  default:
    /* Inflating stream state */
    z->next_in = (Bytef *) buf;
    z->avail_in = (uInt) nbytes;
    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(data, writer, ZLIB_GZIP_INFLATING);
#endif
}

static void gzip_close_writer(struct Curl_easy *data,
                              struct contenc_writer *writer)
{
  struct zlib_params *zp = (struct zlib_params *) &writer->params;
  z_stream *z = &zp->z;     /* zlib state structure */

  exit_zlib(data, z, &zp->zlib_init, CURLE_OK);
}

static const struct content_encoding gzip_encoding = {
  "gzip",
  "x-gzip",
  gzip_init_writer,
  gzip_unencode_write,
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
    return CURLE_OUT_OF_MEMORY;
  default:
    break;
  }
  return CURLE_WRITE_ERROR;
}

static CURLcode brotli_init_writer(struct connectdata *conn,
                                   struct contenc_writer *writer)
{
  struct brotli_params *bp = (struct brotli_params *) &writer->params;
  (void) conn;

  if(!writer->downstream)
    return CURLE_WRITE_ERROR;

  bp->br = BrotliDecoderCreateInstance(NULL, NULL, NULL);
  return bp->br? CURLE_OK: CURLE_OUT_OF_MEMORY;
}

static CURLcode brotli_unencode_write(struct connectdata *conn,
                                      struct contenc_writer *writer,
                                      const char *buf, size_t nbytes)
{
  struct brotli_params *bp = (struct brotli_params *) &writer->params;
  const uint8_t *src = (const uint8_t *) buf;
  char *decomp;
  uint8_t *dst;







|



|








|







621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
    return CURLE_OUT_OF_MEMORY;
  default:
    break;
  }
  return CURLE_WRITE_ERROR;
}

static CURLcode brotli_init_writer(struct Curl_easy *data,
                                   struct contenc_writer *writer)
{
  struct brotli_params *bp = (struct brotli_params *) &writer->params;
  (void) data;

  if(!writer->downstream)
    return CURLE_WRITE_ERROR;

  bp->br = BrotliDecoderCreateInstance(NULL, NULL, NULL);
  return bp->br? CURLE_OK: CURLE_OUT_OF_MEMORY;
}

static CURLcode brotli_unencode_write(struct Curl_easy *data,
                                      struct contenc_writer *writer,
                                      const char *buf, size_t nbytes)
{
  struct brotli_params *bp = (struct brotli_params *) &writer->params;
  const uint8_t *src = (const uint8_t *) buf;
  char *decomp;
  uint8_t *dst;
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674

  while((nbytes || r == BROTLI_DECODER_RESULT_NEEDS_MORE_OUTPUT) &&
        result == CURLE_OK) {
    dst = (uint8_t *) decomp;
    dstleft = DSIZ;
    r = BrotliDecoderDecompressStream(bp->br,
                                      &nbytes, &src, &dstleft, &dst, NULL);
    result = Curl_unencode_write(conn, writer->downstream,
                                 decomp, DSIZ - dstleft);
    if(result)
      break;
    switch(r) {
    case BROTLI_DECODER_RESULT_NEEDS_MORE_OUTPUT:
    case BROTLI_DECODER_RESULT_NEEDS_MORE_INPUT:
      break;







|







659
660
661
662
663
664
665
666
667
668
669
670
671
672
673

  while((nbytes || r == BROTLI_DECODER_RESULT_NEEDS_MORE_OUTPUT) &&
        result == CURLE_OK) {
    dst = (uint8_t *) decomp;
    dstleft = DSIZ;
    r = BrotliDecoderDecompressStream(bp->br,
                                      &nbytes, &src, &dstleft, &dst, NULL);
    result = Curl_unencode_write(data, writer->downstream,
                                 decomp, DSIZ - dstleft);
    if(result)
      break;
    switch(r) {
    case BROTLI_DECODER_RESULT_NEEDS_MORE_OUTPUT:
    case BROTLI_DECODER_RESULT_NEEDS_MORE_INPUT:
      break;
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
      break;
    }
  }
  free(decomp);
  return result;
}

static void brotli_close_writer(struct connectdata *conn,
                                struct contenc_writer *writer)
{
  struct brotli_params *bp = (struct brotli_params *) &writer->params;
  (void) conn;

  if(bp->br) {
    BrotliDecoderDestroyInstance(bp->br);
    bp->br = NULL;
  }
}








|



|







682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
      break;
    }
  }
  free(decomp);
  return result;
}

static void brotli_close_writer(struct Curl_easy *data,
                                struct contenc_writer *writer)
{
  struct brotli_params *bp = (struct brotli_params *) &writer->params;
  (void) data;

  if(bp->br) {
    BrotliDecoderDestroyInstance(bp->br);
    bp->br = NULL;
  }
}

713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
#ifdef HAVE_ZSTD
/* Writer parameters. */
struct zstd_params {
  ZSTD_DStream *zds;    /* State structure for zstd. */
  void *decomp;
};

static CURLcode zstd_init_writer(struct connectdata *conn,
                                 struct contenc_writer *writer)
{
  struct zstd_params *zp = (struct zstd_params *)&writer->params;
  (void)conn;

  if(!writer->downstream)
    return CURLE_WRITE_ERROR;

  zp->zds = ZSTD_createDStream();
  zp->decomp = NULL;
  return zp->zds ? CURLE_OK : CURLE_OUT_OF_MEMORY;
}

static CURLcode zstd_unencode_write(struct connectdata *conn,
    struct contenc_writer *writer,
    const char *buf, size_t nbytes)
{
  CURLcode result = CURLE_OK;
  struct zstd_params *zp = (struct zstd_params *)&writer->params;
  ZSTD_inBuffer in;
  ZSTD_outBuffer out;
  size_t errorCode;








|



|









|
|
|







712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
#ifdef HAVE_ZSTD
/* Writer parameters. */
struct zstd_params {
  ZSTD_DStream *zds;    /* State structure for zstd. */
  void *decomp;
};

static CURLcode zstd_init_writer(struct Curl_easy *data,
                                 struct contenc_writer *writer)
{
  struct zstd_params *zp = (struct zstd_params *)&writer->params;
  (void)data;

  if(!writer->downstream)
    return CURLE_WRITE_ERROR;

  zp->zds = ZSTD_createDStream();
  zp->decomp = NULL;
  return zp->zds ? CURLE_OK : CURLE_OUT_OF_MEMORY;
}

static CURLcode zstd_unencode_write(struct Curl_easy *data,
                                    struct contenc_writer *writer,
                                    const char *buf, size_t nbytes)
{
  CURLcode result = CURLE_OK;
  struct zstd_params *zp = (struct zstd_params *)&writer->params;
  ZSTD_inBuffer in;
  ZSTD_outBuffer out;
  size_t errorCode;

756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
    out.size = DSIZ;

    errorCode = ZSTD_decompressStream(zp->zds, &out, &in);
    if(ZSTD_isError(errorCode)) {
      return CURLE_BAD_CONTENT_ENCODING;
    }
    if(out.pos > 0) {
      result = Curl_unencode_write(conn, writer->downstream,
                                   zp->decomp, out.pos);
      if(result)
        break;
    }
    if((in.pos == nbytes) && (out.pos < out.size))
      break;
  }

  return result;
}

static void zstd_close_writer(struct connectdata *conn,
    struct contenc_writer *writer)
{
  struct zstd_params *zp = (struct zstd_params *)&writer->params;
  (void)conn;

  if(zp->decomp) {
    free(zp->decomp);
    zp->decomp = NULL;
  }
  if(zp->zds) {
    ZSTD_freeDStream(zp->zds);







|











|
|


|







755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
    out.size = DSIZ;

    errorCode = ZSTD_decompressStream(zp->zds, &out, &in);
    if(ZSTD_isError(errorCode)) {
      return CURLE_BAD_CONTENT_ENCODING;
    }
    if(out.pos > 0) {
      result = Curl_unencode_write(data, writer->downstream,
                                   zp->decomp, out.pos);
      if(result)
        break;
    }
    if((in.pos == nbytes) && (out.pos < out.size))
      break;
  }

  return result;
}

static void zstd_close_writer(struct Curl_easy *data,
                              struct contenc_writer *writer)
{
  struct zstd_params *zp = (struct zstd_params *)&writer->params;
  (void)data;

  if(zp->decomp) {
    free(zp->decomp);
    zp->decomp = NULL;
  }
  if(zp->zds) {
    ZSTD_freeDStream(zp->zds);
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
  zstd_close_writer,
  sizeof(struct zstd_params)
};
#endif


/* Identity handler. */
static CURLcode identity_init_writer(struct connectdata *conn,
                                     struct contenc_writer *writer)
{
  (void) conn;
  return writer->downstream? CURLE_OK: CURLE_WRITE_ERROR;
}

static CURLcode identity_unencode_write(struct connectdata *conn,
                                        struct contenc_writer *writer,
                                        const char *buf, size_t nbytes)
{
  return Curl_unencode_write(conn, writer->downstream, buf, nbytes);
}

static void identity_close_writer(struct connectdata *conn,
                                  struct contenc_writer *writer)
{
  (void) conn;
  (void) writer;
}

static const struct content_encoding identity_encoding = {
  "identity",
  "none",
  identity_init_writer,







|


|



|



|


|


|







795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
  zstd_close_writer,
  sizeof(struct zstd_params)
};
#endif


/* Identity handler. */
static CURLcode identity_init_writer(struct Curl_easy *data,
                                     struct contenc_writer *writer)
{
  (void) data;
  return writer->downstream? CURLE_OK: CURLE_WRITE_ERROR;
}

static CURLcode identity_unencode_write(struct Curl_easy *data,
                                        struct contenc_writer *writer,
                                        const char *buf, size_t nbytes)
{
  return Curl_unencode_write(data, writer->downstream, buf, nbytes);
}

static void identity_close_writer(struct Curl_easy *data,
                                  struct contenc_writer *writer)
{
  (void) data;
  (void) writer;
}

static const struct content_encoding identity_encoding = {
  "identity",
  "none",
  identity_init_writer,
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
  }

  return ace;
}


/* Real client writer: no downstream. */
static CURLcode client_init_writer(struct connectdata *conn,
                                   struct contenc_writer *writer)
{
  (void) conn;
  return writer->downstream? CURLE_WRITE_ERROR: CURLE_OK;
}

static CURLcode client_unencode_write(struct connectdata *conn,
                                      struct contenc_writer *writer,
                                      const char *buf, size_t nbytes)
{
  struct Curl_easy *data = conn->data;
  struct SingleRequest *k = &data->req;

  (void) writer;

  if(!nbytes || k->ignorebody)
    return CURLE_OK;

  return Curl_client_write(conn, CLIENTWRITE_BODY, (char *) buf, nbytes);
}

static void client_close_writer(struct connectdata *conn,
                                struct contenc_writer *writer)
{
  (void) conn;
  (void) writer;
}

static const struct content_encoding client_encoding = {
  NULL,
  NULL,
  client_init_writer,
  client_unencode_write,
  client_close_writer,
  0
};


/* Deferred error dummy writer. */
static CURLcode error_init_writer(struct connectdata *conn,
                                  struct contenc_writer *writer)
{
  (void) conn;
  return writer->downstream? CURLE_OK: CURLE_WRITE_ERROR;
}

static CURLcode error_unencode_write(struct connectdata *conn,
                                     struct contenc_writer *writer,
                                     const char *buf, size_t nbytes)
{
  char *all = Curl_all_content_encodings();

  (void) writer;
  (void) buf;
  (void) nbytes;

  if(!all)
    return CURLE_OUT_OF_MEMORY;
  failf(conn->data, "Unrecognized content encoding type. "
                    "libcurl understands %s content encodings.", all);
  free(all);
  return CURLE_BAD_CONTENT_ENCODING;
}

static void error_close_writer(struct connectdata *conn,
                               struct contenc_writer *writer)
{
  (void) conn;
  (void) writer;
}

static const struct content_encoding error_encoding = {
  NULL,
  NULL,
  error_init_writer,
  error_unencode_write,
  error_close_writer,
  0
};

/* Create an unencoding writer stage using the given handler. */
static struct contenc_writer *
new_unencoding_writer(struct connectdata *conn,
                      const struct content_encoding *handler,
                      struct contenc_writer *downstream)
{
  size_t sz = offsetof(struct contenc_writer, params) + handler->paramsize;
  struct contenc_writer *writer = (struct contenc_writer *)calloc(1, sz);

  if(writer) {
    writer->handler = handler;
    writer->downstream = downstream;
    if(handler->init_writer(conn, writer)) {
      free(writer);
      writer = NULL;
    }
  }

  return writer;
}

/* Write data using an unencoding writer stack. */
CURLcode Curl_unencode_write(struct connectdata *conn,
                             struct contenc_writer *writer,
                             const char *buf, size_t nbytes)
{
  if(!nbytes)
    return CURLE_OK;
  return writer->handler->unencode_write(conn, writer, buf, nbytes);
}

/* Close and clean-up the connection's writer stack. */
void Curl_unencode_cleanup(struct connectdata *conn)
{
  struct Curl_easy *data = conn->data;
  struct SingleRequest *k = &data->req;
  struct contenc_writer *writer = k->writer_stack;

  while(writer) {
    k->writer_stack = writer->downstream;
    writer->handler->close_writer(conn, writer);
    free(writer);
    writer = k->writer_stack;
  }
}

/* Find the content encoding by name. */
static const struct content_encoding *find_encoding(const char *name,







|


|



|



<







|


|


|














|


|



|











|
|




|


|














|









|









|





|



|

<





|







880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897

898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000

1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
  }

  return ace;
}


/* Real client writer: no downstream. */
static CURLcode client_init_writer(struct Curl_easy *data,
                                   struct contenc_writer *writer)
{
  (void) data;
  return writer->downstream? CURLE_WRITE_ERROR: CURLE_OK;
}

static CURLcode client_unencode_write(struct Curl_easy *data,
                                      struct contenc_writer *writer,
                                      const char *buf, size_t nbytes)
{

  struct SingleRequest *k = &data->req;

  (void) writer;

  if(!nbytes || k->ignorebody)
    return CURLE_OK;

  return Curl_client_write(data, CLIENTWRITE_BODY, (char *) buf, nbytes);
}

static void client_close_writer(struct Curl_easy *data,
                                struct contenc_writer *writer)
{
  (void) data;
  (void) writer;
}

static const struct content_encoding client_encoding = {
  NULL,
  NULL,
  client_init_writer,
  client_unencode_write,
  client_close_writer,
  0
};


/* Deferred error dummy writer. */
static CURLcode error_init_writer(struct Curl_easy *data,
                                  struct contenc_writer *writer)
{
  (void) data;
  return writer->downstream? CURLE_OK: CURLE_WRITE_ERROR;
}

static CURLcode error_unencode_write(struct Curl_easy *data,
                                     struct contenc_writer *writer,
                                     const char *buf, size_t nbytes)
{
  char *all = Curl_all_content_encodings();

  (void) writer;
  (void) buf;
  (void) nbytes;

  if(!all)
    return CURLE_OUT_OF_MEMORY;
  failf(data, "Unrecognized content encoding type. "
        "libcurl understands %s content encodings.", all);
  free(all);
  return CURLE_BAD_CONTENT_ENCODING;
}

static void error_close_writer(struct Curl_easy *data,
                               struct contenc_writer *writer)
{
  (void) data;
  (void) writer;
}

static const struct content_encoding error_encoding = {
  NULL,
  NULL,
  error_init_writer,
  error_unencode_write,
  error_close_writer,
  0
};

/* Create an unencoding writer stage using the given handler. */
static struct contenc_writer *
new_unencoding_writer(struct Curl_easy *data,
                      const struct content_encoding *handler,
                      struct contenc_writer *downstream)
{
  size_t sz = offsetof(struct contenc_writer, params) + handler->paramsize;
  struct contenc_writer *writer = (struct contenc_writer *)calloc(1, sz);

  if(writer) {
    writer->handler = handler;
    writer->downstream = downstream;
    if(handler->init_writer(data, writer)) {
      free(writer);
      writer = NULL;
    }
  }

  return writer;
}

/* Write data using an unencoding writer stack. */
CURLcode Curl_unencode_write(struct Curl_easy *data,
                             struct contenc_writer *writer,
                             const char *buf, size_t nbytes)
{
  if(!nbytes)
    return CURLE_OK;
  return writer->handler->unencode_write(data, writer, buf, nbytes);
}

/* Close and clean-up the connection's writer stack. */
void Curl_unencode_cleanup(struct Curl_easy *data)
{

  struct SingleRequest *k = &data->req;
  struct contenc_writer *writer = k->writer_stack;

  while(writer) {
    k->writer_stack = writer->downstream;
    writer->handler->close_writer(data, writer);
    free(writer);
    writer = k->writer_stack;
  }
}

/* Find the content encoding by name. */
static const struct content_encoding *find_encoding(const char *name,
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
      return ce;
  }
  return NULL;
}

/* Set-up the unencoding stack from the Content-Encoding header value.
 * See RFC 7231 section 3.1.2.2. */
CURLcode Curl_build_unencoding_stack(struct connectdata *conn,
                                     const char *enclist, int maybechunked)
{
  struct Curl_easy *data = conn->data;
  struct SingleRequest *k = &data->req;

  do {
    const char *name;
    size_t namelen;

    /* Parse a single encoding name. */
    while(ISSPACE(*enclist) || *enclist == ',')
      enclist++;

    name = enclist;

    for(namelen = 0; *enclist && *enclist != ','; enclist++)
      if(!ISSPACE(*enclist))
        namelen = enclist - name + 1;

    /* Special case: chunked encoding is handled at the reader level. */
    if(maybechunked && namelen == 7 && strncasecompare(name, "chunked", 7)) {
      k->chunk = TRUE;             /* chunks coming our way. */
      Curl_httpchunk_init(conn);   /* init our chunky engine. */
    }
    else if(namelen) {
      const struct content_encoding *encoding = find_encoding(name, namelen);
      struct contenc_writer *writer;

      if(!k->writer_stack) {
        k->writer_stack = new_unencoding_writer(conn, &client_encoding, NULL);

        if(!k->writer_stack)
          return CURLE_OUT_OF_MEMORY;
      }

      if(!encoding)
        encoding = &error_encoding;  /* Defer error at stack use. */

      /* Stack the unencoding stage. */
      writer = new_unencoding_writer(conn, encoding, k->writer_stack);
      if(!writer)
        return CURLE_OUT_OF_MEMORY;
      k->writer_stack = writer;
    }
  } while(*enclist);

  return CURLE_OK;
}

#else
/* Stubs for builds without HTTP. */
CURLcode Curl_build_unencoding_stack(struct connectdata *conn,
                                     const char *enclist, int maybechunked)
{
  (void) conn;
  (void) enclist;
  (void) maybechunked;
  return CURLE_NOT_BUILT_IN;
}

CURLcode Curl_unencode_write(struct connectdata *conn,
                             struct contenc_writer *writer,
                             const char *buf, size_t nbytes)
{
  (void) conn;
  (void) writer;
  (void) buf;
  (void) nbytes;
  return CURLE_NOT_BUILT_IN;
}

void Curl_unencode_cleanup(struct connectdata *conn)
{
  (void) conn;
}

char *Curl_all_content_encodings(void)
{
  return strdup(CONTENT_ENCODING_DEFAULT);  /* Satisfy caller. */
}

#endif /* CURL_DISABLE_HTTP */







|


<



















|






|









|











|


|





|



|






|

|








1022
1023
1024
1025
1026
1027
1028
1029
1030
1031

1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
      return ce;
  }
  return NULL;
}

/* Set-up the unencoding stack from the Content-Encoding header value.
 * See RFC 7231 section 3.1.2.2. */
CURLcode Curl_build_unencoding_stack(struct Curl_easy *data,
                                     const char *enclist, int maybechunked)
{

  struct SingleRequest *k = &data->req;

  do {
    const char *name;
    size_t namelen;

    /* Parse a single encoding name. */
    while(ISSPACE(*enclist) || *enclist == ',')
      enclist++;

    name = enclist;

    for(namelen = 0; *enclist && *enclist != ','; enclist++)
      if(!ISSPACE(*enclist))
        namelen = enclist - name + 1;

    /* Special case: chunked encoding is handled at the reader level. */
    if(maybechunked && namelen == 7 && strncasecompare(name, "chunked", 7)) {
      k->chunk = TRUE;             /* chunks coming our way. */
      Curl_httpchunk_init(data);   /* init our chunky engine. */
    }
    else if(namelen) {
      const struct content_encoding *encoding = find_encoding(name, namelen);
      struct contenc_writer *writer;

      if(!k->writer_stack) {
        k->writer_stack = new_unencoding_writer(data, &client_encoding, NULL);

        if(!k->writer_stack)
          return CURLE_OUT_OF_MEMORY;
      }

      if(!encoding)
        encoding = &error_encoding;  /* Defer error at stack use. */

      /* Stack the unencoding stage. */
      writer = new_unencoding_writer(data, encoding, k->writer_stack);
      if(!writer)
        return CURLE_OUT_OF_MEMORY;
      k->writer_stack = writer;
    }
  } while(*enclist);

  return CURLE_OK;
}

#else
/* Stubs for builds without HTTP. */
CURLcode Curl_build_unencoding_stack(struct Curl_easy *data,
                                     const char *enclist, int maybechunked)
{
  (void) data;
  (void) enclist;
  (void) maybechunked;
  return CURLE_NOT_BUILT_IN;
}

CURLcode Curl_unencode_write(struct Curl_easy *data,
                             struct contenc_writer *writer,
                             const char *buf, size_t nbytes)
{
  (void) data;
  (void) writer;
  (void) buf;
  (void) nbytes;
  return CURLE_NOT_BUILT_IN;
}

void Curl_unencode_cleanup(struct Curl_easy *data)
{
  (void) data;
}

char *Curl_all_content_encodings(void)
{
  return strdup(CONTENT_ENCODING_DEFAULT);  /* Satisfy caller. */
}

#endif /* CURL_DISABLE_HTTP */
Changes to jni/curl/lib/content_encoding.h.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#ifndef HEADER_CURL_CONTENT_ENCODING_H
#define HEADER_CURL_CONTENT_ENCODING_H
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2020, 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 https://curl.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









|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#ifndef HEADER_CURL_CONTENT_ENCODING_H
#define HEADER_CURL_CONTENT_ENCODING_H
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2021, 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 https://curl.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
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
  void *params;  /* Encoding-specific storage (variable length). */
};

/* Content encoding writer. */
struct content_encoding {
  const char *name;        /* Encoding name. */
  const char *alias;       /* Encoding name alias. */
  CURLcode (*init_writer)(struct connectdata *conn,
                          struct contenc_writer *writer);
  CURLcode (*unencode_write)(struct connectdata *conn,
                             struct contenc_writer *writer,
                             const char *buf, size_t nbytes);
  void (*close_writer)(struct connectdata *conn,
                       struct contenc_writer *writer);
  size_t paramsize;
};


CURLcode Curl_build_unencoding_stack(struct connectdata *conn,
                                     const char *enclist, int maybechunked);
CURLcode Curl_unencode_write(struct connectdata *conn,
                             struct contenc_writer *writer,
                             const char *buf, size_t nbytes);
void Curl_unencode_cleanup(struct connectdata *conn);
char *Curl_all_content_encodings(void);

#endif /* HEADER_CURL_CONTENT_ENCODING_H */







|

|


|





|

|


|



29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
  void *params;  /* Encoding-specific storage (variable length). */
};

/* Content encoding writer. */
struct content_encoding {
  const char *name;        /* Encoding name. */
  const char *alias;       /* Encoding name alias. */
  CURLcode (*init_writer)(struct Curl_easy *data,
                          struct contenc_writer *writer);
  CURLcode (*unencode_write)(struct Curl_easy *data,
                             struct contenc_writer *writer,
                             const char *buf, size_t nbytes);
  void (*close_writer)(struct Curl_easy *data,
                       struct contenc_writer *writer);
  size_t paramsize;
};


CURLcode Curl_build_unencoding_stack(struct Curl_easy *data,
                                     const char *enclist, int maybechunked);
CURLcode Curl_unencode_write(struct Curl_easy *data,
                             struct contenc_writer *writer,
                             const char *buf, size_t nbytes);
void Curl_unencode_cleanup(struct Curl_easy *data);
char *Curl_all_content_encodings(void);

#endif /* HEADER_CURL_CONTENT_ENCODING_H */
Changes to jni/curl/lib/cookie.c.
260
261
262
263
264
265
266





267
268
269
270
271
272
273
274
275
276
277
278
279
280
281




282
283
284
285
286
287
288

  if(outlen)
    *outlen = len;

  return first? first: domain;
}






/*
 * A case-insensitive hash for the cookie domains.
 */
static size_t cookie_hash_domain(const char *domain, const size_t len)
{
  const char *end = domain + len;
  size_t h = 5381;

  while(domain < end) {
    h += h << 5;
    h ^= Curl_raw_toupper(*domain++);
  }

  return (h % COOKIE_HASH_SIZE);
}





/*
 * Hash this domain.
 */
static size_t cookiehash(const char * const domain)
{
  const char *top;







>
>
>
>
>















>
>
>
>







260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297

  if(outlen)
    *outlen = len;

  return first? first: domain;
}

/* Avoid C1001, an "internal error" with MSVC14 */
#if defined(_MSC_VER) && (_MSC_VER == 1900)
#pragma optimize("", off)
#endif

/*
 * A case-insensitive hash for the cookie domains.
 */
static size_t cookie_hash_domain(const char *domain, const size_t len)
{
  const char *end = domain + len;
  size_t h = 5381;

  while(domain < end) {
    h += h << 5;
    h ^= Curl_raw_toupper(*domain++);
  }

  return (h % COOKIE_HASH_SIZE);
}

#if defined(_MSC_VER) && (_MSC_VER == 1900)
#pragma optimize("", on)
#endif

/*
 * Hash this domain.
 */
static size_t cookiehash(const char * const domain)
{
  const char *top;
Changes to jni/curl/lib/cookie.h.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#ifndef HEADER_CURL_COOKIE_H
#define HEADER_CURL_COOKIE_H
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2020, 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 https://curl.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









|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#ifndef HEADER_CURL_COOKIE_H
#define HEADER_CURL_COOKIE_H
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2021, 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 https://curl.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
30
31
32
33
34
35
36
37
38
39
40
41
42

43
44
45
46
47
48
49
  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;    /* whether we do tail-matching 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 */
  int creationtime;  /* time when the cookie was written */
  unsigned char prefix; /* bitmap fields indicating which prefix are set */
};








<





>







30
31
32
33
34
35
36

37
38
39
40
41
42
43
44
45
46
47
48
49
  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 */


  /* RFC 2109 keywords. Version=1 means 2109-compliant cookie sending */
  char *version;     /* Version = <value> */
  char *maxage;      /* Max-Age = <value> */

  bool tailmatch;    /* whether we do tail-matching of the domain name */
  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 */
  int creationtime;  /* time when the cookie was written */
  unsigned char prefix; /* bitmap fields indicating which prefix are set */
};

57
58
59
60
61
62
63
64
65

66
67
68
69
70
71
72
#define COOKIE_HASH_SIZE 256

struct CookieInfo {
  /* linked list of cookies we know of */
  struct Cookie *cookies[COOKIE_HASH_SIZE];

  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 */
  int lastct;      /* last creation-time used in the jar */
};

/* This is the maximum line length we accept for a cookie line. RFC 2109
   section 6.3 says:








<

>







57
58
59
60
61
62
63

64
65
66
67
68
69
70
71
72
#define COOKIE_HASH_SIZE 256

struct CookieInfo {
  /* linked list of cookies we know of */
  struct Cookie *cookies[COOKIE_HASH_SIZE];

  char *filename;  /* file we read from/write to */

  long numcookies; /* number of cookies in the "jar" */
  bool running;    /* state info, for cookie adding information */
  bool newsession; /* new session, discard session cookies on load */
  int lastct;      /* last creation-time used in the jar */
};

/* This is the maximum line length we accept for a cookie line. RFC 2109
   section 6.3 says:

Changes to jni/curl/lib/curl_addrinfo.c.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2020, 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 https://curl.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







|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2021, 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 https://curl.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
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
#ifdef ENABLE_IPV6
    if(he->h_addrtype == AF_INET6)
      ss_size = sizeof(struct sockaddr_in6);
    else
#endif
      ss_size = sizeof(struct sockaddr_in);

    /* allocate memory to told the struct, the address and the name */
    ai = calloc(1, sizeof(struct Curl_addrinfo) + ss_size + namelen);
    if(!ai) {
      result = CURLE_OUT_OF_MEMORY;
      break;
    }
    /* put the address after the struct */
    ai->ai_addr = (void *)((char *)ai + sizeof(struct Curl_addrinfo));







|







281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
#ifdef ENABLE_IPV6
    if(he->h_addrtype == AF_INET6)
      ss_size = sizeof(struct sockaddr_in6);
    else
#endif
      ss_size = sizeof(struct sockaddr_in);

    /* allocate memory to hold the struct, the address and the name */
    ai = calloc(1, sizeof(struct Curl_addrinfo) + ss_size + namelen);
    if(!ai) {
      result = CURLE_OUT_OF_MEMORY;
      break;
    }
    /* put the address after the struct */
    ai->ai_addr = (void *)((char *)ai + sizeof(struct Curl_addrinfo));
Changes to jni/curl/lib/curl_config.h.cmake.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2020, 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 https://curl.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







|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2021, 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 https://curl.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
997
998
999
1000
1001
1002
1003




1004
1005
1006
1007
1008
1009
1010
#cmakedefine HAVE_PK11_CREATEMANAGEDGENERICOBJECT 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





/* to enable NGHTTP2  */
#cmakedefine USE_NGHTTP2 1

/* to enable NGTCP2 */
#cmakedefine USE_NGTCP2 1








>
>
>
>







997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
#cmakedefine HAVE_PK11_CREATEMANAGEDGENERICOBJECT 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 don't want the OpenSSL configuration to be loaded
   automatically */
#cmakedefine CURL_DISABLE_OPENSSL_AUTO_LOAD_CONFIG 1

/* to enable NGHTTP2  */
#cmakedefine USE_NGHTTP2 1

/* to enable NGTCP2 */
#cmakedefine USE_NGTCP2 1

Changes to jni/curl/lib/curl_config.h.in.
329
330
331
332
333
334
335



336
337
338
339
340
341
342
#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 <idn2.h> header file. */
#undef HAVE_IDN2_H

/* Define to 1 if you have the <ifaddrs.h> header file. */
#undef HAVE_IFADDRS_H








>
>
>







329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
#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 <hyper.h> header file. */
#undef HAVE_HYPER_H

/* Define to 1 if you have the <idn2.h> header file. */
#undef HAVE_IDN2_H

/* Define to 1 if you have the <ifaddrs.h> header file. */
#undef HAVE_IFADDRS_H

991
992
993
994
995
996
997



998
999
1000
1001
1002
1003
1004
#undef USE_GNUTLS

/* if GnuTLS uses nettle as crypto backend */
#undef USE_GNUTLS_NETTLE

/* to enable HSTS */
#undef USE_HSTS




/* PSL support enabled */
#undef USE_LIBPSL

/* if librtmp is in use */
#undef USE_LIBRTMP








>
>
>







994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
#undef USE_GNUTLS

/* if GnuTLS uses nettle as crypto backend */
#undef USE_GNUTLS_NETTLE

/* to enable HSTS */
#undef USE_HSTS

/* if hyper is in use */
#undef USE_HYPER

/* PSL support enabled */
#undef USE_LIBPSL

/* if librtmp is in use */
#undef USE_LIBRTMP

Changes to jni/curl/lib/curl_gssapi.c.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 2011 - 2020, 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 https://curl.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







|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 2011 - 2021, 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 https://curl.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
127
128
129
130
131
132
133




134
135
136

  if(major != GSS_S_FAILURE)
    len = display_gss_error(major, GSS_C_GSS_CODE, buf, len);

  display_gss_error(minor, GSS_C_MECH_CODE, buf, len);

  infof(data, "%s%s\n", prefix, buf);




}

#endif /* HAVE_GSSAPI */







>
>
>
>



127
128
129
130
131
132
133
134
135
136
137
138
139
140

  if(major != GSS_S_FAILURE)
    len = display_gss_error(major, GSS_C_GSS_CODE, buf, len);

  display_gss_error(minor, GSS_C_MECH_CODE, buf, len);

  infof(data, "%s%s\n", prefix, buf);
#ifdef CURL_DISABLE_VERBOSE_STRINGS
  (void)data;
  (void)prefix;
#endif
}

#endif /* HAVE_GSSAPI */
Changes to jni/curl/lib/curl_krb5.h.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
#ifndef HEADER_CURL_KRB5_H
#define HEADER_CURL_KRB5_H
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2020, 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 https://curl.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
int Curl_sec_read_msg(struct connectdata *conn, char *,
                      enum protection_level);
void Curl_sec_end(struct connectdata *);
CURLcode Curl_sec_login(struct connectdata *);
int Curl_sec_request_prot(struct connectdata *conn, const char *level);
#else
#define Curl_sec_end(x)
#endif

#endif /* HEADER_CURL_KRB5_H */









|


















|












|


|






1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
#ifndef HEADER_CURL_KRB5_H
#define HEADER_CURL_KRB5_H
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2021, 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 https://curl.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 Curl_easy *data, 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
int Curl_sec_read_msg(struct Curl_easy *data, struct connectdata *conn, char *,
                      enum protection_level);
void Curl_sec_end(struct connectdata *);
CURLcode Curl_sec_login(struct Curl_easy *, struct connectdata *);
int Curl_sec_request_prot(struct connectdata *conn, const char *level);
#else
#define Curl_sec_end(x)
#endif

#endif /* HEADER_CURL_KRB5_H */
Changes to jni/curl/lib/curl_ntlm_wb.c.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2020, 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 https://curl.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







|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2021, 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 https://curl.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
325
326
327
328
329
330
331
332

333
334
335
336
337


338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379

380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
    return CURLE_OUT_OF_MEMORY;
  return CURLE_OK;
done:
  Curl_dyn_free(&b);
  return CURLE_REMOTE_ACCESS_DENIED;
}

CURLcode Curl_input_ntlm_wb(struct connectdata *conn,

                            bool proxy,
                            const char *header)
{
  struct ntlmdata *ntlm = proxy ? &conn->proxyntlm : &conn->ntlm;
  curlntlm *state = proxy ? &conn->proxy_ntlm_state : &conn->http_ntlm_state;



  if(!checkprefix("NTLM", header))
    return CURLE_BAD_CONTENT_ENCODING;

  header += strlen("NTLM");
  while(*header && ISSPACE(*header))
    header++;

  if(*header) {
    ntlm->challenge = strdup(header);
    if(!ntlm->challenge)
      return CURLE_OUT_OF_MEMORY;

    *state = NTLMSTATE_TYPE2; /* We got a type-2 message */
  }
  else {
    if(*state == NTLMSTATE_LAST) {
      infof(conn->data, "NTLM auth restarted\n");
      Curl_http_auth_cleanup_ntlm_wb(conn);
    }
    else if(*state == NTLMSTATE_TYPE3) {
      infof(conn->data, "NTLM handshake rejected\n");
      Curl_http_auth_cleanup_ntlm_wb(conn);
      *state = NTLMSTATE_NONE;
      return CURLE_REMOTE_ACCESS_DENIED;
    }
    else if(*state >= NTLMSTATE_TYPE1) {
      infof(conn->data, "NTLM handshake failure (internal error)\n");
      return CURLE_REMOTE_ACCESS_DENIED;
    }

    *state = NTLMSTATE_TYPE1; /* We should send away a type-1 */
  }

  return CURLE_OK;
}

/*
 * This is for creating ntlm header output by delegating challenge/response
 * to Samba's winbind daemon helper ntlm_auth.
 */
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;
  struct ntlmdata *ntlm;
  curlntlm *state;
  struct auth *authp;
  struct Curl_easy *data = conn->data;

  CURLcode res = CURLE_OK;

  DEBUGASSERT(conn);
  DEBUGASSERT(conn->data);

  if(proxy) {
#ifndef CURL_DISABLE_PROXY
    allocuserpwd = &data->state.aptr.proxyuserpwd;
    userp = conn->http_proxy.user;
    ntlm = &conn->proxyntlm;
    state = &conn->proxy_ntlm_state;
    authp = &conn->data->state.authproxy;
#else
    return CURLE_NOT_BUILT_IN;
#endif
  }
  else {
    allocuserpwd = &data->state.aptr.userpwd;
    userp = conn->user;
    ntlm = &conn->ntlm;
    state = &conn->http_ntlm_state;
    authp = &conn->data->state.authhost;
  }
  authp->done = FALSE;

  /* not set means empty */
  if(!userp)
    userp = "";








|
>





>
>

















|



|





|













|
>









<




|







|









|







325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392

393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
    return CURLE_OUT_OF_MEMORY;
  return CURLE_OK;
done:
  Curl_dyn_free(&b);
  return CURLE_REMOTE_ACCESS_DENIED;
}

CURLcode Curl_input_ntlm_wb(struct Curl_easy *data,
                            struct connectdata *conn,
                            bool proxy,
                            const char *header)
{
  struct ntlmdata *ntlm = proxy ? &conn->proxyntlm : &conn->ntlm;
  curlntlm *state = proxy ? &conn->proxy_ntlm_state : &conn->http_ntlm_state;

  (void) data;  /* In case it gets unused by nop log macros. */

  if(!checkprefix("NTLM", header))
    return CURLE_BAD_CONTENT_ENCODING;

  header += strlen("NTLM");
  while(*header && ISSPACE(*header))
    header++;

  if(*header) {
    ntlm->challenge = strdup(header);
    if(!ntlm->challenge)
      return CURLE_OUT_OF_MEMORY;

    *state = NTLMSTATE_TYPE2; /* We got a type-2 message */
  }
  else {
    if(*state == NTLMSTATE_LAST) {
      infof(data, "NTLM auth restarted\n");
      Curl_http_auth_cleanup_ntlm_wb(conn);
    }
    else if(*state == NTLMSTATE_TYPE3) {
      infof(data, "NTLM handshake rejected\n");
      Curl_http_auth_cleanup_ntlm_wb(conn);
      *state = NTLMSTATE_NONE;
      return CURLE_REMOTE_ACCESS_DENIED;
    }
    else if(*state >= NTLMSTATE_TYPE1) {
      infof(data, "NTLM handshake failure (internal error)\n");
      return CURLE_REMOTE_ACCESS_DENIED;
    }

    *state = NTLMSTATE_TYPE1; /* We should send away a type-1 */
  }

  return CURLE_OK;
}

/*
 * This is for creating ntlm header output by delegating challenge/response
 * to Samba's winbind daemon helper ntlm_auth.
 */
CURLcode Curl_output_ntlm_wb(struct Curl_easy *data, 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;
  struct ntlmdata *ntlm;
  curlntlm *state;
  struct auth *authp;


  CURLcode res = CURLE_OK;

  DEBUGASSERT(conn);
  DEBUGASSERT(data);

  if(proxy) {
#ifndef CURL_DISABLE_PROXY
    allocuserpwd = &data->state.aptr.proxyuserpwd;
    userp = conn->http_proxy.user;
    ntlm = &conn->proxyntlm;
    state = &conn->proxy_ntlm_state;
    authp = &data->state.authproxy;
#else
    return CURLE_NOT_BUILT_IN;
#endif
  }
  else {
    allocuserpwd = &data->state.aptr.userpwd;
    userp = conn->user;
    ntlm = &conn->ntlm;
    state = &conn->http_ntlm_state;
    authp = &data->state.authhost;
  }
  authp->done = FALSE;

  /* not set means empty */
  if(!userp)
    userp = "";

429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
     * 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->data, ntlm, userp);
    if(res)
      return res;
    res = ntlm_wb_response(conn->data, ntlm, "YR\n", *state);
    if(res)
      return res;

    free(*allocuserpwd);
    *allocuserpwd = aprintf("%sAuthorization: NTLM %s\r\n",
                            proxy ? "Proxy-" : "",
                            ntlm->response);
    DEBUG_OUT(fprintf(stderr, "**** Header %s\n ", *allocuserpwd));
    Curl_safefree(ntlm->response);
    if(!*allocuserpwd)
      return CURLE_OUT_OF_MEMORY;
    break;

  case NTLMSTATE_TYPE2: {
    char *input = aprintf("TT %s\n", ntlm->challenge);
    if(!input)
      return CURLE_OUT_OF_MEMORY;
    res = ntlm_wb_response(conn->data, ntlm, input, *state);
    free(input);
    if(res)
      return res;

    free(*allocuserpwd);
    *allocuserpwd = aprintf("%sAuthorization: NTLM %s\r\n",
                            proxy ? "Proxy-" : "",







|


|

















|







432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
     * 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(data, ntlm, userp);
    if(res)
      return res;
    res = ntlm_wb_response(data, ntlm, "YR\n", *state);
    if(res)
      return res;

    free(*allocuserpwd);
    *allocuserpwd = aprintf("%sAuthorization: NTLM %s\r\n",
                            proxy ? "Proxy-" : "",
                            ntlm->response);
    DEBUG_OUT(fprintf(stderr, "**** Header %s\n ", *allocuserpwd));
    Curl_safefree(ntlm->response);
    if(!*allocuserpwd)
      return CURLE_OUT_OF_MEMORY;
    break;

  case NTLMSTATE_TYPE2: {
    char *input = aprintf("TT %s\n", ntlm->challenge);
    if(!input)
      return CURLE_OUT_OF_MEMORY;
    res = ntlm_wb_response(data, ntlm, input, *state);
    free(input);
    if(res)
      return res;

    free(*allocuserpwd);
    *allocuserpwd = aprintf("%sAuthorization: NTLM %s\r\n",
                            proxy ? "Proxy-" : "",
Changes to jni/curl/lib/curl_ntlm_wb.h.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31

32
33
34
35

36
37
38
39
40
41
#ifndef HEADER_CURL_NTLM_WB_H
#define HEADER_CURL_NTLM_WB_H
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2020, 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 https://curl.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 ntlm header input */
CURLcode Curl_input_ntlm_wb(struct connectdata *conn, bool proxy,

                            const char *header);

/* this is for creating ntlm header output */
CURLcode Curl_output_ntlm_wb(struct connectdata *conn, bool proxy);


void Curl_http_auth_cleanup_ntlm_wb(struct connectdata *conn);

#endif /* !CURL_DISABLE_HTTP && USE_NTLM && NTLM_WB_ENABLED */

#endif /* HEADER_CURL_NTLM_WB_H */









|




















|
>



|
>






1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
#ifndef HEADER_CURL_NTLM_WB_H
#define HEADER_CURL_NTLM_WB_H
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2021, 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 https://curl.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 ntlm header input */
CURLcode Curl_input_ntlm_wb(struct Curl_easy *data,
                            struct connectdata *conn, bool proxy,
                            const char *header);

/* this is for creating ntlm header output */
CURLcode Curl_output_ntlm_wb(struct Curl_easy *data, struct connectdata *conn,
                             bool proxy);

void Curl_http_auth_cleanup_ntlm_wb(struct connectdata *conn);

#endif /* !CURL_DISABLE_HTTP && USE_NTLM && NTLM_WB_ENABLED */

#endif /* HEADER_CURL_NTLM_WB_H */
Changes to jni/curl/lib/curl_path.c.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2020, 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 https://curl.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







|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2021, 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 https://curl.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
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
#include <curl/curl.h>
#include "curl_memory.h"
#include "curl_path.h"
#include "escape.h"
#include "memdebug.h"

/* figure out the path to work with in this particular request */
CURLcode Curl_getworkingpath(struct connectdata *conn,
                             char *homedir,  /* when SFTP is used */
                             char **path) /* returns the  allocated
                                             real path to work with */
{
  struct Curl_easy *data = conn->data;
  char *real_path = NULL;
  char *working_path;
  size_t working_path_len;
  CURLcode result =
    Curl_urldecode(data, data->state.up.path, 0, &working_path,
                   &working_path_len, REJECT_ZERO);
  if(result)
    return result;

  /* 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, working_path_len - 2);
    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;
      }







|




<










|











|







27
28
29
30
31
32
33
34
35
36
37
38

39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
#include <curl/curl.h>
#include "curl_memory.h"
#include "curl_path.h"
#include "escape.h"
#include "memdebug.h"

/* figure out the path to work with in this particular request */
CURLcode Curl_getworkingpath(struct Curl_easy *data,
                             char *homedir,  /* when SFTP is used */
                             char **path) /* returns the  allocated
                                             real path to work with */
{

  char *real_path = NULL;
  char *working_path;
  size_t working_path_len;
  CURLcode result =
    Curl_urldecode(data, data->state.up.path, 0, &working_path,
                   &working_path_len, REJECT_ZERO);
  if(result)
    return result;

  /* Check for /~/, indicating relative to the user's home directory */
  if(data->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, working_path_len - 2);
    else
      memcpy(real_path, working_path, 1 + working_path_len);
  }
  else if(data->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;
      }
Changes to jni/curl/lib/curl_path.h.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#ifndef HEADER_CURL_PATH_H
#define HEADER_CURL_PATH_H
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2020, 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 https://curl.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









|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#ifndef HEADER_CURL_PATH_H
#define HEADER_CURL_PATH_H
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2021, 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 https://curl.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
35
36
37
38
39
40
41
42
43
44
45
46
47
#endif

#ifndef PATH_MAX
#define PATH_MAX 1024 /* just an extra precaution since there are systems that
                         have their definition hidden well */
#endif

CURLcode Curl_getworkingpath(struct connectdata *conn,
                             char *homedir,
                             char **path);

CURLcode Curl_get_pathname(const char **cpp, char **path, char *homedir);
#endif /* HEADER_CURL_PATH_H */







|





35
36
37
38
39
40
41
42
43
44
45
46
47
#endif

#ifndef PATH_MAX
#define PATH_MAX 1024 /* just an extra precaution since there are systems that
                         have their definition hidden well */
#endif

CURLcode Curl_getworkingpath(struct Curl_easy *data,
                             char *homedir,
                             char **path);

CURLcode Curl_get_pathname(const char **cpp, char **path, char *homedir);
#endif /* HEADER_CURL_PATH_H */
Changes to jni/curl/lib/curl_range.c.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2020, 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 https://curl.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







|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2021, 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 https://curl.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
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
/* Only include this function if one or more of FTP, FILE are enabled. */
#if !defined(CURL_DISABLE_FTP) || !defined(CURL_DISABLE_FILE)

 /*
  Check if this is a range download, and if so, set the internal variables
  properly.
 */
CURLcode Curl_range(struct connectdata *conn)
{
  curl_off_t from, to;
  char *ptr;
  char *ptr2;
  struct Curl_easy *data = conn->data;

  if(data->state.use_range && data->state.range) {
    CURLofft from_t;
    CURLofft to_t;
    from_t = curlx_strtoofft(data->state.range, &ptr, 0, &from);
    if(from_t == CURL_OFFT_FLOW)
      return CURLE_RANGE_ERROR;







|




<







29
30
31
32
33
34
35
36
37
38
39
40

41
42
43
44
45
46
47
/* Only include this function if one or more of FTP, FILE are enabled. */
#if !defined(CURL_DISABLE_FTP) || !defined(CURL_DISABLE_FILE)

 /*
  Check if this is a range download, and if so, set the internal variables
  properly.
 */
CURLcode Curl_range(struct Curl_easy *data)
{
  curl_off_t from, to;
  char *ptr;
  char *ptr2;


  if(data->state.use_range && data->state.range) {
    CURLofft from_t;
    CURLofft to_t;
    from_t = curlx_strtoofft(data->state.range, &ptr, 0, &from);
    if(from_t == CURL_OFFT_FLOW)
      return CURLE_RANGE_ERROR;
Changes to jni/curl/lib/curl_range.h.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#ifndef HEADER_CURL_RANGE_H
#define HEADER_CURL_RANGE_H
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2020, 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 https://curl.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"

CURLcode Curl_range(struct connectdata *conn);

#endif /* HEADER_CURL_RANGE_H */









|

















|
<

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28

29
#ifndef HEADER_CURL_RANGE_H
#define HEADER_CURL_RANGE_H
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2021, 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 https://curl.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"

CURLcode Curl_range(struct Curl_easy *data);

#endif /* HEADER_CURL_RANGE_H */
Changes to jni/curl/lib/curl_rtmp.c.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/***************************************************************************
 *                      _   _ ____  _
 *  Project         ___| | | |  _ \| |
 *                 / __| | | | |_) | |
 *                | (__| |_| |  _ <| |___
 *                 \___|\___/|_| \_\_____|
 *
 * Copyright (C) 2012 - 2020, 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 https://curl.se/docs/copyright.html.
 *
 * You may opt to use, copy, modify, merge, publish, distribute and/or sell







|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/***************************************************************************
 *                      _   _ ____  _
 *  Project         ___| | | |  _ \| |
 *                 / __| | | | |_) | |
 *                | (__| |_| |  _ <| |___
 *                 \___|\___/|_| \_\_____|
 *
 * Copyright (C) 2012 - 2021, 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 https://curl.se/docs/copyright.html.
 *
 * You may opt to use, copy, modify, merge, publish, distribute and/or sell
44
45
46
47
48
49
50
51

52
53
54
55

56
57
58
59
60
61
62
#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 https://rtmpdump.mplayerhq.hu
 */







|
>
|
|
|
|
>







44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
#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 Curl_easy *data,
                                      struct connectdata *conn);
static CURLcode rtmp_do(struct Curl_easy *data, bool *done);
static CURLcode rtmp_done(struct Curl_easy *data, CURLcode, bool premature);
static CURLcode rtmp_connect(struct Curl_easy *data, bool *done);
static CURLcode rtmp_disconnect(struct Curl_easy *data,
                                struct connectdata *conn, bool dead);

static Curl_recv rtmp_recv;
static Curl_send rtmp_send;

/*
 * RTMP protocol handler.h, based on https://rtmpdump.mplayerhq.hu
 */
189
190
191
192
193
194
195
196

197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213

214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
  ZERO_NULL,                            /* connection_check */
  PORT_RTMPS,                           /* defport */
  CURLPROTO_RTMPTS,                     /* protocol */
  CURLPROTO_RTMPT,                      /* family */
  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.rtmp = r;
  return CURLE_OK;
}

static CURLcode rtmp_connect(struct connectdata *conn, bool *done)
{

  RTMP *r = conn->proto.rtmp;
  SET_RCVTIMEO(tv, 10);

  r->m_sb.sb_socket = (int)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;








|
>







|







|

>








|







191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
  ZERO_NULL,                            /* connection_check */
  PORT_RTMPS,                           /* defport */
  CURLPROTO_RTMPTS,                     /* protocol */
  CURLPROTO_RTMPT,                      /* family */
  PROTOPT_NONE                          /* flags*/
};

static CURLcode rtmp_setup_connection(struct Curl_easy *data,
                                      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, data->change.url)) {
    RTMP_Free(r);
    return CURLE_URL_MALFORMAT;
  }
  conn->proto.rtmp = r;
  return CURLE_OK;
}

static CURLcode rtmp_connect(struct Curl_easy *data, bool *done)
{
  struct connectdata *conn = data->conn;
  RTMP *r = conn->proto.rtmp;
  SET_RCVTIMEO(tv, 10);

  r->m_sb.sb_socket = (int)conn->sock[FIRSTSOCKET];

  /* We have to know if it's a write before we send the
   * connect request packet
   */
  if(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;

239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274

275
276
277

278
279
280
281
282
283
284
285
286
287
288
289

290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310

311
312
313
314
315
316
317
318
319
320
321
322

  *done = TRUE;
  conn->recv[FIRSTSOCKET] = rtmp_recv;
  conn->send[FIRSTSOCKET] = rtmp_send;
  return CURLE_OK;
}

static CURLcode rtmp_do(struct connectdata *conn, bool *done)
{
  struct Curl_easy *data = conn->data;
  RTMP *r = conn->proto.rtmp;

  if(!RTMP_ConnectStream(r, 0))
    return CURLE_FAILED_INIT;

  if(conn->data->set.upload) {
    Curl_pgrsSetUploadSize(data, data->state.infilesize);
    Curl_setup_transfer(data, -1, -1, FALSE, FIRSTSOCKET);
  }
  else
    Curl_setup_transfer(data, FIRSTSOCKET, -1, FALSE, -1);
  *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.rtmp;

  (void)dead_connection;
  if(r) {
    conn->proto.rtmp = 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.rtmp;
  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.rtmp;
  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 */







|

|





|









|


|






|
>



>









|


>








|
|








|


>












243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330

  *done = TRUE;
  conn->recv[FIRSTSOCKET] = rtmp_recv;
  conn->send[FIRSTSOCKET] = rtmp_send;
  return CURLE_OK;
}

static CURLcode rtmp_do(struct Curl_easy *data, bool *done)
{
  struct connectdata *conn = data->conn;
  RTMP *r = conn->proto.rtmp;

  if(!RTMP_ConnectStream(r, 0))
    return CURLE_FAILED_INIT;

  if(data->set.upload) {
    Curl_pgrsSetUploadSize(data, data->state.infilesize);
    Curl_setup_transfer(data, -1, -1, FALSE, FIRSTSOCKET);
  }
  else
    Curl_setup_transfer(data, FIRSTSOCKET, -1, FALSE, -1);
  *done = TRUE;
  return CURLE_OK;
}

static CURLcode rtmp_done(struct Curl_easy *data, CURLcode status,
                          bool premature)
{
  (void)data; /* unused */
  (void)status; /* unused */
  (void)premature; /* unused */

  return CURLE_OK;
}

static CURLcode rtmp_disconnect(struct Curl_easy *data,
                                struct connectdata *conn,
                                bool dead_connection)
{
  RTMP *r = conn->proto.rtmp;
  (void)data;
  (void)dead_connection;
  if(r) {
    conn->proto.rtmp = NULL;
    RTMP_Close(r);
    RTMP_Free(r);
  }
  return CURLE_OK;
}

static ssize_t rtmp_recv(struct Curl_easy *data, int sockindex, char *buf,
                         size_t len, CURLcode *err)
{
  struct connectdata *conn = data->conn;
  RTMP *r = conn->proto.rtmp;
  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) {
      data->req.size = data->req.bytecount;
      nread = 0;
    }
    else
      *err = CURLE_RECV_ERROR;
  }
  return nread;
}

static ssize_t rtmp_send(struct Curl_easy *data, int sockindex,
                         const void *buf, size_t len, CURLcode *err)
{
  struct connectdata *conn = data->conn;
  RTMP *r = conn->proto.rtmp;
  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 */
Changes to jni/curl/lib/curl_sasl.c.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 2012 - 2020, 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 https://curl.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







|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 2012 - 2021, 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 https://curl.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
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
}

/*
 * 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",







|







190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
}

/*
 * state()
 *
 * This is the ONLY way to change SASL state!
 */
static void state(struct SASL *sasl, struct Curl_easy *data,
                  saslstate newstate)
{
#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
  /* for debug purposes */
  static const char * const names[]={
    "STOP",
    "PLAIN",
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
    "OAUTH2_RESP",
    "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()







|


|







217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
    "OAUTH2_RESP",
    "CANCEL",
    "FINAL",
    /* LAST */
  };

  if(sasl->state != newstate)
    infof(data, "SASL %p state change from %s to %s\n",
          (void *)sasl, names[sasl->state], names[newstate]);
#else
  (void) data;
#endif

  sasl->state = newstate;
}

/*
 * Curl_sasl_can_authenticate()
249
250
251
252
253
254
255
256

257
258
259
260
261
262
263
264
265
266
267
}

/*
 * Curl_sasl_start()
 *
 * Calculate the required login details for SASL authentication.
 */
CURLcode Curl_sasl_start(struct SASL *sasl, struct connectdata *conn,

                         bool force_ir, saslprogress *progress)
{
  CURLcode result = CURLE_OK;
  struct Curl_easy *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;
#ifndef CURL_DISABLE_PROXY







|
>



<







249
250
251
252
253
254
255
256
257
258
259
260

261
262
263
264
265
266
267
}

/*
 * Curl_sasl_start()
 *
 * Calculate the required login details for SASL authentication.
 */
CURLcode Curl_sasl_start(struct SASL *sasl, struct Curl_easy *data,
                         struct connectdata *conn,
                         bool force_ir, saslprogress *progress)
{
  CURLcode result = CURLE_OK;

  unsigned int enabledmechs;
  const char *mech = NULL;
  char *resp = NULL;
  size_t len = 0;
  saslstate state1 = SASL_STOP;
  saslstate state2 = SASL_FINAL;
#ifndef CURL_DISABLE_PROXY
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418

419
420
421
422
423
424
425
426
427
428
429
  if(!result && mech) {
    if(resp && sasl->params->maxirlen &&
       strlen(mech) + len > sasl->params->maxirlen) {
      free(resp);
      resp = NULL;
    }

    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.
 */
CURLcode Curl_sasl_continue(struct SASL *sasl, struct connectdata *conn,

                            int code, saslprogress *progress)
{
  CURLcode result = CURLE_OK;
  struct Curl_easy *data = conn->data;
  saslstate newstate = SASL_FINAL;
  char *resp = NULL;
#ifndef CURL_DISABLE_PROXY
  const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name :
    conn->host.name;
  const long int port = SSL_IS_PROXY() ? conn->port : conn->remote_port;
#else







|


|













|
>



<







394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422

423
424
425
426
427
428
429
  if(!result && mech) {
    if(resp && sasl->params->maxirlen &&
       strlen(mech) + len > sasl->params->maxirlen) {
      free(resp);
      resp = NULL;
    }

    result = sasl->params->sendauth(data, conn, mech, resp);
    if(!result) {
      *progress = SASL_INPROGRESS;
      state(sasl, data, resp ? state2 : state1);
    }
  }

  free(resp);

  return result;
}

/*
 * Curl_sasl_continue()
 *
 * Continue the authentication.
 */
CURLcode Curl_sasl_continue(struct SASL *sasl, struct Curl_easy *data,
                            struct connectdata *conn,
                            int code, saslprogress *progress)
{
  CURLcode result = CURLE_OK;

  saslstate newstate = SASL_FINAL;
  char *resp = NULL;
#ifndef CURL_DISABLE_PROXY
  const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name :
    conn->host.name;
  const long int port = SSL_IS_PROXY() ? conn->port : conn->remote_port;
#else
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467

  *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 && sasl->state != SASL_OAUTH2_RESP &&
     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;







|






|







446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467

  *progress = SASL_INPROGRESS;

  if(sasl->state == SASL_FINAL) {
    if(code != sasl->params->finalcode)
      result = CURLE_LOGIN_DENIED;
    *progress = SASL_DONE;
    state(sasl, data, SASL_STOP);
    return result;
  }

  if(sasl->state != SASL_CANCEL && sasl->state != SASL_OAUTH2_RESP &&
     code != sasl->params->contcode) {
    *progress = SASL_DONE;
    state(sasl, data, SASL_STOP);
    return CURLE_LOGIN_DENIED;
  }

  switch(sasl->state) {
  case SASL_STOP:
    *progress = SASL_DONE;
    return result;
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
    break;

  case SASL_OAUTH2_RESP:
    /* The continuation is optional so check the response code */
    if(code == sasl->params->finalcode) {
      /* Final response was received so we are done */
      *progress = SASL_DONE;
      state(sasl, conn, SASL_STOP);
      return result;
    }
    else if(code == sasl->params->contcode) {
      /* Acknowledge the continuation by sending a 0x01 response base64
         encoded */
      resp = strdup("AQ==");
      if(!resp)
        result = CURLE_OUT_OF_MEMORY;
      break;
    }
    else {
      *progress = SASL_DONE;
      state(sasl, conn, SASL_STOP);
      return CURLE_LOGIN_DENIED;
    }

  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;
}
#endif /* protocols are enabled that use SASL */







|












|








|











|




|









|




583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
    break;

  case SASL_OAUTH2_RESP:
    /* The continuation is optional so check the response code */
    if(code == sasl->params->finalcode) {
      /* Final response was received so we are done */
      *progress = SASL_DONE;
      state(sasl, data, SASL_STOP);
      return result;
    }
    else if(code == sasl->params->contcode) {
      /* Acknowledge the continuation by sending a 0x01 response base64
         encoded */
      resp = strdup("AQ==");
      if(!resp)
        result = CURLE_OUT_OF_MEMORY;
      break;
    }
    else {
      *progress = SASL_DONE;
      state(sasl, data, SASL_STOP);
      return CURLE_LOGIN_DENIED;
    }

  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, data, 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(data, conn, "*");
    newstate = SASL_CANCEL;
    break;
  case CURLE_OK:
    if(resp)
      result = sasl->params->sendcont(data, conn, resp);
    break;
  default:
    newstate = SASL_STOP;    /* Stop on error */
    *progress = SASL_DONE;
    break;
  }

  free(resp);

  state(sasl, data, newstate);

  return result;
}
#endif /* protocols are enabled that use SASL */
Changes to jni/curl/lib/curl_sasl.h.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#ifndef HEADER_CURL_SASL_H
#define HEADER_CURL_SASL_H
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 2012 - 2020, 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 https://curl.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









|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#ifndef HEADER_CURL_SASL_H
#define HEADER_CURL_SASL_H
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 2012 - 2021, 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 https://curl.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
84
85
86
87
88
89
90
91

92
93

94
95
96
97
98
99
100
101

/* 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 {







|
>


>
|







84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103

/* 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 Curl_easy *data,
                       struct connectdata *conn,
                       const char *mech, const char *ir);
                           /* Send authentication command */
  CURLcode (*sendcont)(struct Curl_easy *data,
                       struct connectdata *conn, const char *contauth);
                           /* Send authentication continuation */
  void (*getmessage)(char *buffer, char **outptr);
                           /* Get SASL response message */
};

/* Per-connection parameters */
struct SASL {
129
130
131
132
133
134
135
136

137
138
139
140

141
142
143
/* Initializes an SASL structure */
void Curl_sasl_init(struct SASL *sasl, const struct SASLproto *params);

/* Check if we have enough auth data and capabilities to authenticate */
bool Curl_sasl_can_authenticate(struct SASL *sasl, struct connectdata *conn);

/* Calculate the required login details for SASL authentication  */
CURLcode Curl_sasl_start(struct SASL *sasl, struct connectdata *conn,

                         bool force_ir, saslprogress *progress);

/* Continue an SASL authentication  */
CURLcode Curl_sasl_continue(struct SASL *sasl, struct connectdata *conn,

                            int code, saslprogress *progress);

#endif /* HEADER_CURL_SASL_H */







|
>



|
>



131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
/* Initializes an SASL structure */
void Curl_sasl_init(struct SASL *sasl, const struct SASLproto *params);

/* Check if we have enough auth data and capabilities to authenticate */
bool Curl_sasl_can_authenticate(struct SASL *sasl, struct connectdata *conn);

/* Calculate the required login details for SASL authentication  */
CURLcode Curl_sasl_start(struct SASL *sasl, struct Curl_easy *data,
                         struct connectdata *conn,
                         bool force_ir, saslprogress *progress);

/* Continue an SASL authentication  */
CURLcode Curl_sasl_continue(struct SASL *sasl, struct Curl_easy *data,
                            struct connectdata *conn,
                            int code, saslprogress *progress);

#endif /* HEADER_CURL_SASL_H */
Changes to jni/curl/lib/curl_sha256.h.
20
21
22
23
24
25
26



27
28
29
30
31
32
33
 *
 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
 * KIND, either express or implied.
 *
 ***************************************************************************/

#ifndef CURL_DISABLE_CRYPTO_AUTH




#define SHA256_DIGEST_LENGTH 32

void Curl_sha256it(unsigned char *outbuffer, const unsigned char *input,
                   const size_t len);

#endif







>
>
>







20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
 *
 * 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"

extern const struct HMAC_params Curl_HMAC_SHA256[1];

#define SHA256_DIGEST_LENGTH 32

void Curl_sha256it(unsigned char *outbuffer, const unsigned char *input,
                   const size_t len);

#endif
Changes to jni/curl/lib/dict.c.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2020, 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 https://curl.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







|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2021, 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 https://curl.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
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
/* 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 */







|







63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
/* The last #include file should be: */
#include "memdebug.h"

/*
 * Forward declarations.
 */

static CURLcode dict_do(struct Curl_easy *data, bool *done);

/*
 * DICT protocol handler.
 */

const struct Curl_handler Curl_handler_dict = {
  "DICT",                               /* scheme */
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
    dictp[olen] = 0;
  }
  free(newp);
  return dictp;
}

/* sendf() sends formatted data to the server */
static CURLcode sendf(curl_socket_t sockfd, struct connectdata *conn,
                      const char *fmt, ...)
{
  struct Curl_easy *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;

    Curl_debug(data, CURLINFO_DATA_OUT, sptr, (size_t)bytes_written);

    if((size_t)bytes_written != write_len) {







|


<


















|







125
126
127
128
129
130
131
132
133
134

135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
    dictp[olen] = 0;
  }
  free(newp);
  return dictp;
}

/* sendf() sends formatted data to the server */
static CURLcode sendf(curl_socket_t sockfd, struct Curl_easy *data,
                      const char *fmt, ...)
{

  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(data, sockfd, sptr, write_len, &bytes_written);

    if(result)
      break;

    Curl_debug(data, CURLINFO_DATA_OUT, sptr, (size_t)bytes_written);

    if((size_t)bytes_written != write_len) {
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
  }

  free(s); /* free the output string */

  return result;
}

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 Curl_easy *data = conn->data;
  curl_socket_t sockfd = conn->sock[FIRSTSOCKET];

  char *path = data->state.up.path;

  *done = TRUE; /* unconditionally */

  if(conn->bits.user_passwd) {







|









|







168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
  }

  free(s); /* free the output string */

  return result;
}

static CURLcode dict_do(struct Curl_easy *data, 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 connectdata *conn = data->conn;
  curl_socket_t sockfd = conn->sock[FIRSTSOCKET];

  char *path = data->state.up.path;

  *done = TRUE; /* unconditionally */

  if(conn->bits.user_passwd) {
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
      strategy = (char *)".";
    }

    eword = unescape_word(data, word);
    if(!eword)
      return CURLE_OUT_OF_MEMORY;

    result = sendf(sockfd, conn,
                   "CLIENT " LIBCURL_NAME " " LIBCURL_VERSION "\r\n"
                   "MATCH "
                   "%s "    /* database */
                   "%s "    /* strategy */
                   "%s\r\n" /* word */
                   "QUIT\r\n",
                   database,







|







225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
      strategy = (char *)".";
    }

    eword = unescape_word(data, word);
    if(!eword)
      return CURLE_OUT_OF_MEMORY;

    result = sendf(sockfd, data,
                   "CLIENT " LIBCURL_NAME " " LIBCURL_VERSION "\r\n"
                   "MATCH "
                   "%s "    /* database */
                   "%s "    /* strategy */
                   "%s\r\n" /* word */
                   "QUIT\r\n",
                   database,
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
      database = (char *)"!";
    }

    eword = unescape_word(data, word);
    if(!eword)
      return CURLE_OUT_OF_MEMORY;

    result = sendf(sockfd, conn,
                   "CLIENT " LIBCURL_NAME " " LIBCURL_VERSION "\r\n"
                   "DEFINE "
                   "%s "     /* database */
                   "%s\r\n"  /* word */
                   "QUIT\r\n",
                   database,
                   eword);







|







273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
      database = (char *)"!";
    }

    eword = unescape_word(data, word);
    if(!eword)
      return CURLE_OUT_OF_MEMORY;

    result = sendf(sockfd, data,
                   "CLIENT " LIBCURL_NAME " " LIBCURL_VERSION "\r\n"
                   "DEFINE "
                   "%s "     /* database */
                   "%s\r\n"  /* word */
                   "QUIT\r\n",
                   database,
                   eword);
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
      int i;

      ppath++;
      for(i = 0; ppath[i]; i++) {
        if(ppath[i] == ':')
          ppath[i] = ' ';
      }
      result = 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;
      }







|







301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
      int i;

      ppath++;
      for(i = 0; ppath[i]; i++) {
        if(ppath[i] == ':')
          ppath[i] = ' ';
      }
      result = sendf(sockfd, data,
                     "CLIENT " LIBCURL_NAME " " LIBCURL_VERSION "\r\n"
                     "%s\r\n"
                     "QUIT\r\n", ppath);
      if(result) {
        failf(data, "Failed sending DICT request");
        return result;
      }
Changes to jni/curl/lib/doh.c.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 2018 - 2020, 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 https://curl.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







|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 2018 - 2021, 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 https://curl.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
183
184
185
186
187
188
189
190
191
192

193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
  if(Curl_dyn_addn(mem, contents, realsize))
    return 0;

  return realsize;
}

/* called from multi.c when this DOH transfer is complete */
static int Curl_doh_done(struct Curl_easy *doh, CURLcode result)
{
  struct Curl_easy *data = doh->set.dohfor;

  /* so one of the DOH request done for the 'data' transfer is now complete! */
  data->req.doh.pending--;
  infof(data, "a DOH request is completed, %u to go\n", data->req.doh.pending);
  if(result)
    infof(data, "DOH request %s\n", curl_easy_strerror(result));

  if(!data->req.doh.pending) {
    /* DOH completed */
    curl_slist_free_all(data->req.doh.headers);
    data->req.doh.headers = NULL;
    Curl_expire(data, 0, EXPIRE_RUN_NOW);
  }
  return 0;
}

#define ERROR_CHECK_SETOPT(x,y) \
do {                                      \







|


>

|
|



|

|
|







183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
  if(Curl_dyn_addn(mem, contents, realsize))
    return 0;

  return realsize;
}

/* called from multi.c when this DOH transfer is complete */
static int doh_done(struct Curl_easy *doh, CURLcode result)
{
  struct Curl_easy *data = doh->set.dohfor;
  struct dohdata *dohp = data->req.doh;
  /* so one of the DOH request done for the 'data' transfer is now complete! */
  dohp->pending--;
  infof(data, "a DOH request is completed, %u to go\n", dohp->pending);
  if(result)
    infof(data, "DOH request %s\n", curl_easy_strerror(result));

  if(!dohp->pending) {
    /* DOH completed */
    curl_slist_free_all(dohp->headers);
    dohp->headers = NULL;
    Curl_expire(data, 0, EXPIRE_RUN_NOW);
  }
  return 0;
}

#define ERROR_CHECK_SETOPT(x,y) \
do {                                      \
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
  struct Curl_easy *doh = NULL;
  char *nurl = NULL;
  CURLcode result = CURLE_OK;
  timediff_t timeout_ms;
  DOHcode d = doh_encode(host, dnstype, p->dohbuffer, sizeof(p->dohbuffer),
                         &p->dohlen);
  if(d) {
    failf(data, "Failed to encode DOH packet [%d]\n", d);
    return CURLE_OUT_OF_MEMORY;
  }

  p->dnstype = dnstype;
  Curl_dyn_init(&p->serverdoh, DYN_DOH_RESPONSE);

  /* Note: this is code for sending the DoH request with GET but there's still







|







222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
  struct Curl_easy *doh = NULL;
  char *nurl = NULL;
  CURLcode result = CURLE_OK;
  timediff_t timeout_ms;
  DOHcode d = doh_encode(host, dnstype, p->dohbuffer, sizeof(p->dohbuffer),
                         &p->dohlen);
  if(d) {
    failf(data, "Failed to encode DOH packet [%d]", d);
    return CURLE_OUT_OF_MEMORY;
  }

  p->dnstype = dnstype;
  Curl_dyn_init(&p->serverdoh, DYN_DOH_RESPONSE);

  /* Note: this is code for sending the DoH request with GET but there's still
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
    if(data->set.ssl.fsslctxp)
      ERROR_CHECK_SETOPT(CURLOPT_SSL_CTX_DATA, data->set.ssl.fsslctxp);
    if(data->set.str[STRING_SSL_EC_CURVES]) {
      ERROR_CHECK_SETOPT(CURLOPT_SSL_EC_CURVES,
        data->set.str[STRING_SSL_EC_CURVES]);
    }

    doh->set.fmultidone = Curl_doh_done;
    doh->set.dohfor = data; /* identify for which transfer this is done */
    p->easy = doh;

    /* add this transfer to the multi handle */
    if(curl_multi_add_handle(multi, doh))
      goto error;
  }







|







351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
    if(data->set.ssl.fsslctxp)
      ERROR_CHECK_SETOPT(CURLOPT_SSL_CTX_DATA, data->set.ssl.fsslctxp);
    if(data->set.str[STRING_SSL_EC_CURVES]) {
      ERROR_CHECK_SETOPT(CURLOPT_SSL_EC_CURVES,
        data->set.str[STRING_SSL_EC_CURVES]);
    }

    doh->set.fmultidone = doh_done;
    doh->set.dohfor = data; /* identify for which transfer this is done */
    p->easy = doh;

    /* add this transfer to the multi handle */
    if(curl_multi_add_handle(multi, doh))
      goto error;
  }
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388


389
390
391
392
393



394
395


396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432

433
434
435
436
437
438
439
}

/*
 * Curl_doh() resolves a name using DOH. It resolves a name and returns a
 * 'Curl_addrinfo *' with the address information.
 */

struct Curl_addrinfo *Curl_doh(struct connectdata *conn,
                               const char *hostname,
                               int port,
                               int *waitp)
{
  struct Curl_easy *data = conn->data;
  CURLcode result = CURLE_OK;
  int slot;


  *waitp = TRUE; /* this never returns synchronously */
  (void)conn;
  (void)hostname;
  (void)port;




  /* start clean, consider allocating this struct on demand */
  memset(&data->req.doh, 0, sizeof(struct dohdata));



  conn->bits.doh = TRUE;
  data->req.doh.host = hostname;
  data->req.doh.port = port;
  data->req.doh.headers =
    curl_slist_append(NULL,
                      "Content-Type: application/dns-message");
  if(!data->req.doh.headers)
    goto error;

  if(conn->ip_version != CURL_IPRESOLVE_V6) {
    /* create IPv4 DOH request */
    result = dohprobe(data, &data->req.doh.probe[DOH_PROBE_SLOT_IPADDR_V4],
                      DNS_TYPE_A, hostname, data->set.str[STRING_DOH],
                      data->multi, data->req.doh.headers);
    if(result)
      goto error;
    data->req.doh.pending++;
  }

  if(conn->ip_version != CURL_IPRESOLVE_V4) {
    /* create IPv6 DOH request */
    result = dohprobe(data, &data->req.doh.probe[DOH_PROBE_SLOT_IPADDR_V6],
                      DNS_TYPE_AAAA, hostname, data->set.str[STRING_DOH],
                      data->multi, data->req.doh.headers);
    if(result)
      goto error;
    data->req.doh.pending++;
  }
  return NULL;

  error:
  curl_slist_free_all(data->req.doh.headers);
  data->req.doh.headers = NULL;
  for(slot = 0; slot < DOH_PROBE_SLOTS; slot++) {
    Curl_close(&data->req.doh.probe[slot].easy);
  }

  return NULL;
}

static DOHcode skipqname(const unsigned char *doh, size_t dohlen,
                         unsigned int *indexp)
{
  unsigned char length;







|




<


>
>

<



>
>
>

|
>
>


|
|
|


|




|

|


|




|

|


|




|
|

|

>







375
376
377
378
379
380
381
382
383
384
385
386

387
388
389
390
391

392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
}

/*
 * Curl_doh() resolves a name using DOH. It resolves a name and returns a
 * 'Curl_addrinfo *' with the address information.
 */

struct Curl_addrinfo *Curl_doh(struct Curl_easy *data,
                               const char *hostname,
                               int port,
                               int *waitp)
{

  CURLcode result = CURLE_OK;
  int slot;
  struct dohdata *dohp;
  struct connectdata *conn = data->conn;
  *waitp = TRUE; /* this never returns synchronously */

  (void)hostname;
  (void)port;

  DEBUGASSERT(!data->req.doh);
  DEBUGASSERT(conn);

  /* start clean, consider allocating this struct on demand */
  dohp = data->req.doh = calloc(sizeof(struct dohdata), 1);
  if(!dohp)
    return NULL;

  conn->bits.doh = TRUE;
  dohp->host = hostname;
  dohp->port = port;
  dohp->headers =
    curl_slist_append(NULL,
                      "Content-Type: application/dns-message");
  if(!dohp->headers)
    goto error;

  if(conn->ip_version != CURL_IPRESOLVE_V6) {
    /* create IPv4 DOH request */
    result = dohprobe(data, &dohp->probe[DOH_PROBE_SLOT_IPADDR_V4],
                      DNS_TYPE_A, hostname, data->set.str[STRING_DOH],
                      data->multi, dohp->headers);
    if(result)
      goto error;
    dohp->pending++;
  }

  if(conn->ip_version != CURL_IPRESOLVE_V4) {
    /* create IPv6 DOH request */
    result = dohprobe(data, &dohp->probe[DOH_PROBE_SLOT_IPADDR_V6],
                      DNS_TYPE_AAAA, hostname, data->set.str[STRING_DOH],
                      data->multi, dohp->headers);
    if(result)
      goto error;
    dohp->pending++;
  }
  return NULL;

  error:
  curl_slist_free_all(dohp->headers);
  data->req.doh->headers = NULL;
  for(slot = 0; slot < DOH_PROBE_SLOTS; slot++) {
    Curl_close(&dohp->probe[slot].easy);
  }
  Curl_safefree(data->req.doh);
  return NULL;
}

static DOHcode skipqname(const unsigned char *doh, size_t dohlen,
                         unsigned int *indexp)
{
  unsigned char length;
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478

static unsigned int get32bit(const unsigned char *doh, int index)
{
   /* make clang and gcc optimize this to bswap by incrementing
      the pointer first. */
   doh += index;

   /* avoid undefined behaviour by casting to unsigned before shifting
      24 bits, possibly into the sign bit. codegen is same, but
      ub sanitizer won't be upset */
  return ( (unsigned)doh[0] << 24) | (doh[1] << 16) |(doh[2] << 8) | doh[3];
}

static DOHcode store_a(const unsigned char *doh, int index, struct dohentry *d)
{







|







471
472
473
474
475
476
477
478
479
480
481
482
483
484
485

static unsigned int get32bit(const unsigned char *doh, int index)
{
   /* make clang and gcc optimize this to bswap by incrementing
      the pointer first. */
   doh += index;

   /* avoid undefined behavior by casting to unsigned before shifting
      24 bits, possibly into the sign bit. codegen is same, but
      ub sanitizer won't be upset */
  return ( (unsigned)doh[0] << 24) | (doh[1] << 16) |(doh[2] << 8) | doh[3];
}

static DOHcode store_a(const unsigned char *doh, int index, struct dohentry *d)
{
900
901
902
903
904
905
906
907
908
909
910
911
912


913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986

987
988
989
990
991
992
993
994
995
{
  int i = 0;
  for(i = 0; i < d->numcname; i++) {
    Curl_dyn_free(&d->cname[i]);
  }
}

CURLcode Curl_doh_is_resolved(struct connectdata *conn,
                              struct Curl_dns_entry **dnsp)
{
  CURLcode result;
  struct Curl_easy *data = conn->data;
  *dnsp = NULL; /* defaults to no response */



  if(!data->req.doh.probe[DOH_PROBE_SLOT_IPADDR_V4].easy &&
     !data->req.doh.probe[DOH_PROBE_SLOT_IPADDR_V6].easy) {
    failf(data, "Could not DOH-resolve: %s", conn->async.hostname);
    return conn->bits.proxy?CURLE_COULDNT_RESOLVE_PROXY:
      CURLE_COULDNT_RESOLVE_HOST;
  }
  else if(!data->req.doh.pending) {
    DOHcode rc[DOH_PROBE_SLOTS] = {
      DOH_OK, DOH_OK
    };
    struct dohentry de;
    int slot;
    /* remove DOH handles from multi handle and close them */
    for(slot = 0; slot < DOH_PROBE_SLOTS; slot++) {
      curl_multi_remove_handle(data->multi, data->req.doh.probe[slot].easy);
      Curl_close(&data->req.doh.probe[slot].easy);
    }
    /* parse the responses, create the struct and return it! */
    de_init(&de);
    for(slot = 0; slot < DOH_PROBE_SLOTS; slot++) {
      struct dnsprobe *p = &data->req.doh.probe[slot];
      if(!p->dnstype)
        continue;
      rc[slot] = doh_decode(Curl_dyn_uptr(&p->serverdoh),
                            Curl_dyn_len(&p->serverdoh),
                            p->dnstype,
                            &de);
      Curl_dyn_free(&p->serverdoh);
      if(rc[slot]) {
        infof(data, "DOH: %s type %s for %s\n", doh_strerror(rc[slot]),
              type2name(p->dnstype), data->req.doh.host);
      }
    } /* next slot */

    result = CURLE_COULDNT_RESOLVE_HOST; /* until we know better */
    if(!rc[DOH_PROBE_SLOT_IPADDR_V4] || !rc[DOH_PROBE_SLOT_IPADDR_V6]) {
      /* we have an address, of one kind or other */
      struct Curl_dns_entry *dns;
      struct Curl_addrinfo *ai;

      infof(data, "DOH Host name: %s\n", data->req.doh.host);
      showdoh(data, &de);

      ai = doh2ai(&de, data->req.doh.host, data->req.doh.port);
      if(!ai) {
        de_cleanup(&de);
        return CURLE_OUT_OF_MEMORY;
      }

      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, ai, data->req.doh.host, data->req.doh.port);

      if(data->share)
        Curl_share_unlock(data, CURL_LOCK_DATA_DNS);

      if(!dns) {
        /* returned failure, bail out nicely */
        Curl_freeaddrinfo(ai);
      }
      else {
        conn->async.dns = dns;
        *dnsp = dns;
        result = CURLE_OK;      /* address resolution OK */
      }
    } /* address processing done */

    /* Now process any build-specific attributes retrieved from DNS */

    /* All done */
    de_cleanup(&de);

    return result;

  } /* !data->req.doh.pending */

  /* else wait for pending DOH transactions to complete */
  return CURLE_OK;
}

#endif /* CURL_DISABLE_DOH */







|



|

>
>

|
|
|
|


|







|
|




|









|









|


|









|









|









>


|






907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
{
  int i = 0;
  for(i = 0; i < d->numcname; i++) {
    Curl_dyn_free(&d->cname[i]);
  }
}

CURLcode Curl_doh_is_resolved(struct Curl_easy *data,
                              struct Curl_dns_entry **dnsp)
{
  CURLcode result;
  struct dohdata *dohp = data->req.doh;
  *dnsp = NULL; /* defaults to no response */
  if(!dohp)
    return CURLE_OUT_OF_MEMORY;

  if(!dohp->probe[DOH_PROBE_SLOT_IPADDR_V4].easy &&
     !dohp->probe[DOH_PROBE_SLOT_IPADDR_V6].easy) {
    failf(data, "Could not DOH-resolve: %s", data->state.async.hostname);
    return data->conn->bits.proxy?CURLE_COULDNT_RESOLVE_PROXY:
      CURLE_COULDNT_RESOLVE_HOST;
  }
  else if(!dohp->pending) {
    DOHcode rc[DOH_PROBE_SLOTS] = {
      DOH_OK, DOH_OK
    };
    struct dohentry de;
    int slot;
    /* remove DOH handles from multi handle and close them */
    for(slot = 0; slot < DOH_PROBE_SLOTS; slot++) {
      curl_multi_remove_handle(data->multi, dohp->probe[slot].easy);
      Curl_close(&dohp->probe[slot].easy);
    }
    /* parse the responses, create the struct and return it! */
    de_init(&de);
    for(slot = 0; slot < DOH_PROBE_SLOTS; slot++) {
      struct dnsprobe *p = &dohp->probe[slot];
      if(!p->dnstype)
        continue;
      rc[slot] = doh_decode(Curl_dyn_uptr(&p->serverdoh),
                            Curl_dyn_len(&p->serverdoh),
                            p->dnstype,
                            &de);
      Curl_dyn_free(&p->serverdoh);
      if(rc[slot]) {
        infof(data, "DOH: %s type %s for %s\n", doh_strerror(rc[slot]),
              type2name(p->dnstype), dohp->host);
      }
    } /* next slot */

    result = CURLE_COULDNT_RESOLVE_HOST; /* until we know better */
    if(!rc[DOH_PROBE_SLOT_IPADDR_V4] || !rc[DOH_PROBE_SLOT_IPADDR_V6]) {
      /* we have an address, of one kind or other */
      struct Curl_dns_entry *dns;
      struct Curl_addrinfo *ai;

      infof(data, "DOH Host name: %s\n", dohp->host);
      showdoh(data, &de);

      ai = doh2ai(&de, dohp->host, dohp->port);
      if(!ai) {
        de_cleanup(&de);
        return CURLE_OUT_OF_MEMORY;
      }

      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, ai, dohp->host, dohp->port);

      if(data->share)
        Curl_share_unlock(data, CURL_LOCK_DATA_DNS);

      if(!dns) {
        /* returned failure, bail out nicely */
        Curl_freeaddrinfo(ai);
      }
      else {
        data->state.async.dns = dns;
        *dnsp = dns;
        result = CURLE_OK;      /* address resolution OK */
      }
    } /* address processing done */

    /* Now process any build-specific attributes retrieved from DNS */

    /* All done */
    de_cleanup(&de);
    Curl_safefree(data->req.doh);
    return result;

  } /* !dohp->pending */

  /* else wait for pending DOH transactions to complete */
  return CURLE_OK;
}

#endif /* CURL_DISABLE_DOH */
Changes to jni/curl/lib/doh.h.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#ifndef HEADER_CURL_DOH_H
#define HEADER_CURL_DOH_H
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 2018 - 2020, 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 https://curl.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









|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#ifndef HEADER_CURL_DOH_H
#define HEADER_CURL_DOH_H
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 2018 - 2021, 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 https://curl.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
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
#ifndef CURL_DISABLE_DOH

/*
 * Curl_doh() resolve a name using DoH (DNS-over-HTTPS). It resolves a name
 * and returns a 'Curl_addrinfo *' with the address information.
 */

struct Curl_addrinfo *Curl_doh(struct connectdata *conn,
                               const char *hostname,
                               int port,
                               int *waitp);

CURLcode Curl_doh_is_resolved(struct connectdata *conn,
                              struct Curl_dns_entry **dns);

int Curl_doh_getsock(struct connectdata *conn, curl_socket_t *socks);

typedef enum {
  DOH_OK,
  DOH_DNS_BAD_LABEL,    /* 1 */







|




|







28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
#ifndef CURL_DISABLE_DOH

/*
 * Curl_doh() resolve a name using DoH (DNS-over-HTTPS). It resolves a name
 * and returns a 'Curl_addrinfo *' with the address information.
 */

struct Curl_addrinfo *Curl_doh(struct Curl_easy *data,
                               const char *hostname,
                               int port,
                               int *waitp);

CURLcode Curl_doh_is_resolved(struct Curl_easy *data,
                              struct Curl_dns_entry **dns);

int Curl_doh_getsock(struct connectdata *conn, curl_socket_t *socks);

typedef enum {
  DOH_OK,
  DOH_DNS_BAD_LABEL,    /* 1 */
Changes to jni/curl/lib/easy.c.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2020, 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 https://curl.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







|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2021, 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 https://curl.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
120
121
122
123
124
125
126




127
128
129
130
131
132
133
curl_wcsdup_callback Curl_cwcsdup = (curl_wcsdup_callback)_wcsdup;
#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.
 */
static CURLcode global_init(long flags, bool memoryfuncs)
{
  if(initialized++)







>
>
>
>







120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
curl_wcsdup_callback Curl_cwcsdup = (curl_wcsdup_callback)_wcsdup;
#endif

#if defined(_MSC_VER) && defined(_DLL) && !defined(__POCC__)
#  pragma warning(default:4232) /* MSVC extension, dllimport identity */
#endif

#ifdef DEBUGBUILD
static char *leakpointer;
#endif

/**
 * curl_global_init() globally initializes curl given a bitwise set of the
 * different features of what to initialize.
 */
static CURLcode global_init(long flags, bool memoryfuncs)
{
  if(initialized++)
185
186
187
188
189
190
191






192
193
194
195
196
197
198
  if(WS_SUCCESS != wolfSSH_Init()) {
    DEBUGF(fprintf(stderr, "Error: wolfSSH_Init failed\n"));
    return CURLE_FAILED_INIT;
  }
#endif

  init_flags = flags;







  return CURLE_OK;

  fail:
  initialized--; /* undo the increase */
  return CURLE_FAILED_INIT;
}







>
>
>
>
>
>







189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
  if(WS_SUCCESS != wolfSSH_Init()) {
    DEBUGF(fprintf(stderr, "Error: wolfSSH_Init failed\n"));
    return CURLE_FAILED_INIT;
  }
#endif

  init_flags = flags;

#ifdef DEBUGBUILD
  if(getenv("CURL_GLOBAL_INIT"))
    /* alloc data that will leak if *cleanup() is not called! */
    leakpointer = malloc(1);
#endif

  return CURLE_OK;

  fail:
  initialized--; /* undo the increase */
  return CURLE_FAILED_INIT;
}
261
262
263
264
265
266
267



268
269
270
271
272
273
274
  Curl_amiga_cleanup();

  Curl_ssh_cleanup();

#ifdef USE_WOLFSSH
  (void)wolfSSH_Cleanup();
#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.







>
>
>







271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
  Curl_amiga_cleanup();

  Curl_ssh_cleanup();

#ifdef USE_WOLFSSH
  (void)wolfSSH_Cleanup();
#endif
#ifdef DEBUGBUILD
  free(leakpointer);
#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.
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
      (void)Curl_hsts_loadfile(outcurl,
                               outcurl->hsts, outcurl->set.str[STRING_HSTS]);
    (void)Curl_hsts_loadcb(outcurl, outcurl->hsts);
  }
#endif
  /* Clone the resolver handle, if present, for the new handle */
  if(Curl_resolver_duphandle(outcurl,
                             &outcurl->state.resolver,
                             data->state.resolver))
    goto fail;

#ifdef USE_ARES
  {
    CURLcode rc;

    rc = Curl_set_dns_servers(outcurl, data->set.str[STRING_DNS_SERVERS]);







|
|







904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
      (void)Curl_hsts_loadfile(outcurl,
                               outcurl->hsts, outcurl->set.str[STRING_HSTS]);
    (void)Curl_hsts_loadcb(outcurl, outcurl->hsts);
  }
#endif
  /* Clone the resolver handle, if present, for the new handle */
  if(Curl_resolver_duphandle(outcurl,
                             &outcurl->state.async.resolver,
                             data->state.async.resolver))
    goto fail;

#ifdef USE_ARES
  {
    CURLcode rc;

    rc = Curl_set_dns_servers(outcurl, data->set.str[STRING_DNS_SERVERS]);
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081



1082
1083
1084
1085
1086
1087
1088
        conn->data = data;
      }

      for(i = 0; i < count; i++) {
        /* even if one function returns error, this loops through and frees
           all buffers */
        if(!result)
          result = Curl_client_write(conn, writebuf[i].type,
                                     Curl_dyn_ptr(&writebuf[i].b),
                                     Curl_dyn_len(&writebuf[i].b));
        Curl_dyn_free(&writebuf[i].b);
      }

      /* recover previous owner of the connection */
      if(saved_data)
        conn->data = saved_data;

      if(result)
        return result;
    }
  }

  /* if there's no error and we're not pausing both directions, we want
     to have this handle checked soon */
  if((newstate & (KEEP_RECV_PAUSE|KEEP_SEND_PAUSE)) !=
     (KEEP_RECV_PAUSE|KEEP_SEND_PAUSE)) {
    Curl_expire(data, 0, EXPIRE_RUN_NOW); /* get this handle going again */




    if(!data->state.tempcount)
      /* if not pausing again, force a recv/send check of this connection as
         the data might've been read off the socket already */
      data->conn->cselect_bits = CURL_CSELECT_IN | CURL_CSELECT_OUT;
    if(data->multi)
      Curl_update_timer(data->multi);







|



















>
>
>







1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
        conn->data = data;
      }

      for(i = 0; i < count; i++) {
        /* even if one function returns error, this loops through and frees
           all buffers */
        if(!result)
          result = Curl_client_write(data, writebuf[i].type,
                                     Curl_dyn_ptr(&writebuf[i].b),
                                     Curl_dyn_len(&writebuf[i].b));
        Curl_dyn_free(&writebuf[i].b);
      }

      /* recover previous owner of the connection */
      if(saved_data)
        conn->data = saved_data;

      if(result)
        return result;
    }
  }

  /* if there's no error and we're not pausing both directions, we want
     to have this handle checked soon */
  if((newstate & (KEEP_RECV_PAUSE|KEEP_SEND_PAUSE)) !=
     (KEEP_RECV_PAUSE|KEEP_SEND_PAUSE)) {
    Curl_expire(data, 0, EXPIRE_RUN_NOW); /* get this handle going again */

    /* reset the too-slow time keeper */
    data->state.keeps_speed.tv_sec = 0;

    if(!data->state.tempcount)
      /* if not pausing again, force a recv/send check of this connection as
         the data might've been read off the socket already */
      data->conn->cselect_bits = CURL_CSELECT_IN | CURL_CSELECT_OUT;
    if(data->multi)
      Curl_update_timer(data->multi);
1136
1137
1138
1139
1140
1141
1142





1143
1144
1145
1146
1147
1148
1149
1150
1151
  if(Curl_is_in_callback(data))
    return CURLE_RECURSIVE_API_CALL;

  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;







>
>
>
>
>

|







1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
  if(Curl_is_in_callback(data))
    return CURLE_RECURSIVE_API_CALL;

  result = easy_connection(data, &sfd, &c);
  if(result)
    return result;

  if(!data->conn)
    /* on first invoke, the transfer has been detached from the connection and
       needs to be reattached */
    Curl_attach_connnection(data, c);

  *n = 0;
  result = Curl_read(data, sfd, buffer, buflen, &n1);

  if(result)
    return result;

  *n = (size_t)n1;

  return CURLE_OK;
1166
1167
1168
1169
1170
1171
1172





1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193

1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
  if(Curl_is_in_callback(data))
    return CURLE_RECURSIVE_API_CALL;

  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;
}

/*
 * Wrapper to call functions in Curl_conncache_foreach()
 *
 * Returns always 0.
 */
static int conn_upkeep(struct connectdata *conn,

                       void *param)
{
  /* Param is unused. */
  (void)param;

  if(conn->handler->connection_check) {
    /* Do a protocol-specific keepalive check on the connection. */
    conn->handler->connection_check(conn, CONNCHECK_KEEPALIVE);
  }

  return 0; /* continue iteration */
}

static CURLcode upkeep(struct conncache *conn_cache, void *data)
{
  /* Loop over every connection and make connection alive. */







>
>
>
>
>

|


















|
>





|

|
<







1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228

1229
1230
1231
1232
1233
1234
1235
  if(Curl_is_in_callback(data))
    return CURLE_RECURSIVE_API_CALL;

  result = easy_connection(data, &sfd, &c);
  if(result)
    return result;

  if(!data->conn)
    /* on first invoke, the transfer has been detached from the connection and
       needs to be reattached */
    Curl_attach_connnection(data, c);

  *n = 0;
  result = Curl_write(data, 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;
}

/*
 * Wrapper to call functions in Curl_conncache_foreach()
 *
 * Returns always 0.
 */
static int conn_upkeep(struct Curl_easy *data,
                       struct connectdata *conn,
                       void *param)
{
  /* Param is unused. */
  (void)param;

  if(conn->handler->connection_check)
    /* Do a protocol-specific keepalive check on the connection. */
    conn->handler->connection_check(data, conn, CONNCHECK_KEEPALIVE);


  return 0; /* continue iteration */
}

static CURLcode upkeep(struct conncache *conn_cache, void *data)
{
  /* Loop over every connection and make connection alive. */
Changes to jni/curl/lib/easyoptions.c.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ | |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             ___|___/|_| ______|
 *
 * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel.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 https://curl.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







|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ | |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             ___|___/|_| ______|
 *
 * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel.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 https://curl.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
31
32
33
34
35
36
37

38
39
40
41
42
43
44
  {"ACCEPTTIMEOUT_MS", CURLOPT_ACCEPTTIMEOUT_MS, CURLOT_LONG, 0},
  {"ACCEPT_ENCODING", CURLOPT_ACCEPT_ENCODING, CURLOT_STRING, 0},
  {"ADDRESS_SCOPE", CURLOPT_ADDRESS_SCOPE, CURLOT_LONG, 0},
  {"ALTSVC", CURLOPT_ALTSVC, CURLOT_STRING, 0},
  {"ALTSVC_CTRL", CURLOPT_ALTSVC_CTRL, CURLOT_LONG, 0},
  {"APPEND", CURLOPT_APPEND, CURLOT_LONG, 0},
  {"AUTOREFERER", CURLOPT_AUTOREFERER, CURLOT_LONG, 0},

  {"BUFFERSIZE", CURLOPT_BUFFERSIZE, CURLOT_LONG, 0},
  {"CAINFO", CURLOPT_CAINFO, CURLOT_STRING, 0},
  {"CAPATH", CURLOPT_CAPATH, CURLOT_STRING, 0},
  {"CERTINFO", CURLOPT_CERTINFO, CURLOT_LONG, 0},
  {"CHUNK_BGN_FUNCTION", CURLOPT_CHUNK_BGN_FUNCTION, CURLOT_FUNCTION, 0},
  {"CHUNK_DATA", CURLOPT_CHUNK_DATA, CURLOT_CBPTR, 0},
  {"CHUNK_END_FUNCTION", CURLOPT_CHUNK_END_FUNCTION, CURLOT_FUNCTION, 0},







>







31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
  {"ACCEPTTIMEOUT_MS", CURLOPT_ACCEPTTIMEOUT_MS, CURLOT_LONG, 0},
  {"ACCEPT_ENCODING", CURLOPT_ACCEPT_ENCODING, CURLOT_STRING, 0},
  {"ADDRESS_SCOPE", CURLOPT_ADDRESS_SCOPE, CURLOT_LONG, 0},
  {"ALTSVC", CURLOPT_ALTSVC, CURLOT_STRING, 0},
  {"ALTSVC_CTRL", CURLOPT_ALTSVC_CTRL, CURLOT_LONG, 0},
  {"APPEND", CURLOPT_APPEND, CURLOT_LONG, 0},
  {"AUTOREFERER", CURLOPT_AUTOREFERER, CURLOT_LONG, 0},
  {"AWS_SIGV4", CURLOPT_AWS_SIGV4, CURLOT_STRING, 0},
  {"BUFFERSIZE", CURLOPT_BUFFERSIZE, CURLOT_LONG, 0},
  {"CAINFO", CURLOPT_CAINFO, CURLOT_STRING, 0},
  {"CAPATH", CURLOPT_CAPATH, CURLOT_STRING, 0},
  {"CERTINFO", CURLOPT_CERTINFO, CURLOT_LONG, 0},
  {"CHUNK_BGN_FUNCTION", CURLOPT_CHUNK_BGN_FUNCTION, CURLOT_FUNCTION, 0},
  {"CHUNK_DATA", CURLOPT_CHUNK_DATA, CURLOT_CBPTR, 0},
  {"CHUNK_END_FUNCTION", CURLOPT_CHUNK_END_FUNCTION, CURLOT_FUNCTION, 0},
344
345
346
347
348
349
350
351
352
353
#ifdef DEBUGBUILD
/*
 * Curl_easyopts_check() is a debug-only function that returns non-zero
 * if this source file is not in sync with the options listed in curl/curl.h
 */
int Curl_easyopts_check(void)
{
  return (CURLOPT_LASTENTRY != (304 + 1));
}
#endif







|


345
346
347
348
349
350
351
352
353
354
#ifdef DEBUGBUILD
/*
 * Curl_easyopts_check() is a debug-only function that returns non-zero
 * if this source file is not in sync with the options listed in curl/curl.h
 */
int Curl_easyopts_check(void)
{
  return ((CURLOPT_LASTENTRY%10000) != (305 + 1));
}
#endif
Changes to jni/curl/lib/file.c.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2020, 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 https://curl.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







|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2021, 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 https://curl.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
77
78
79
80
81
82
83
84
85
86
87
88

89
90

91
92
93
94
95
96
97
#  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 */







|
|

|
|
>

|
>







77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
#  define open_readonly(p,f) open((p),(f))
#endif

/*
 * Forward declarations.
 */

static CURLcode file_do(struct Curl_easy *data, bool *done);
static CURLcode file_done(struct Curl_easy *data,
                          CURLcode status, bool premature);
static CURLcode file_connect(struct Curl_easy *data, bool *done);
static CURLcode file_disconnect(struct Curl_easy *data,
                                struct connectdata *conn,
                                bool dead_connection);
static CURLcode file_setup_connection(struct Curl_easy *data,
                                      struct connectdata *conn);

/*
 * FILE scheme handler.
 */

const struct Curl_handler Curl_handler_file = {
  "FILE",                               /* scheme */
112
113
114
115
116
117
118
119

120

121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
  0,                                    /* defport */
  CURLPROTO_FILE,                       /* protocol */
  CURLPROTO_FILE,                       /* family */
  PROTOPT_NONETWORK | PROTOPT_NOURLQUERY /* flags */
};


static CURLcode file_setup_connection(struct connectdata *conn)

{

  /* allocate the FILE specific struct */
  conn->data->req.p.file = calloc(1, sizeof(struct FILEPROTO));
  if(!conn->data->req.p.file)
    return CURLE_OUT_OF_MEMORY;

  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 Curl_easy *data = conn->data;
  char *real_path;
  struct FILEPROTO *file = data->req.p.file;
  int fd;
#ifdef DOS_FILESYSTEM
  size_t i;
  char *actual_path;
#endif







|
>

>

|
|










|

<







114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139

140
141
142
143
144
145
146
  0,                                    /* defport */
  CURLPROTO_FILE,                       /* protocol */
  CURLPROTO_FILE,                       /* family */
  PROTOPT_NONETWORK | PROTOPT_NOURLQUERY /* flags */
};


static CURLcode file_setup_connection(struct Curl_easy *data,
                                      struct connectdata *conn)
{
  (void)conn;
  /* allocate the FILE specific struct */
  data->req.p.file = calloc(1, sizeof(struct FILEPROTO));
  if(!data->req.p.file)
    return CURLE_OUT_OF_MEMORY;

  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 Curl_easy *data, bool *done)
{

  char *real_path;
  struct FILEPROTO *file = data->req.p.file;
  int fd;
#ifdef DOS_FILESYSTEM
  size_t i;
  char *actual_path;
#endif
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227

228
229
230

231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
  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.up.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.p.file;
  (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)
{
  (void)dead_connection; /* not used */

  return file_done(conn, 0, 0);
}

#ifdef DOS_FILESYSTEM
#define DIRSEP '\\'
#else
#define DIRSEP '/'
#endif

static CURLcode file_upload(struct connectdata *conn)
{
  struct FILEPROTO *file = conn->data->req.p.file;
  const char *dir = strchr(file->path, DIRSEP);
  int fd;
  int mode;
  CURLcode result = CURLE_OK;
  struct Curl_easy *data = conn->data;
  char *buf = data->state.buffer;
  curl_off_t bytecount = 0;
  struct_stat file_stat;
  const char *buf2;

  /*
   * Since FILE: doesn't do the full init, we need to provide some extra
   * assignments here.
   */
  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" */







|







|
|

|














|
>



>
|








|

|




<









|


















|







197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251

252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
  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.up.path);
    file_done(data, CURLE_FILE_COULDNT_READ_FILE, FALSE);
    return CURLE_FILE_COULDNT_READ_FILE;
  }
  *done = TRUE;

  return CURLE_OK;
}

static CURLcode file_done(struct Curl_easy *data,
                          CURLcode status, bool premature)
{
  struct FILEPROTO *file = data->req.p.file;
  (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 Curl_easy *data,
                                struct connectdata *conn,
                                bool dead_connection)
{
  (void)dead_connection; /* not used */
  (void)conn;
  return file_done(data, 0, 0);
}

#ifdef DOS_FILESYSTEM
#define DIRSEP '\\'
#else
#define DIRSEP '/'
#endif

static CURLcode file_upload(struct Curl_easy *data)
{
  struct FILEPROTO *file = data->req.p.file;
  const char *dir = strchr(file->path, DIRSEP);
  int fd;
  int mode;
  CURLcode result = CURLE_OK;

  char *buf = data->state.buffer;
  curl_off_t bytecount = 0;
  struct_stat file_stat;
  const char *buf2;

  /*
   * Since FILE: doesn't do the full init, we need to provide some extra
   * assignments here.
   */
  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, 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" */
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
    data->state.resume_from = (curl_off_t)file_stat.st_size;
  }

  while(!result) {
    size_t nread;
    size_t nwrite;
    size_t readcount;
    result = Curl_fillreadbuffer(conn, data->set.buffer_size, &readcount);
    if(result)
      break;

    if(!readcount)
      break;

    nread = readcount;







|







297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
    data->state.resume_from = (curl_off_t)file_stat.st_size;
  }

  while(!result) {
    size_t nread;
    size_t nwrite;
    size_t readcount;
    result = Curl_fillreadbuffer(data, data->set.buffer_size, &readcount);
    if(result)
      break;

    if(!readcount)
      break;

    nread = readcount;
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409

410
411
412
413
414
415
416

417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
      break;
    }

    bytecount += nread;

    Curl_pgrsSetUploadCounter(data, bytecount);

    if(Curl_pgrsUpdate(conn))
      result = CURLE_ABORTED_BY_CALLBACK;
    else
      result = Curl_speedcheck(data, Curl_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 size_known;
  bool fstated = FALSE;
  struct Curl_easy *data = conn->data;
  char *buf = data->state.buffer;
  curl_off_t bytecount = 0;
  int fd;
  struct FILEPROTO *file;

  *done = TRUE; /* unconditionally */

  Curl_pgrsStartNow(data);

  if(data->set.upload)
    return file_upload(conn);

  file = conn->data->req.p.file;

  /* 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 = statbuf.st_mtime;
    fstated = TRUE;
  }

  if(fstated && !data->state.range && data->set.timecondition) {
    if(!Curl_meets_timecondition(data, data->info.filetime)) {
      *done = TRUE;
      return CURLE_OK;
    }
  }

  if(fstated) {
    time_t filetime;
    struct tm buffer;
    const struct tm *tm = &buffer;
    char header[80];

    msnprintf(header, sizeof(header),
              "Content-Length: %" CURL_FORMAT_CURL_OFF_T "\r\n",
              expected_size);
    result = Curl_client_write(conn, CLIENTWRITE_HEADER, header, 0);
    if(result)
      return result;


    result = Curl_client_write(conn, CLIENTWRITE_HEADER,
                               (char *)"Accept-ranges: bytes\r\n", 0);
    if(result)
      return result;

    filetime = (time_t)statbuf.st_mtime;
    result = Curl_gmtime(filetime, &buffer);
    if(result)
      return result;

    /* format: "Tue, 15 Nov 1994 12:45:26 GMT" */
    msnprintf(header, sizeof(header),
              "Last-Modified: %s, %02d %s %4d %02d:%02d:%02d GMT\r\n%s",
              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,
              data->set.opt_no_body ? "": "\r\n");
    result = Curl_client_write(conn, CLIENTWRITE_HEADER, header, 0);
    if(result)
      return result;
    /* set the file size to make it available post transfer */
    Curl_pgrsSetDownloadSize(data, expected_size);
    if(data->set.opt_no_body)
      return result;
  }

  /* Check whether file range has been specified */
  result = Curl_range(conn);
  if(result)
    return result;

  /* Adjust the start offset in case we want to get the N last bytes
   * of the stream if the filesize could be determined */
  if(data->state.resume_from < 0) {
    if(!fstated) {







|




|















|










|


<










|

|






|
|

















>
|
|
|
|
|
|
|
>
|




















|









|







333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374

375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
      break;
    }

    bytecount += nread;

    Curl_pgrsSetUploadCounter(data, bytecount);

    if(Curl_pgrsUpdate(data))
      result = CURLE_ABORTED_BY_CALLBACK;
    else
      result = Curl_speedcheck(data, Curl_now());
  }
  if(!result && Curl_pgrsUpdate(data))
    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 Curl_easy *data, 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 = -1;
  bool size_known;
  bool fstated = FALSE;

  char *buf = data->state.buffer;
  curl_off_t bytecount = 0;
  int fd;
  struct FILEPROTO *file;

  *done = TRUE; /* unconditionally */

  Curl_pgrsStartNow(data);

  if(data->set.upload)
    return file_upload(data);

  file = data->req.p.file;

  /* get the fd from the connection phase */
  fd = file->fd;

  /* VMS: This only works reliable for STREAMLF files */
  if(-1 != fstat(fd, &statbuf)) {
    if(!S_ISDIR(statbuf.st_mode))
      expected_size = statbuf.st_size;
    /* and store the modification time */
    data->info.filetime = statbuf.st_mtime;
    fstated = TRUE;
  }

  if(fstated && !data->state.range && data->set.timecondition) {
    if(!Curl_meets_timecondition(data, data->info.filetime)) {
      *done = TRUE;
      return CURLE_OK;
    }
  }

  if(fstated) {
    time_t filetime;
    struct tm buffer;
    const struct tm *tm = &buffer;
    char header[80];
    if(expected_size >= 0) {
      msnprintf(header, sizeof(header),
                "Content-Length: %" CURL_FORMAT_CURL_OFF_T "\r\n",
                expected_size);
      result = Curl_client_write(data, CLIENTWRITE_HEADER, header, 0);
      if(result)
        return result;
    }

    result = Curl_client_write(data, CLIENTWRITE_HEADER,
                               (char *)"Accept-ranges: bytes\r\n", 0);
    if(result)
      return result;

    filetime = (time_t)statbuf.st_mtime;
    result = Curl_gmtime(filetime, &buffer);
    if(result)
      return result;

    /* format: "Tue, 15 Nov 1994 12:45:26 GMT" */
    msnprintf(header, sizeof(header),
              "Last-Modified: %s, %02d %s %4d %02d:%02d:%02d GMT\r\n%s",
              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,
              data->set.opt_no_body ? "": "\r\n");
    result = Curl_client_write(data, CLIENTWRITE_HEADER, header, 0);
    if(result)
      return result;
    /* set the file size to make it available post transfer */
    Curl_pgrsSetDownloadSize(data, expected_size);
    if(data->set.opt_no_body)
      return result;
  }

  /* Check whether file range has been specified */
  result = Curl_range(data);
  if(result)
    return result;

  /* Adjust the start offset in case we want to get the N last bytes
   * of the stream if the filesize could be determined */
  if(data->state.resume_from < 0) {
    if(!fstated) {
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
    if(nread <= 0 || (size_known && (expected_size == 0)))
      break;

    bytecount += nread;
    if(size_known)
      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, Curl_now());
  }
  if(Curl_pgrsUpdate(conn))
    result = CURLE_ABORTED_BY_CALLBACK;

  return result;
}

#endif







|





|




|






515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
    if(nread <= 0 || (size_known && (expected_size == 0)))
      break;

    bytecount += nread;
    if(size_known)
      expected_size -= nread;

    result = Curl_client_write(data, CLIENTWRITE_BODY, buf, nread);
    if(result)
      return result;

    Curl_pgrsSetDownloadCounter(data, bytecount);

    if(Curl_pgrsUpdate(data))
      result = CURLE_ABORTED_BY_CALLBACK;
    else
      result = Curl_speedcheck(data, Curl_now());
  }
  if(Curl_pgrsUpdate(data))
    result = CURLE_ABORTED_BY_CALLBACK;

  return result;
}

#endif
Changes to jni/curl/lib/formdata.h.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#ifndef HEADER_CURL_FORMDATA_H
#define HEADER_CURL_FORMDATA_H
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2020, 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 https://curl.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









|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#ifndef HEADER_CURL_FORMDATA_H
#define HEADER_CURL_FORMDATA_H
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2021, 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 https://curl.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
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47




48
49
50
51
52
53
54
55
56
57
58
59
60
#include "curl_setup.h"

#ifndef CURL_DISABLE_MIME

/* used by FormAdd for temporary storage */
struct FormInfo {
  char *name;
  bool name_alloc;
  size_t namelength;
  char *value;
  bool value_alloc;
  curl_off_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;




};

CURLcode Curl_getformdata(struct Curl_easy *data,
                          curl_mimepart *,
                          struct curl_httppost *post,
                          curl_read_callback fread_func);
#else
/* disabled */
#define Curl_getformdata(a,b,c,d) CURLE_NOT_BUILT_IN
#endif


#endif /* HEADER_CURL_FORMDATA_H */







<


<


<





<



>
>
>
>













25
26
27
28
29
30
31

32
33

34
35

36
37
38
39
40

41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
#include "curl_setup.h"

#ifndef CURL_DISABLE_MIME

/* used by FormAdd for temporary storage */
struct FormInfo {
  char *name;

  size_t namelength;
  char *value;

  curl_off_t contentslength;
  char *contenttype;

  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 */

  char *userp;        /* pointer for the read callback */
  struct curl_slist *contentheader;
  struct FormInfo *more;
  bool name_alloc;
  bool value_alloc;
  bool contenttype_alloc;
  bool showfilename_alloc;
};

CURLcode Curl_getformdata(struct Curl_easy *data,
                          curl_mimepart *,
                          struct curl_httppost *post,
                          curl_read_callback fread_func);
#else
/* disabled */
#define Curl_getformdata(a,b,c,d) CURLE_NOT_BUILT_IN
#endif


#endif /* HEADER_CURL_FORMDATA_H */
Changes to jni/curl/lib/ftp.c.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2020, 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 https://curl.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







|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2021, 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 https://curl.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
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109

110
111
112
113
114
115
116
117
118
119
120
121
122
123
124

125
126
127
128
129
130
131
132

133
134

135
136

137
138
139

140
141
142
143
144

145
146
147
148
149
150
151
152
153
154
155

#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,
                             struct 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);
static int ftp_domore_getsock(struct connectdata *conn, curl_socket_t *socks);

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);

/*
 * FTP protocol handler.
 */

const struct Curl_handler Curl_handler_ftp = {







|



|





|
>

|
|
|

|




|
|
|

|
>



|
|

|
|
>
|
|
>
|
|
>
|

|
>
|
|

|
|
>



|







92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162

#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 Curl_easy *data,
                   ftpstate newstate);
#define state(x,y) _state(x,y)
#else
static void _state(struct Curl_easy *data,
                   ftpstate newstate,
                   int lineno);
#define state(x,y) _state(x,y,__LINE__)
#endif

static CURLcode ftp_sendquote(struct Curl_easy *data,
                              struct connectdata *conn,
                              struct curl_slist *quote);
static CURLcode ftp_quit(struct Curl_easy *data, struct connectdata *conn);
static CURLcode ftp_parse_url_path(struct Curl_easy *data);
static CURLcode ftp_regular_transfer(struct Curl_easy *data, bool *done);
#ifndef CURL_DISABLE_VERBOSE_STRINGS
static void ftp_pasv_verbose(struct Curl_easy *data,
                             struct Curl_addrinfo *ai,
                             char *newhost, /* ascii version */
                             int port);
#endif
static CURLcode ftp_state_prepare_transfer(struct Curl_easy *data);
static CURLcode ftp_state_mdtm(struct Curl_easy *data);
static CURLcode ftp_state_quote(struct Curl_easy *data,
                                bool init, ftpstate instate);
static CURLcode ftp_nb_type(struct Curl_easy *data,
                            struct connectdata *conn,
                            bool ascii, ftpstate newstate);
static int ftp_need_type(struct connectdata *conn,
                         bool ascii);
static CURLcode ftp_do(struct Curl_easy *data, bool *done);
static CURLcode ftp_done(struct Curl_easy *data,
                         CURLcode, bool premature);
static CURLcode ftp_connect(struct Curl_easy *data, bool *done);
static CURLcode ftp_disconnect(struct Curl_easy *data,
                               struct connectdata *conn, bool dead_connection);
static CURLcode ftp_do_more(struct Curl_easy *data, int *completed);
static CURLcode ftp_multi_statemach(struct Curl_easy *data, bool *done);
static int ftp_getsock(struct Curl_easy *data, struct connectdata *conn,
                       curl_socket_t *socks);
static int ftp_domore_getsock(struct Curl_easy *data,
                              struct connectdata *conn, curl_socket_t *socks);
static CURLcode ftp_doing(struct Curl_easy *data,
                          bool *dophase_done);
static CURLcode ftp_setup_connection(struct Curl_easy *data,
                                     struct connectdata *conn);
static CURLcode init_wc_data(struct Curl_easy *data);
static CURLcode wc_statemach(struct Curl_easy *data);
static void wc_data_dtor(void *ptr);
static CURLcode ftp_state_retr(struct Curl_easy *data, curl_off_t filesize);
static CURLcode ftp_readresp(struct Curl_easy *data,
                             curl_socket_t sockfd,
                             struct pingpong *pp,
                             int *ftpcode,
                             size_t *size);
static CURLcode ftp_dophase_done(struct Curl_easy *data,
                                 bool connected);

/*
 * FTP protocol handler.
 */

const struct Curl_handler Curl_handler_ftp = {
202
203
204
205
206
207
208
209

210
211
212
213
214
215
216
217
218
219
  CURLPROTO_FTPS,                  /* protocol */
  CURLPROTO_FTP,                   /* family */
  PROTOPT_SSL | PROTOPT_DUAL | PROTOPT_CLOSEACTION |
  PROTOPT_NEEDSPWD | PROTOPT_NOURLQUERY | PROTOPT_WILDCARD /* flags */
};
#endif

static void close_secondarysocket(struct connectdata *conn)

{
  if(CURL_SOCKET_BAD != conn->sock[SECONDARYSOCKET]) {
    Curl_closesocket(conn, conn->sock[SECONDARYSOCKET]);
    conn->sock[SECONDARYSOCKET] = CURL_SOCKET_BAD;
  }
  conn->bits.tcpconnect[SECONDARYSOCKET] = FALSE;
#ifndef CURL_DISABLE_PROXY
  conn->bits.proxy_ssl_connected[SECONDARYSOCKET] = FALSE;
#endif
}







|
>


|







209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
  CURLPROTO_FTPS,                  /* protocol */
  CURLPROTO_FTP,                   /* family */
  PROTOPT_SSL | PROTOPT_DUAL | PROTOPT_CLOSEACTION |
  PROTOPT_NEEDSPWD | PROTOPT_NOURLQUERY | PROTOPT_WILDCARD /* flags */
};
#endif

static void close_secondarysocket(struct Curl_easy *data,
                                  struct connectdata *conn)
{
  if(CURL_SOCKET_BAD != conn->sock[SECONDARYSOCKET]) {
    Curl_closesocket(data, conn, conn->sock[SECONDARYSOCKET]);
    conn->sock[SECONDARYSOCKET] = CURL_SOCKET_BAD;
  }
  conn->bits.tcpconnect[SECONDARYSOCKET] = FALSE;
#ifndef CURL_DISABLE_PROXY
  conn->bits.proxy_ssl_connected[SECONDARYSOCKET] = FALSE;
#endif
}
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
 *
 * 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 Curl_easy *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");
  /* when this happens within the DO state it is important that we mark us as







|

|














|







260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
 *
 * 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 Curl_easy *data)
{
  struct connectdata *conn = data->conn;
  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(data, 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");
  /* when this happens within the DO state it is important that we mark us as
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
    Curl_set_in_callback(data, true);
    error = data->set.fsockopt(data->set.sockopt_client,
                               s,
                               CURLSOCKTYPE_ACCEPT);
    Curl_set_in_callback(data, false);

    if(error) {
      close_secondarysocket(conn);
      return CURLE_ABORTED_BY_CALLBACK;
    }
  }

  return CURLE_OK;

}







|







303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
    Curl_set_in_callback(data, true);
    error = data->set.fsockopt(data->set.sockopt_client,
                               s,
                               CURLSOCKTYPE_ACCEPT);
    Curl_set_in_callback(data, false);

    if(error) {
      close_secondarysocket(data, conn);
      return CURLE_ABORTED_BY_CALLBACK;
    }
  }

  return CURLE_OK;

}
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
 * 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 Curl_easy *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;
  timediff_t timeout_ms;
  ssize_t nread;







|

|







359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
 * 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 Curl_easy *data, bool *received)
{
  struct connectdata *conn = data->conn;
  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;
  timediff_t timeout_ms;
  ssize_t nread;
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
    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");
    (void)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) {







|







385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
    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");
    (void)Curl_GetFTPResponse(data, &nread, &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) {
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413

    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");
      (void)Curl_GetFTPResponse(&nread, conn, &ftpcode);

      if(ftpcode/100 > 3)
        return CURLE_FTP_ACCEPT_FAILED;

      return CURLE_WEIRD_SERVER_REPLY;
    }








|







407
408
409
410
411
412
413
414
415
416
417
418
419
420
421

    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");
      (void)Curl_GetFTPResponse(data, &nread, &ftpcode);

      if(ftpcode/100 > 3)
        return CURLE_FTP_ACCEPT_FAILED;

      return CURLE_WEIRD_SERVER_REPLY;
    }

422
423
424
425
426
427
428
429
430
431
432

433
434
435
436
437
438
439
440
441
442
443
444
445
 *
 * 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 Curl_easy *data = conn->data;
  CURLcode result = CURLE_OK;


  if(conn->bits.ftp_use_data_ssl) {
    /* 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) {
    /* When we know we're uploading a specified file, we can get the file
       size prior to the actual upload. */







|

<

>





|







430
431
432
433
434
435
436
437
438

439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
 *
 * InitiateTransfer()
 *
 * After connection from server is accepted this function is called to
 * setup transfer parameters and initiate the data transfer.
 *
 */
static CURLcode InitiateTransfer(struct Curl_easy *data)
{

  CURLcode result = CURLE_OK;
  struct connectdata *conn = data->conn;

  if(conn->bits.ftp_use_data_ssl) {
    /* 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(data, conn, SECONDARYSOCKET);
    if(result)
      return result;
  }

  if(conn->proto.ftpc.state_saved == FTP_STOR) {
    /* When we know we're uploading a specified file, we can get the file
       size prior to the actual upload. */
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
  else {
    /* FTP download: */
    Curl_setup_transfer(data, SECONDARYSOCKET,
                        conn->proto.ftpc.retr_size_saved, FALSE, -1);
  }

  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 Curl_easy *data = conn->data;
  timediff_t 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(*connected == FALSE) {
      Curl_expire(data, data->set.accepttimeout > 0 ?







|













|

<

















|




|



|







461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483

484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
  else {
    /* FTP download: */
    Curl_setup_transfer(data, SECONDARYSOCKET,
                        conn->proto.ftpc.retr_size_saved, FALSE, -1);
  }

  conn->proto.ftpc.pp.pending_resp = TRUE; /* expect server response */
  state(data, 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 Curl_easy *data, bool *connected)
{

  timediff_t 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(data, connected);
  if(result)
    return result;

  if(*connected) {
    result = AcceptServerConnect(data);
    if(result)
      return result;

    result = InitiateTransfer(data);
    if(result)
      return result;
  }
  else {
    /* Add timeout to multi handle and break out of the loop */
    if(*connected == FALSE) {
      Curl_expire(data, data->set.accepttimeout > 0 ?
519
520
521
522
523
524
525
526
527
528

529
530
531
532
533
534
535
536
537
538
539

540
541
542
543
544

545
546


547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566

567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599

600
601
602
603
604
605
606
607
608
609
610

611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
   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 Curl_easy *data = conn->data;
#ifdef HAVE_GSSAPI


  char * const buf = data->state.buffer;
#endif
  int code;
  CURLcode result = Curl_pp_readresp(sockfd, pp, &code, size);

#if defined(HAVE_GSSAPI)
  /* handle the security-oriented responses 6xx ***/
  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];
  struct Curl_easy *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 */
    timediff_t timeout = Curl_pp_state_timeout(pp, FALSE);
    timediff_t interval_ms;

    if(timeout <= 0) {
      failf(data, "FTP response timeout");
      return CURLE_OPERATION_TIMEDOUT; /* already too little time */
    }








|
|

>










|
>




|
>
|

>
>
|
<
<
<

<
|
|
|
|
|
|
|
|
|
|
|
|
|
|
>


















|














>
|
<









>

<

















|







526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559



560

561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610

611
612
613
614
615
616
617
618
619
620
621

622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
   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 Curl_easy *data, struct connectdata *conn,
                          char *line, size_t len, int *code)
{
  (void)data;
  (void)conn;

  if((len > 3) && LASTLINE(line)) {
    *code = curlx_sltosi(strtol(line, NULL, 10));
    return TRUE;
  }

  return FALSE;
}

static CURLcode ftp_readresp(struct Curl_easy *data,
                             curl_socket_t sockfd,
                             struct pingpong *pp,
                             int *ftpcode, /* return the ftp-code if done */
                             size_t *size) /* size of the response */
{
  int code;
  CURLcode result = Curl_pp_readresp(data, sockfd, pp, &code, size);

#ifdef HAVE_GSSAPI
  {
    struct connectdata *conn = data->conn;
    char * const buf = data->state.buffer;





    /* handle the security-oriented responses 6xx ***/
    switch(code) {
    case 631:
      code = Curl_sec_read_msg(data, conn, buf, PROT_SAFE);
      break;
    case 632:
      code = Curl_sec_read_msg(data, conn, buf, PROT_PRIVATE);
      break;
    case 633:
      code = Curl_sec_read_msg(data, 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(data, 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(struct Curl_easy *data,
                             ssize_t *nreadp, /* return number of bytes read */

                             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.  */

  struct connectdata *conn = data->conn;
  curl_socket_t sockfd = conn->sock[FIRSTSOCKET];

  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 */
    timediff_t timeout = Curl_pp_state_timeout(data, pp, FALSE);
    timediff_t interval_ms;

    if(timeout <= 0) {
      failf(data, "FTP response timeout");
      return CURLE_OPERATION_TIMEDOUT; /* already too little time */
    }

665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
      switch(SOCKET_READABLE(sockfd, 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++;







|







|







674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
      switch(SOCKET_READABLE(sockfd, 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(data))
          return CURLE_ABORTED_BY_CALLBACK;
        continue; /* just continue in our loop for the timeout duration */

      default: /* for clarity */
        break;
      }
    }
    result = ftp_readresp(data, 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++;
737
738
739
740
741
742
743
744
745
746
747
748
749
750

751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768

769
770

771
772
773
774
775
776
777
778
779

780
781
782
783
784
785
786
787
788
789

790
791
792
793
794
795
796

797
798

799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845

846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905

906
907
908
909
910
911
912
913
914
  "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 = Curl_pp_sendf(&conn->proto.ftpc.pp, "USER %s",

                                  conn->user?conn->user:"");
  if(!result) {
    state(conn, FTP_USER);
    conn->data->state.ftp_trying_alternative = FALSE;
  }
  return result;
}

static CURLcode ftp_state_pwd(struct connectdata *conn)

{
  CURLcode result = Curl_pp_sendf(&conn->proto.ftpc.pp, "%s", "PWD");
  if(!result)
    state(conn, FTP_PWD);

  return result;
}

/* For the FTP "protocol connect" and "doing" phases only */
static int ftp_getsock(struct connectdata *conn,

                       curl_socket_t *socks)
{
  return Curl_pp_getsock(&conn->proto.ftpc.pp, socks);
}

/* For the FTP "DO_MORE" phase only */
static int ftp_domore_getsock(struct connectdata *conn, curl_socket_t *socks)

{
  struct ftp_conn *ftpc = &conn->proto.ftpc;


  /* 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(SOCKS_STATE(conn->cnnct.state))
    return Curl_SOCKS_getsock(conn, socks, SECONDARYSOCKET);

  if(FTP_STOP == ftpc->state) {
    int bits = GETSOCK_READSOCK(0);
    bool any = FALSE;

    /* 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++);
          any = TRUE;
        }
      }
    }
    if(!any) {
      socks[1] = conn->sock[SECONDARYSOCKET];
      bits |= GETSOCK_WRITESOCK(1) | GETSOCK_READSOCK(1);
    }

    return bits;
  }
  return Curl_pp_getsock(&conn->proto.ftpc.pp, socks);
}

/* 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 {
    /* FTPFILE_NOCWD with full path: expect ftpc->cwddone! */
    DEBUGASSERT((conn->data->set.ftp_filemethod != FTPFILE_NOCWD) ||
                !(ftpc->dirdepth && ftpc->dirs[0][0] == '/'));

    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 &&
       /* no need to go to entrypath when we have an absolute path */
       !(ftpc->dirdepth && ftpc->dirs[0][0] == '/')) {
      /* 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->cwdcount = 0; /* we count this as the first path, then we add one
                             for all upcoming ones in the ftp->dirs[] array */
      result = Curl_pp_sendf(&ftpc->pp, "CWD %s", ftpc->entrypath);
      if(!result)
        state(conn, FTP_CWD);
    }
    else {
      if(ftpc->dirdepth) {
        ftpc->cwdcount = 1;
        /* issue the first CWD, the rest is sent when the CWD responses are
           received... */
        result = Curl_pp_sendf(&ftpc->pp, "CWD %s",
                               ftpc->dirs[ftpc->cwdcount -1]);
        if(!result)
          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 Curl_easy *data = conn->data;
  curl_socket_t portsock = CURL_SOCKET_BAD;
  char myhost[MAX_IPADR_LEN + 1] = "";

  struct Curl_sockaddr_storage ss;
  struct Curl_addrinfo *res, *ai;
  curl_socklen_t sslen;
  char hbuf[NI_MAXHOST];







|






>








|








|
>

|
>


|
|




|
>

|

|





|
>


|



|
>


>

















|



















|








|
>






|


|







|









|

|






|


|



|












|



>

<







746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924

925
926
927
928
929
930
931
  "RETR",
  "STOR",
  "QUIT"
};
#endif

/* This is the ONLY way to change FTP state! */
static void _state(struct Curl_easy *data,
                   ftpstate newstate
#ifdef DEBUGBUILD
                   , int lineno
#endif
  )
{
  struct connectdata *conn = data->conn;
  struct ftp_conn *ftpc = &conn->proto.ftpc;

#if defined(DEBUGBUILD)

#if defined(CURL_DISABLE_VERBOSE_STRINGS)
  (void) lineno;
#else
  if(ftpc->state != newstate)
    infof(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 Curl_easy *data,
                               struct connectdata *conn)
{
  CURLcode result = Curl_pp_sendf(data,
                                  &conn->proto.ftpc.pp, "USER %s",
                                  conn->user?conn->user:"");
  if(!result) {
    state(data, FTP_USER);
    data->state.ftp_trying_alternative = FALSE;
  }
  return result;
}

static CURLcode ftp_state_pwd(struct Curl_easy *data,
                              struct connectdata *conn)
{
  CURLcode result = Curl_pp_sendf(data, &conn->proto.ftpc.pp, "%s", "PWD");
  if(!result)
    state(data, FTP_PWD);

  return result;
}

/* For the FTP "protocol connect" and "doing" phases only */
static int ftp_getsock(struct Curl_easy *data,
                       struct connectdata *conn,
                       curl_socket_t *socks)
{
  return Curl_pp_getsock(data, &conn->proto.ftpc.pp, socks);
}

/* For the FTP "DO_MORE" phase only */
static int ftp_domore_getsock(struct Curl_easy *data,
                              struct connectdata *conn, curl_socket_t *socks)
{
  struct ftp_conn *ftpc = &conn->proto.ftpc;
  (void)data;

  /* 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(SOCKS_STATE(conn->cnnct.state))
    return Curl_SOCKS_getsock(conn, socks, SECONDARYSOCKET);

  if(FTP_STOP == ftpc->state) {
    int bits = GETSOCK_READSOCK(0);
    bool any = FALSE;

    /* 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(!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++);
          any = TRUE;
        }
      }
    }
    if(!any) {
      socks[1] = conn->sock[SECONDARYSOCKET];
      bits |= GETSOCK_WRITESOCK(1) | GETSOCK_READSOCK(1);
    }

    return bits;
  }
  return Curl_pp_getsock(data, &conn->proto.ftpc.pp, socks);
}

/* 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 Curl_easy *data,
                              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(data);
  else {
    /* FTPFILE_NOCWD with full path: expect ftpc->cwddone! */
    DEBUGASSERT((data->set.ftp_filemethod != FTPFILE_NOCWD) ||
                !(ftpc->dirdepth && ftpc->dirs[0][0] == '/'));

    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 = (data->set.ftp_create_missing_dirs == 2)?1:0;

    if(conn->bits.reuse && ftpc->entrypath &&
       /* no need to go to entrypath when we have an absolute path */
       !(ftpc->dirdepth && ftpc->dirs[0][0] == '/')) {
      /* 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->cwdcount = 0; /* we count this as the first path, then we add one
                             for all upcoming ones in the ftp->dirs[] array */
      result = Curl_pp_sendf(data, &ftpc->pp, "CWD %s", ftpc->entrypath);
      if(!result)
        state(data, FTP_CWD);
    }
    else {
      if(ftpc->dirdepth) {
        ftpc->cwdcount = 1;
        /* issue the first CWD, the rest is sent when the CWD responses are
           received... */
        result = Curl_pp_sendf(data, &ftpc->pp, "CWD %s",
                               ftpc->dirs[ftpc->cwdcount -1]);
        if(!result)
          state(data, FTP_CWD);
      }
      else {
        /* No CWD necessary */
        result = ftp_state_mdtm(data);
      }
    }
  }
  return result;
}

typedef enum {
  EPRT,
  PORT,
  DONE
} ftpport;

static CURLcode ftp_state_use_port(struct Curl_easy *data,
                                   ftpport fcmd) /* start with this */
{
  CURLcode result = CURLE_OK;
  struct connectdata *conn = data->conn;
  struct ftp_conn *ftpc = &conn->proto.ftpc;

  curl_socket_t portsock = CURL_SOCKET_BAD;
  char myhost[MAX_IPADR_LEN + 1] = "";

  struct Curl_sockaddr_storage ss;
  struct Curl_addrinfo *res, *ai;
  curl_socklen_t sslen;
  char hbuf[NI_MAXHOST];
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
    if(!r)
      return CURLE_FTP_PORT_FAILED;
    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, FALSE, &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







|

|







1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
    if(!r)
      return CURLE_FTP_PORT_FAILED;
    host = hbuf; /* use this host name */
    possibly_non_local = FALSE; /* we know it is local now */
  }

  /* resolv ip/host to ip */
  rc = Curl_resolv(data, host, 0, FALSE, &h);
  if(rc == CURLRESOLV_PENDING)
    (void)Curl_resolver_wait_resolv(data, &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
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
  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) {







|







1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
  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(data, ai, NULL, &portsock);
    if(result) {
      error = SOCKERRNO;
      continue;
    }
    break;
  }
  if(!ai) {
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
        infof(data, "bind(port=%hu) on non-local address failed: %s\n", port,
              Curl_strerror(error, buffer, sizeof(buffer)));

        sslen = sizeof(ss);
        if(getsockname(conn->sock[FIRSTSOCKET], sa, &sslen)) {
          failf(data, "getsockname() failed: %s",
                Curl_strerror(SOCKERRNO, buffer, sizeof(buffer)));
          Curl_closesocket(conn, portsock);
          return CURLE_FTP_PORT_FAILED;
        }
        port = port_min;
        possibly_non_local = FALSE; /* don't try this again */
        continue;
      }
      if(error != EADDRINUSE && error != EACCES) {
        failf(data, "bind(port=%hu) failed: %s", port,
              Curl_strerror(error, buffer, sizeof(buffer)));
        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(SOCKERRNO, buffer, sizeof(buffer)));
    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(SOCKERRNO, buffer, sizeof(buffer)));
    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 */







|









|












|









|








|







1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
        infof(data, "bind(port=%hu) on non-local address failed: %s\n", port,
              Curl_strerror(error, buffer, sizeof(buffer)));

        sslen = sizeof(ss);
        if(getsockname(conn->sock[FIRSTSOCKET], sa, &sslen)) {
          failf(data, "getsockname() failed: %s",
                Curl_strerror(SOCKERRNO, buffer, sizeof(buffer)));
          Curl_closesocket(data, conn, portsock);
          return CURLE_FTP_PORT_FAILED;
        }
        port = port_min;
        possibly_non_local = FALSE; /* don't try this again */
        continue;
      }
      if(error != EADDRINUSE && error != EACCES) {
        failf(data, "bind(port=%hu) failed: %s", port,
              Curl_strerror(error, buffer, sizeof(buffer)));
        Curl_closesocket(data, 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(data, 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(SOCKERRNO, buffer, sizeof(buffer)));
    Curl_closesocket(data, conn, portsock);
    return CURLE_FTP_PORT_FAILED;
  }

  /* step 4, listen on the socket */

  if(listen(portsock, 1)) {
    failf(data, "socket failure: %s",
          Curl_strerror(SOCKERRNO, buffer, sizeof(buffer)));
    Curl_closesocket(data, 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 */
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
       * 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;
    }
    if(PORT == fcmd) {
      /* large enough for [IP address],[num],[num] */
      char target[sizeof(myhost) + 20];







|





|



|







1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
       * Two fine examples from RFC2428;
       *
       * EPRT |1|132.235.1.2|6275|
       *
       * EPRT |2|1080::8:800:200C:417A|5282|
       */

      result = Curl_pp_sendf(data, &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(data, conn, portsock);
        /* don't retry using PORT */
        ftpc->count1 = PORT;
        /* bail out */
        state(data, FTP_STOP);
        return result;
      }
      break;
    }
    if(PORT == fcmd) {
      /* large enough for [IP address],[num],[num] */
      char target[sizeof(myhost) + 20];
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290

1291
1292
1293
1294
1295
1296
1297
          *dest = *source;
        dest++;
        source++;
      }
      *dest = 0;
      msnprintf(dest, 20, ",%d,%d", (int)(port>>8), (int)(port&0xff));

      result = Curl_pp_sendf(&ftpc->pp, "%s %s", mode[fcmd], target);
      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;

  close_secondarysocket(conn);

  /* 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 */
  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 executive summary on what to do:

    PASV is RFC959, expect:







|



|

|









|















|



|
>







1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
          *dest = *source;
        dest++;
        source++;
      }
      *dest = 0;
      msnprintf(dest, 20, ",%d,%d", (int)(port>>8), (int)(port&0xff));

      result = Curl_pp_sendf(data, &ftpc->pp, "%s %s", mode[fcmd], target);
      if(result) {
        failf(data, "Failure sending PORT command: %s",
              curl_easy_strerror(result));
        Curl_closesocket(data, conn, portsock);
        /* bail out */
        state(data, FTP_STOP);
        return result;
      }
      break;
    }
  }

  /* store which command was sent */
  ftpc->count1 = fcmd;

  close_secondarysocket(data, conn);

  /* 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 */
  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(data, FTP_PORT);
  return result;
}

static CURLcode ftp_state_use_pasv(struct Curl_easy *data,
                                   struct connectdata *conn)
{
  struct ftp_conn *ftpc = &conn->proto.ftpc;
  CURLcode result = CURLE_OK;
  /*
    Here's the executive summary on what to do:

    PASV is RFC959, expect:
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379

1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400

1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424

1425
1426
1427
1428
1429
1430
1431
    /* 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;

  result = Curl_pp_sendf(&ftpc->pp, "%s", mode[modeoff]);
  if(!result) {
    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.p.ftp;
  struct Curl_easy *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 */
      struct ftp_conn *ftpc = &conn->proto.ftpc;
      if(!conn->proto.ftpc.file)
        result = Curl_pp_sendf(&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)
        result = Curl_pp_sendf(&ftpc->pp, "PRET STOR %s",
                               conn->proto.ftpc.file);
      else
        result = Curl_pp_sendf(&ftpc->pp, "PRET RETR %s",
                               conn->proto.ftpc.file);
      if(!result)
        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.p.ftp;
  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 */
    result = Curl_pp_sendf(&ftpc->pp, "REST %d", 0);
    if(!result)
      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.p.ftp;
  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 */
    result = Curl_pp_sendf(&ftpc->pp, "SIZE %s", ftpc->file);
    if(!result)
      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 Curl_easy *data = conn->data;
  struct FTP *ftp = data->req.p.ftp;


  /* 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... */

  /*







|


|
|











|


|
|





|
|



|








|




|


|


|


|




|
>


|







|

|


|




|
>


|






|

|


|




|


<

>







1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442

1443
1444
1445
1446
1447
1448
1449
1450
1451
    /* 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;

  result = Curl_pp_sendf(data, &ftpc->pp, "%s", mode[modeoff]);
  if(!result) {
    ftpc->count1 = modeoff;
    state(data, FTP_PASV);
    infof(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 Curl_easy *data)
{
  CURLcode result = CURLE_OK;
  struct FTP *ftp = data->req.p.ftp;
  struct connectdata *conn = data->conn;

  if(ftp->transfer != FTPTRANSFER_BODY) {
    /* doesn't transfer any data */

    /* still possibly do PRE QUOTE jobs */
    state(data, FTP_RETR_PREQUOTE);
    result = ftp_state_quote(data, 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(data, 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 */
      struct ftp_conn *ftpc = &conn->proto.ftpc;
      if(!conn->proto.ftpc.file)
        result = Curl_pp_sendf(data, &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)
        result = Curl_pp_sendf(data, &ftpc->pp, "PRET STOR %s",
                               conn->proto.ftpc.file);
      else
        result = Curl_pp_sendf(data, &ftpc->pp, "PRET RETR %s",
                               conn->proto.ftpc.file);
      if(!result)
        state(data, FTP_PRET);
    }
    else
      result = ftp_state_use_pasv(data, conn);
  }
  return result;
}

static CURLcode ftp_state_rest(struct Curl_easy *data,
                               struct connectdata *conn)
{
  CURLcode result = CURLE_OK;
  struct FTP *ftp = data->req.p.ftp;
  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 */
    result = Curl_pp_sendf(data, &ftpc->pp, "REST %d", 0);
    if(!result)
      state(data, FTP_REST);
  }
  else
    result = ftp_state_prepare_transfer(data);

  return result;
}

static CURLcode ftp_state_size(struct Curl_easy *data,
                               struct connectdata *conn)
{
  CURLcode result = CURLE_OK;
  struct FTP *ftp = data->req.p.ftp;
  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 */
    result = Curl_pp_sendf(data, &ftpc->pp, "SIZE %s", ftpc->file);
    if(!result)
      state(data, FTP_SIZE);
  }
  else
    result = ftp_state_rest(data, conn);

  return result;
}

static CURLcode ftp_state_list(struct Curl_easy *data)
{
  CURLcode result = CURLE_OK;

  struct FTP *ftp = data->req.p.ftp;
  struct connectdata *conn = data->conn;

  /* 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... */

  /*
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557

1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
                lstArg? " ": "",
                lstArg? lstArg: "");
  free(lstArg);

  if(!cmd)
    return CURLE_OUT_OF_MEMORY;

  result = Curl_pp_sendf(&conn->proto.ftpc.pp, "%s", cmd);
  free(cmd);

  if(!result)
    state(conn, FTP_LIST);

  return result;
}

static CURLcode ftp_state_retr_prequote(struct connectdata *conn)
{
  /* We've sent the TYPE, now we must send the list of prequote strings */
  return ftp_state_quote(conn, TRUE, FTP_RETR_PREQUOTE);
}

static CURLcode ftp_state_stor_prequote(struct connectdata *conn)
{
  /* We've sent the TYPE, now we must send the list of prequote strings */
  return ftp_state_quote(conn, TRUE, FTP_STOR_PREQUOTE);
}

static CURLcode ftp_state_type(struct connectdata *conn)
{
  CURLcode result = CURLE_OK;
  struct FTP *ftp = conn->data->req.p.ftp;
  struct Curl_easy *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 therefore 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 Curl_easy *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 */
    result = Curl_pp_sendf(&ftpc->pp, "MDTM %s", ftpc->file);

    if(!result)
      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.p.ftp;
  struct Curl_easy *data = conn->data;
  struct ftp_conn *ftpc = &conn->proto.ftpc;

  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 */
    int seekerr = CURL_SEEKFUNC_OK;

    if(data->state.resume_from < 0) {
      /* Got no given size to start from, figure it out */
      result = Curl_pp_sendf(&ftpc->pp, "SIZE %s", ftpc->file);
      if(!result)
        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. */







|



|




|


|


|


|


|


|
|
















|




|






|


|







|


|


|






|



>
|
<




















|

|







1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579

1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
                lstArg? " ": "",
                lstArg? lstArg: "");
  free(lstArg);

  if(!cmd)
    return CURLE_OUT_OF_MEMORY;

  result = Curl_pp_sendf(data, &conn->proto.ftpc.pp, "%s", cmd);
  free(cmd);

  if(!result)
    state(data, FTP_LIST);

  return result;
}

static CURLcode ftp_state_retr_prequote(struct Curl_easy *data)
{
  /* We've sent the TYPE, now we must send the list of prequote strings */
  return ftp_state_quote(data, TRUE, FTP_RETR_PREQUOTE);
}

static CURLcode ftp_state_stor_prequote(struct Curl_easy *data)
{
  /* We've sent the TYPE, now we must send the list of prequote strings */
  return ftp_state_quote(data, TRUE, FTP_STOR_PREQUOTE);
}

static CURLcode ftp_state_type(struct Curl_easy *data)
{
  CURLcode result = CURLE_OK;
  struct FTP *ftp = data->req.p.ftp;
  struct connectdata *conn = data->conn;
  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 therefore 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(data, conn, data->set.prefer_ascii, FTP_TYPE);
    if(result)
      return result;
  }
  else
    result = ftp_state_size(data, 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 Curl_easy *data)
{
  CURLcode result = CURLE_OK;
  struct connectdata *conn = data->conn;
  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 */
    result = Curl_pp_sendf(data, &ftpc->pp, "MDTM %s", ftpc->file);

    if(!result)
      state(data, FTP_MDTM);
  }
  else
    result = ftp_state_type(data);

  return result;
}


/* This is called after the TYPE and possible quote commands have been sent */
static CURLcode ftp_state_ul_setup(struct Curl_easy *data,
                                   bool sizechecked)
{
  CURLcode result = CURLE_OK;
  struct connectdata *conn = data->conn;
  struct FTP *ftp = data->req.p.ftp;

  struct ftp_conn *ftpc = &conn->proto.ftpc;

  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 */
    int seekerr = CURL_SEEKFUNC_OK;

    if(data->state.resume_from < 0) {
      /* Got no given size to start from, figure it out */
      result = Curl_pp_sendf(data, &ftpc->pp, "SIZE %s", ftpc->file);
      if(!result)
        state(data, FTP_STOR_SIZE);
      return result;
    }

    /* enable append */
    data->set.ftp_append = TRUE;

    /* Let's read off the proper amount of bytes from the input. */
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643

1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658

1659
1660
1661
1662
1663
1664
1665
        /* no data to transfer */
        Curl_setup_transfer(data, -1, -1, FALSE, -1);

        /* 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 */


  result = Curl_pp_sendf(&ftpc->pp, data->set.ftp_append?"APPE %s":"STOR %s",
                         ftpc->file);
  if(!result)
    state(conn, FTP_STOR);

  return result;
}

static CURLcode ftp_state_quote(struct connectdata *conn,
                                bool init,
                                ftpstate instate)
{
  CURLcode result = CURLE_OK;
  struct Curl_easy *data = conn->data;
  struct FTP *ftp = data->req.p.ftp;

  struct ftp_conn *ftpc = &conn->proto.ftpc;
  bool quote = FALSE;
  struct curl_slist *item;

  switch(instate) {
  case FTP_QUOTE:
  default:







|






>
|


|




|




<

>







1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677

1678
1679
1680
1681
1682
1683
1684
1685
1686
        /* no data to transfer */
        Curl_setup_transfer(data, -1, -1, FALSE, -1);

        /* Set ->transfer so that we won't get any error in
         * ftp_done() because we didn't transfer anything! */
        ftp->transfer = FTPTRANSFER_NONE;

        state(data, FTP_STOP);
        return CURLE_OK;
      }
    }
    /* we've passed, proceed as normal */
  } /* resume_from */

  result = Curl_pp_sendf(data, &ftpc->pp,
                         data->set.ftp_append?"APPE %s":"STOR %s",
                         ftpc->file);
  if(!result)
    state(data, FTP_STOR);

  return result;
}

static CURLcode ftp_state_quote(struct Curl_easy *data,
                                bool init,
                                ftpstate instate)
{
  CURLcode result = CURLE_OK;

  struct FTP *ftp = data->req.p.ftp;
  struct connectdata *conn = data->conn;
  struct ftp_conn *ftpc = &conn->proto.ftpc;
  bool quote = FALSE;
  struct curl_slist *item;

  switch(instate) {
  case FTP_QUOTE:
  default:
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761

1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805

1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
      if(cmd[0] == '*') {
        cmd++;
        ftpc->count2 = 1; /* the sent command is allowed to fail */
      }
      else
        ftpc->count2 = 0; /* failure means cancel operation */

      result = Curl_pp_sendf(&ftpc->pp, "%s", cmd);
      if(result)
        return result;
      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 {
          if(data->set.ignorecl) {
            /* This code is to support download of growing files.  It prevents
               the state machine from requesting the file size from the
               server.  With an unknown file size the download continues until
               the server terminates it, otherwise the client stops if the
               received byte count exceeds the reported file size.  Set option
               CURLOPT_IGNORE_CONTENT_LENGTH to 1 to enable this behavior.*/
            result = Curl_pp_sendf(&ftpc->pp, "RETR %s", ftpc->file);
            if(!result)
              state(conn, FTP_RETR);
          }
          else {
            result = Curl_pp_sendf(&ftpc->pp, "SIZE %s", ftpc->file);
            if(!result)
              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
#ifndef CURL_DISABLE_PROXY
     && !(conn->bits.tunnel_proxy || conn->bits.socksproxy)
#endif
    ) {
    /* We can't disable EPSV when doing IPv6, so this is instead a fail */
    failf(conn->data, "Failed EPSV attempt, exiting\n");
    return CURLE_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 */
  result = Curl_pp_sendf(&conn->proto.ftpc.pp, "%s", "PASV");
  if(!result) {
    conn->proto.ftpc.count1++;
    /* remain in/go to the FTP_PASV state */
    state(conn, FTP_PASV);
  }
  return result;
}


static char *control_address(struct connectdata *conn)
{
  /* Returns the control connection IP address.
     If a proxy tunnel is used, returns the original host name instead, because
     the effective control connection address is the proxy address,
     not the ftp host. */
#ifndef CURL_DISABLE_PROXY
  if(conn->bits.tunnel_proxy || conn->bits.socksproxy)
    return conn->host.name;
#endif
  return conn->ip_addr_str;
}

static CURLcode ftp_state_pasv_resp(struct connectdata *conn,
                                    int ftpcode)
{

  struct ftp_conn *ftpc = &conn->proto.ftpc;
  CURLcode result;
  struct Curl_easy *data = conn->data;
  struct Curl_dns_entry *addr = NULL;
  enum resolve_t 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);







|


|









|



|



|









|

|


|

|





|











|
>









|



|


|

|



|















|


|


>


<







1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830

1831
1832
1833
1834
1835
1836
1837
      if(cmd[0] == '*') {
        cmd++;
        ftpc->count2 = 1; /* the sent command is allowed to fail */
      }
      else
        ftpc->count2 = 0; /* failure means cancel operation */

      result = Curl_pp_sendf(data, &ftpc->pp, "%s", cmd);
      if(result)
        return result;
      state(data, instate);
      quote = TRUE;
    }
  }

  if(!quote) {
    /* No more quote to send, continue to ... */
    switch(instate) {
    case FTP_QUOTE:
    default:
      result = ftp_state_cwd(data, conn);
      break;
    case FTP_RETR_PREQUOTE:
      if(ftp->transfer != FTPTRANSFER_BODY)
        state(data, FTP_STOP);
      else {
        if(ftpc->known_filesize != -1) {
          Curl_pgrsSetDownloadSize(data, ftpc->known_filesize);
          result = ftp_state_retr(data, ftpc->known_filesize);
        }
        else {
          if(data->set.ignorecl) {
            /* This code is to support download of growing files.  It prevents
               the state machine from requesting the file size from the
               server.  With an unknown file size the download continues until
               the server terminates it, otherwise the client stops if the
               received byte count exceeds the reported file size.  Set option
               CURLOPT_IGNORE_CONTENT_LENGTH to 1 to enable this behavior.*/
            result = Curl_pp_sendf(data, &ftpc->pp, "RETR %s", ftpc->file);
            if(!result)
              state(data, FTP_RETR);
          }
          else {
            result = Curl_pp_sendf(data, &ftpc->pp, "SIZE %s", ftpc->file);
            if(!result)
              state(data, FTP_RETR_SIZE);
          }
        }
      }
      break;
    case FTP_STOR_PREQUOTE:
      result = ftp_state_ul_setup(data, 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 Curl_easy *data,
                                 struct connectdata *conn)
{
  CURLcode result = CURLE_OK;

  if(conn->bits.ipv6
#ifndef CURL_DISABLE_PROXY
     && !(conn->bits.tunnel_proxy || conn->bits.socksproxy)
#endif
    ) {
    /* We can't disable EPSV when doing IPv6, so this is instead a fail */
    failf(data, "Failed EPSV attempt, exiting");
    return CURLE_WEIRD_SERVER_REPLY;
  }

  infof(data, "Failed EPSV attempt. Disabling EPSV\n");
  /* disable it for next transfer */
  conn->bits.ftp_use_epsv = FALSE;
  data->state.errorbuf = FALSE; /* allow error message to get
                                         rewritten */
  result = Curl_pp_sendf(data, &conn->proto.ftpc.pp, "%s", "PASV");
  if(!result) {
    conn->proto.ftpc.count1++;
    /* remain in/go to the FTP_PASV state */
    state(data, FTP_PASV);
  }
  return result;
}


static char *control_address(struct connectdata *conn)
{
  /* Returns the control connection IP address.
     If a proxy tunnel is used, returns the original host name instead, because
     the effective control connection address is the proxy address,
     not the ftp host. */
#ifndef CURL_DISABLE_PROXY
  if(conn->bits.tunnel_proxy || conn->bits.socksproxy)
    return conn->host.name;
#endif
  return conn->primary_ip;
}

static CURLcode ftp_state_pasv_resp(struct Curl_easy *data,
                                    int ftpcode)
{
  struct connectdata *conn = data->conn;
  struct ftp_conn *ftpc = &conn->proto.ftpc;
  CURLcode result;

  struct Curl_dns_entry *addr = NULL;
  enum resolve_t 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);
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
    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;
  }

#ifndef CURL_DISABLE_PROXY
  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!
     */
    const char * const host_name = conn->bits.socksproxy ?
      conn->socks_proxy.host.name : conn->http_proxy.host.name;
    rc = Curl_resolv(conn, host_name, (int)conn->port, FALSE, &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", host_name, connectport);
      return CURLE_COULDNT_RESOLVE_PROXY;
    }
  }
  else
#endif
  {
    /* normal, direct, ftp connection */
    DEBUGASSERT(ftpc->newhost);

    /* postponed address resolution in case of tcp fastopen */
    if(conn->bits.tcp_fastopen && !conn->bits.reuse && !ftpc->newhost[0]) {
      Curl_conninfo_remote(conn, conn->sock[FIRSTSOCKET]);
      Curl_safefree(ftpc->newhost);
      ftpc->newhost = strdup(control_address(conn));
      if(!ftpc->newhost)
        return CURLE_OUT_OF_MEMORY;
    }

    rc = Curl_resolv(conn, ftpc->newhost, ftpc->newport, FALSE, &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);

  if(result) {
    Curl_resolv_unlock(data, addr); /* we're done using this address */
    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, addr->addr, ftpc->newhost, connectport);

  Curl_resolv_unlock(data, addr); /* we're done using this address */

  Curl_safefree(conn->secondaryhostname);
  conn->secondary_port = ftpc->newport;
  conn->secondaryhostname = strdup(ftpc->newhost);
  if(!conn->secondaryhostname)
    return CURLE_OUT_OF_MEMORY;

  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 Curl_easy *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) {







|















|



|

















|






|


|










|




|













|










|




|


|







1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
    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(data, conn);
  }
  else {
    failf(data, "Bad PASV/EPSV response: %03d", ftpcode);
    return CURLE_FTP_WEIRD_PASV_REPLY;
  }

#ifndef CURL_DISABLE_PROXY
  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!
     */
    const char * const host_name = conn->bits.socksproxy ?
      conn->socks_proxy.host.name : conn->http_proxy.host.name;
    rc = Curl_resolv(data, host_name, (int)conn->port, FALSE, &addr);
    if(rc == CURLRESOLV_PENDING)
      /* BLOCKING, ignores the return code but 'addr' will be NULL in
         case of failure */
      (void)Curl_resolver_wait_resolv(data, &addr);

    connectport =
      (unsigned short)conn->port; /* we connect to the proxy's port */

    if(!addr) {
      failf(data, "Can't resolve proxy host %s:%hu", host_name, connectport);
      return CURLE_COULDNT_RESOLVE_PROXY;
    }
  }
  else
#endif
  {
    /* normal, direct, ftp connection */
    DEBUGASSERT(ftpc->newhost);

    /* postponed address resolution in case of tcp fastopen */
    if(conn->bits.tcp_fastopen && !conn->bits.reuse && !ftpc->newhost[0]) {
      Curl_conninfo_remote(data, conn, conn->sock[FIRSTSOCKET]);
      Curl_safefree(ftpc->newhost);
      ftpc->newhost = strdup(control_address(conn));
      if(!ftpc->newhost)
        return CURLE_OUT_OF_MEMORY;
    }

    rc = Curl_resolv(data, ftpc->newhost, ftpc->newport, FALSE, &addr);
    if(rc == CURLRESOLV_PENDING)
      /* BLOCKING */
      (void)Curl_resolver_wait_resolv(data, &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(data, conn, addr);

  if(result) {
    Curl_resolv_unlock(data, addr); /* we're done using this address */
    if(ftpc->count1 == 0 && ftpcode == 229)
      return ftp_epsv_disable(data, 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(data, addr->addr, ftpc->newhost, connectport);

  Curl_resolv_unlock(data, addr); /* we're done using this address */

  Curl_safefree(conn->secondaryhostname);
  conn->secondary_port = ftpc->newport;
  conn->secondaryhostname = strdup(ftpc->newhost);
  if(!conn->secondaryhostname)
    return CURLE_OUT_OF_MEMORY;

  conn->bits.do_more = TRUE;
  state(data, FTP_STOP); /* this phase is completed */

  return result;
}

static CURLcode ftp_state_port_resp(struct Curl_easy *data,
                                    int ftpcode)
{
  struct connectdata *conn = data->conn;
  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) {
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044

2045
2046
2047
2048
2049
2050
2051

    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 Curl_easy *data = conn->data;
  struct FTP *ftp = data->req.p.ftp;

  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 */







|



|
|





|



<

>







2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064

2065
2066
2067
2068
2069
2070
2071
2072
2073

    if(fcmd == DONE) {
      failf(data, "Failed to do PORT");
      result = CURLE_FTP_PORT_FAILED;
    }
    else
      /* try next */
      result = ftp_state_use_port(data, fcmd);
  }
  else {
    infof(data, "Connect data stream actively\n");
    state(data, FTP_STOP); /* end of DO phase */
    result = ftp_dophase_done(data, FALSE);
  }

  return result;
}

static CURLcode ftp_state_mdtm_resp(struct Curl_easy *data,
                                    int ftpcode)
{
  CURLcode result = CURLE_OK;

  struct FTP *ftp = data->req.p.ftp;
  struct connectdata *conn = data->conn;
  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 */
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
                  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, headerbuf, 0);
        if(result)
          return result;
      } /* end of a ridiculous amount of conditionals */
#endif
    }
    break;
  default:







|







2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
                  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(data, CLIENTWRITE_BOTH, headerbuf, 0);
        if(result)
          return result;
      } /* end of a ridiculous amount of conditionals */
#endif
    }
    break;
  default:
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177

2178
2179
2180
2181
2182
2183
2184
      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 Curl_easy *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 Curl_easy *data = conn->data;
  struct FTP *ftp = data->req.p.ftp;

  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;







|








|











|




|




|













|

|

|

|




|
|


<

>







2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197

2198
2199
2200
2201
2202
2203
2204
2205
2206
      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(data, 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(data, FTP_STOP);
          return CURLE_OK;
        }
        break;
      } /* switch */
    }
    else {
      infof(data, "Skipping time comparison\n");
    }
  }

  if(!result)
    result = ftp_state_type(data);

  return result;
}

static CURLcode ftp_state_type_resp(struct Curl_easy *data,
                                    int ftpcode,
                                    ftpstate instate)
{
  CURLcode result = CURLE_OK;
  struct connectdata *conn = data->conn;

  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(data, conn);
  else if(instate == FTP_LIST_TYPE)
    result = ftp_state_list(data);
  else if(instate == FTP_RETR_TYPE)
    result = ftp_state_retr_prequote(data);
  else if(instate == FTP_STOR_TYPE)
    result = ftp_state_stor_prequote(data);

  return result;
}

static CURLcode ftp_state_retr(struct Curl_easy *data,
                               curl_off_t filesize)
{
  CURLcode result = CURLE_OK;

  struct FTP *ftp = data->req.p.ftp;
  struct connectdata *conn = data->conn;
  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;
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
      /* no data to transfer */
      Curl_setup_transfer(data, -1, -1, FALSE, -1);
      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);

    result = Curl_pp_sendf(&ftpc->pp, "REST %" CURL_FORMAT_CURL_OFF_T,
                           data->state.resume_from);
    if(!result)
      state(conn, FTP_RETR_REST);
  }
  else {
    /* no resume */
    result = Curl_pp_sendf(&ftpc->pp, "RETR %s", ftpc->file);
    if(!result)
      state(conn, FTP_RETR);
  }

  return result;
}

static CURLcode ftp_state_size_resp(struct connectdata *conn,
                                    int ftpcode,
                                    ftpstate instate)
{
  CURLcode result = CURLE_OK;
  struct Curl_easy *data = conn->data;
  curl_off_t filesize = -1;
  char *buf = data->state.buffer;

  /* get the size from the ascii string: */
  if(ftpcode == 213) {
    /* To allow servers to prepend "rubbish" in the response string, we scan
       for all the digits at the end of the response and parse only those as a







|







|


|



|

|





|




<







2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281

2282
2283
2284
2285
2286
2287
2288
      /* no data to transfer */
      Curl_setup_transfer(data, -1, -1, FALSE, -1);
      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(data, 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);

    result = Curl_pp_sendf(data, &ftpc->pp, "REST %" CURL_FORMAT_CURL_OFF_T,
                           data->state.resume_from);
    if(!result)
      state(data, FTP_RETR_REST);
  }
  else {
    /* no resume */
    result = Curl_pp_sendf(data, &ftpc->pp, "RETR %s", ftpc->file);
    if(!result)
      state(data, FTP_RETR);
  }

  return result;
}

static CURLcode ftp_state_size_resp(struct Curl_easy *data,
                                    int ftpcode,
                                    ftpstate instate)
{
  CURLcode result = CURLE_OK;

  curl_off_t filesize = -1;
  char *buf = data->state.buffer;

  /* get the size from the ascii string: */
  if(ftpcode == 213) {
    /* To allow servers to prepend "rubbish" in the response string, we scan
       for all the digits at the end of the response and parse only those as a
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315

2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
2370
2371
2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
2384
2385
2386
2387
2388
2389
2390
2391
2392
2393
2394
2395

2396
2397
2398
2399
2400
2401
2402

  if(instate == FTP_SIZE) {
#ifdef CURL_FTP_HTTPSTYLE_HEAD
    if(-1 != filesize) {
      char clbuf[128];
      msnprintf(clbuf, sizeof(clbuf),
                "Content-Length: %" CURL_FORMAT_CURL_OFF_T "\r\n", filesize);
      result = Curl_client_write(conn, CLIENTWRITE_BOTH, clbuf, 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 {
      result = Curl_pp_sendf(&ftpc->pp, "RETR %s", ftpc->file);
      if(!result)
        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 Curl_easy *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;
  }
  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 Curl_easy *data = conn->data;
  struct FTP *ftp = data->req.p.ftp;


  if((ftpcode == 150) || (ftpcode == 125)) {

    /*
      A;
      150 Opening BINARY mode data connection for /etc/passwd (2241
      bytes).  (ok, the file is being transferred)







|





|



|



|





|
>












|




|




|



|

|







|



|



|










|

|











|



|
|
|


<

>







2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
2370
2371
2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
2384
2385
2386
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415

2416
2417
2418
2419
2420
2421
2422
2423
2424

  if(instate == FTP_SIZE) {
#ifdef CURL_FTP_HTTPSTYLE_HEAD
    if(-1 != filesize) {
      char clbuf[128];
      msnprintf(clbuf, sizeof(clbuf),
                "Content-Length: %" CURL_FORMAT_CURL_OFF_T "\r\n", filesize);
      result = Curl_client_write(data, CLIENTWRITE_BOTH, clbuf, 0);
      if(result)
        return result;
    }
#endif
    Curl_pgrsSetDownloadSize(data, filesize);
    result = ftp_state_rest(data, data->conn);
  }
  else if(instate == FTP_RETR_SIZE) {
    Curl_pgrsSetDownloadSize(data, filesize);
    result = ftp_state_retr(data, filesize);
  }
  else if(instate == FTP_STOR_SIZE) {
    data->state.resume_from = filesize;
    result = ftp_state_ul_setup(data, TRUE);
  }

  return result;
}

static CURLcode ftp_state_rest_resp(struct Curl_easy *data,
                                    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(data, CLIENTWRITE_BOTH, buffer, 0);
      if(result)
        return result;
    }
#endif
    result = ftp_state_prepare_transfer(data);
    break;

  case FTP_RETR_REST:
    if(ftpcode != 350) {
      failf(data, "Couldn't use REST");
      result = CURLE_FTP_COULDNT_USE_REST;
    }
    else {
      result = Curl_pp_sendf(data, &ftpc->pp, "RETR %s", ftpc->file);
      if(!result)
        state(data, FTP_RETR);
    }
    break;
  }

  return result;
}

static CURLcode ftp_state_stor_resp(struct Curl_easy *data,
                                    int ftpcode, ftpstate instate)
{
  CURLcode result = CURLE_OK;
  struct connectdata *conn = data->conn;

  if(ftpcode >= 400) {
    failf(data, "Failed FTP upload: %0d", ftpcode);
    state(data, 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(data, FTP_STOP); /* no longer in STOR state */

    result = AllowServerConnect(data, &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;
  }
  return InitiateTransfer(data);
}

/* for LIST and RETR responses */
static CURLcode ftp_state_get_resp(struct Curl_easy *data,
                                   int ftpcode,
                                   ftpstate instate)
{
  CURLcode result = CURLE_OK;

  struct FTP *ftp = data->req.p.ftp;
  struct connectdata *conn = data->conn;

  if((ftpcode == 150) || (ftpcode == 125)) {

    /*
      A;
      150 Opening BINARY mode data connection for /etc/passwd (2241
      bytes).  (ok, the file is being transferred)
2478
2479
2480
2481
2482
2483
2484
2485
2486
2487
2488
2489
2490
2491
2492
2493
2494
2495
2496
2497
2498
2499
2500
2501
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519

2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
2539
2540
2541
2542
2543
2544
2545
2546
2547
2548
2549
2550
2551
2552
2553
2554
2555
2556
2557
2558
2559

2560
2561
2562
2563
2564
2565
2566
2567
2568
2569
2570
2571
2572
2573
2574
2575
2576
2577
2578
2579
2580
2581
2582
2583
2584
2585
2586
2587
2588
2589
2590
2591
2592
2593
2594
2595
2596
2597
2598
2599
2600
2601
2602
2603
2604
2605
2606
2607
2608
2609
2610
2611
2612
2613
2614
2615
2616
2617
2618
2619
2620
2621
2622
2623

2624
2625
2626
2627
2628
2629
2630
2631
2632
2633
2634
2635
2636
2637
2638
2639
2640
2641
2642
2643
2644
2645
2646
2647
2648
2649
2650
2651
2652
2653
2654
2655
2656
2657
2658
2659
2660
2661
2662
2663
2664
2665
2666
2667
2668
2669
2670
2671
2672
    /* 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->bits.ftp_use_control_ssl) {
    /* 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.
    */
    result = Curl_pp_sendf(&conn->proto.ftpc.pp, "PBSZ %d", 0);
    if(!result)
      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 Curl_easy *data = conn->data;
  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) */

    result = Curl_pp_sendf(&ftpc->pp, "PASS %s", conn->passwd?conn->passwd:"");
    if(!result)
      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]) {
      result = Curl_pp_sendf(&ftpc->pp, "ACCT %s",
                             data->set.str[STRING_FTP_ACCOUNT]);
      if(!result)
        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. */
      result =
        Curl_pp_sendf(&ftpc->pp, "%s",
                      conn->data->set.str[STRING_FTP_ALTERNATIVE_TO_USER]);
      if(!result) {
        conn->data->state.ftp_trying_alternative = TRUE;
        state(conn, FTP_USER);
      }
    }
    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 Curl_easy *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 Curl_easy *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_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->bits.ftp_use_control_ssl) {







|






|




|





|













|


>
















|

|


|





|




|







>
|

|




|



|


|












|
|


|
|

|
|











|



<





|





|
>



<







|

|









|

















|







2500
2501
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
2539
2540
2541
2542
2543
2544
2545
2546
2547
2548
2549
2550
2551
2552
2553
2554
2555
2556
2557
2558
2559
2560
2561
2562
2563
2564
2565
2566
2567
2568
2569
2570
2571
2572
2573
2574
2575
2576
2577
2578
2579
2580
2581
2582
2583
2584
2585
2586
2587
2588
2589
2590
2591
2592
2593
2594
2595
2596
2597
2598
2599
2600
2601
2602
2603
2604
2605
2606
2607
2608
2609
2610
2611
2612
2613
2614
2615
2616
2617
2618
2619
2620
2621
2622
2623
2624
2625
2626
2627
2628
2629
2630
2631
2632
2633
2634

2635
2636
2637
2638
2639
2640
2641
2642
2643
2644
2645
2646
2647
2648
2649
2650

2651
2652
2653
2654
2655
2656
2657
2658
2659
2660
2661
2662
2663
2664
2665
2666
2667
2668
2669
2670
2671
2672
2673
2674
2675
2676
2677
2678
2679
2680
2681
2682
2683
2684
2685
2686
2687
2688
2689
2690
2691
2692
2693
2694
2695
    /* 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(data, &connected);
      if(result)
        return result;

      if(!connected) {
        struct ftp_conn *ftpc = &conn->proto.ftpc;
        infof(data, "Data conn was not available immediately\n");
        state(data, FTP_STOP);
        ftpc->wait_data_conn = TRUE;
      }
    }
    else
      return InitiateTransfer(data);
  }
  else {
    if((instate == FTP_LIST) && (ftpcode == 450)) {
      /* simply no matching files in the dir listing */
      ftp->transfer = FTPTRANSFER_NONE; /* don't download anything */
      state(data, 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 Curl_easy *data)
{
  CURLcode result = CURLE_OK;
  struct connectdata *conn = data->conn;

  if(conn->bits.ftp_use_control_ssl) {
    /* 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.
    */
    result = Curl_pp_sendf(data, &conn->proto.ftpc.pp, "PBSZ %d", 0);
    if(!result)
      state(data, FTP_PBSZ);
  }
  else {
    result = ftp_state_pwd(data, conn);
  }
  return result;
}

/* for USER and PASS responses */
static CURLcode ftp_state_user_resp(struct Curl_easy *data,
                                    int ftpcode,
                                    ftpstate instate)
{
  CURLcode result = CURLE_OK;
  struct connectdata *conn = data->conn;
  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) */
    result = Curl_pp_sendf(data, &ftpc->pp, "PASS %s",
                           conn->passwd?conn->passwd:"");
    if(!result)
      state(data, FTP_PASS);
  }
  else if(ftpcode/100 == 2) {
    /* 230 User ... logged in.
       (the user logged in with or without password) */
    result = ftp_state_loggedin(data);
  }
  else if(ftpcode == 332) {
    if(data->set.str[STRING_FTP_ACCOUNT]) {
      result = Curl_pp_sendf(data, &ftpc->pp, "ACCT %s",
                             data->set.str[STRING_FTP_ACCOUNT]);
      if(!result)
        state(data, 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(data->set.str[STRING_FTP_ALTERNATIVE_TO_USER] &&
        !data->state.ftp_trying_alternative) {
      /* Ok, USER failed.  Let's try the supplied command. */
      result =
        Curl_pp_sendf(data, &ftpc->pp, "%s",
                      data->set.str[STRING_FTP_ALTERNATIVE_TO_USER]);
      if(!result) {
        data->state.ftp_trying_alternative = TRUE;
        state(data, FTP_USER);
      }
    }
    else {
      failf(data, "Access denied: %03d", ftpcode);
      result = CURLE_LOGIN_DENIED;
    }
  }
  return result;
}

/* for ACCT response */
static CURLcode ftp_state_acct_resp(struct Curl_easy *data,
                                    int ftpcode)
{
  CURLcode result = CURLE_OK;

  if(ftpcode != 230) {
    failf(data, "ACCT rejected by server: %03d", ftpcode);
    result = CURLE_FTP_WEIRD_PASS_REPLY; /* FIX */
  }
  else
    result = ftp_state_loggedin(data);

  return result;
}


static CURLcode ftp_statemachine(struct Curl_easy *data,
                                 struct connectdata *conn)
{
  CURLcode result;
  curl_socket_t sock = conn->sock[FIRSTSOCKET];

  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(data, pp);

  result = ftp_readresp(data, 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(data, ftpcode, ftpc->state);
      else if(ftpcode != 220) {
        failf(data, "Got a %03d ftp-server response when 220 was expected",
              ftpcode);
        return CURLE_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(data, conn))
          infof(data, "Logging in with password in cleartext!\n");
        else
          infof(data, "Authentication successful\n");
      }
#endif

      if(data->set.use_ssl && !conn->bits.ftp_use_control_ssl) {
2685
2686
2687
2688
2689
2690
2691

2692
2693
2694
2695
2696
2697
2698
2699
2700
2701
2702
2703
2704
2705
2706
2707
2708
2709
2710
2711
2712
2713
2714
2715
2716
2717
2718
2719
2720
2721

2722
2723
2724
2725
2726
2727
2728
2729
2730
2731
2732
2733
2734
2735
2736
2737
2738
2739
2740
2741
2742
2743
2744
2745
2746
2747
2748
2749
2750
2751
2752
2753
2754
2755
2756
2757
2758
2759
2760
2761
2762
2763
2764
2765
2766
2767
2768
2769
2770
2771
2772
2773
2774
2775
2776
2777
2778
2779
2780
2781
2782
2783
2784
2785
2786
2787
2788
2789
2790
2791
          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 */
        }

        result = Curl_pp_sendf(&ftpc->pp, "AUTH %s", ftpauth[ftpc->count1]);
        if(!result)
          state(conn, FTP_AUTH);
      }
      else
        result = ftp_state_user(conn);
      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->bits.ftp_use_data_ssl = FALSE; /* clear-text data */
          conn->bits.ftp_use_control_ssl = TRUE; /* SSL on control */
          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);
      }
      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:
      result =
        Curl_pp_sendf(&ftpc->pp, "PROT %c",
                      data->set.use_ssl == CURLUSESSL_CONTROL ? 'C' : 'P');
      if(!result)
        state(conn, FTP_PROT);
      break;

    case FTP_PROT:
      if(ftpcode/100 == 2)
        /* We have enabled SSL for the data connection! */
        conn->bits.ftp_use_data_ssl =
          (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
         */
        result = Curl_pp_sendf(&ftpc->pp, "%s", "CCC");
        if(!result)
          state(conn, FTP_CCC);
      }
      else
        result = ftp_state_pwd(conn);
      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)");
      }
      if(!result)
        /* Then continue as normal */
        result = ftp_state_pwd(conn);
      break;

    case FTP_PWD:
      if(ftpcode == 257) {
        char *ptr = &data->state.buffer[4];  /* start on the first letter */
        const size_t buf_size = data->set.buffer_size;
        char *dir;







>
|

|


|














|



|





>
|








|





|



|




|


|
















|

|


|





|


|



|







2708
2709
2710
2711
2712
2713
2714
2715
2716
2717
2718
2719
2720
2721
2722
2723
2724
2725
2726
2727
2728
2729
2730
2731
2732
2733
2734
2735
2736
2737
2738
2739
2740
2741
2742
2743
2744
2745
2746
2747
2748
2749
2750
2751
2752
2753
2754
2755
2756
2757
2758
2759
2760
2761
2762
2763
2764
2765
2766
2767
2768
2769
2770
2771
2772
2773
2774
2775
2776
2777
2778
2779
2780
2781
2782
2783
2784
2785
2786
2787
2788
2789
2790
2791
2792
2793
2794
2795
2796
2797
2798
2799
2800
2801
2802
2803
2804
2805
2806
2807
2808
2809
2810
2811
2812
2813
2814
2815
2816
          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 */
        }
        result = Curl_pp_sendf(data, &ftpc->pp, "AUTH %s",
                               ftpauth[ftpc->count1]);
        if(!result)
          state(data, FTP_AUTH);
      }
      else
        result = ftp_state_user(data, conn);
      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(data, conn, FIRSTSOCKET);
        if(!result) {
          conn->bits.ftp_use_data_ssl = FALSE; /* clear-text data */
          conn->bits.ftp_use_control_ssl = TRUE; /* SSL on control */
          result = ftp_state_user(data, conn);
        }
      }
      else if(ftpc->count3 < 1) {
        ftpc->count3++;
        ftpc->count1 += ftpc->count2; /* get next attempt */
        result = Curl_pp_sendf(data, &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(data, conn);
      }
      break;

    case FTP_USER:
    case FTP_PASS:
      result = ftp_state_user_resp(data, ftpcode, ftpc->state);
      break;

    case FTP_ACCT:
      result = ftp_state_acct_resp(data, ftpcode);
      break;

    case FTP_PBSZ:
      result =
        Curl_pp_sendf(data, &ftpc->pp, "PROT %c",
                      data->set.use_ssl == CURLUSESSL_CONTROL ? 'C' : 'P');
      if(!result)
        state(data, FTP_PROT);
      break;

    case FTP_PROT:
      if(ftpcode/100 == 2)
        /* We have enabled SSL for the data connection! */
        conn->bits.ftp_use_data_ssl =
          (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
         */
        result = Curl_pp_sendf(data, &ftpc->pp, "%s", "CCC");
        if(!result)
          state(data, FTP_CCC);
      }
      else
        result = ftp_state_pwd(data, conn);
      break;

    case FTP_CCC:
      if(ftpcode < 500) {
        /* First shut down the SSL layer (note: this call will block) */
        result = Curl_ssl_shutdown(data, conn, FIRSTSOCKET);

        if(result)
          failf(data, "Failed to clear the command channel (CCC)");
      }
      if(!result)
        /* Then continue as normal */
        result = ftp_state_pwd(data, conn);
      break;

    case FTP_PWD:
      if(ftpcode == 257) {
        char *ptr = &data->state.buffer[4];  /* start on the first letter */
        const size_t buf_size = data->set.buffer_size;
        char *dir;
2843
2844
2845
2846
2847
2848
2849
2850
2851
2852
2853
2854
2855
2856
2857
2858
2859
2860
2861
2862
2863
2864
2865
2866
2867
2868
2869
2870
2871
2872
2873
2874
2875
2876
2877
2878
2879
2880
2881
2882
2883
             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;







|









|















|







2868
2869
2870
2871
2872
2873
2874
2875
2876
2877
2878
2879
2880
2881
2882
2883
2884
2885
2886
2887
2888
2889
2890
2891
2892
2893
2894
2895
2896
2897
2898
2899
2900
2901
2902
2903
2904
2905
2906
2907
2908
             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(data, &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(data, 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(data, 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;
2896
2897
2898
2899
2900
2901
2902
2903
2904
2905
2906
2907
2908
2909
2910
2911
2912
2913
2914
2915
2916
2917
2918
2919
2920
2921
2922
2923
2924
2925
2926
2927
2928
2929
2930
2931
2932
2933
2934
2935
2936
2937
2938
2939
2940
2941
2942
2943
2944
2945
2946
2947
2948
2949
2950
2951
2952
2953
2954
2955
2956
2957
2958
2959
2960
2961
2962
2963
2964
2965
2966
2967
2968
2969
2970
2971
2972
2973
2974
2975
2976
2977
2978
2979
2980
2981
2982
2983
2984
2985
2986
2987
2988
2989
2990
2991
2992
2993
2994
2995
2996
2997
2998
2999
3000
3001
3002
3003
3004
3005
3006
3007
3008
3009
3010
3011
3012
3013
3014
3015
3016
3017
3018
3019
3020
3021
3022
3023
3024
3025
3026
3027
3028
3029
3030
3031
3032
3033
3034
3035
3036
3037
3038
3039
3040
3041
3042
3043
3044
3045
3046
3047
3048
3049
3050
3051
3052
3053
3054
3055
3056
3057
3058
3059
3060
3061

3062
3063
3064
3065
3066
3067
3068
3069
3070
3071
3072
3073

3074
3075
3076
3077
3078
3079
3080
3081
3082
3083
3084
3085
3086
3087
3088
3089
3090
3091
3092
3093
3094
3095
3096
3097
3098
3099

3100
3101
3102
3103
3104
3105
3106
3107
3108
3109
3110
3111
3112
3113
3114
3115
3116
3117
3118
3119
3120
3121
3122
3123
3124
3125
3126
3127
3128
3129
3130
3131
3132
3133
3134
3135
3136
3137
3138
3139
3140
3141
3142
3143
3144
3145
3146
3147
3148
3149
3150
3151
3152
          *store++ = *ptr++;
        *store = '\0'; /* null-terminate */

        /* Check for special servers here. */

        if(strcasecompare(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;
        }
        /* 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);
        result = CURLE_QUOTE_ERROR;
      }
      else
        result = ftp_state_quote(conn, FALSE, ftpc->state);
      break;

    case FTP_CWD:
      if(ftpcode/100 != 2) {
        /* failure to CWD there */
        if(conn->data->set.ftp_create_missing_dirs &&
           ftpc->cwdcount && !ftpc->count2) {
          /* try making it */
          ftpc->count2++; /* counter to prevent CWD-MKD loops */
          result = Curl_pp_sendf(&ftpc->pp, "MKD %s",
                                 ftpc->dirs[ftpc->cwdcount - 1]);
          if(!result)
            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 */
          result = CURLE_REMOTE_ACCESS_DENIED;
        }
      }
      else {
        /* success */
        ftpc->count2 = 0;
        if(++ftpc->cwdcount <= ftpc->dirdepth)
          /* send next CWD */
          result = Curl_pp_sendf(&ftpc->pp, "CWD %s",
                                 ftpc->dirs[ftpc->cwdcount - 1]);
        else
          result = ftp_state_mdtm(conn);
      }
      break;

    case FTP_MKD:
      if((ftpcode/100 != 2) && !ftpc->count3--) {
        /* failure to MKD the dir */
        failf(data, "Failed to MKD dir: %03d", ftpcode);
        result = CURLE_REMOTE_ACCESS_DENIED;
      }
      else {
        state(conn, FTP_CWD);
        /* send CWD */
        result = Curl_pp_sendf(&ftpc->pp, "CWD %s",
                               ftpc->dirs[ftpc->cwdcount - 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, FALSE);

  /* Check for the state outside of the Curl_socket_check() 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, TRUE /* disconnecting */);
    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;
    conn->bits.ftp_use_control_ssl = TRUE;
  }

  Curl_pp_setup(pp); /* once per transfer */
  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 Curl_easy *data = conn->data;
  struct FTP *ftp = data->req.p.ftp;
  struct ftp_conn *ftpc = &conn->proto.ftpc;
  struct pingpong *pp = &ftpc->pp;
  ssize_t nread;
  int ftpcode;
  CURLcode result = CURLE_OK;
  char *rawPath = NULL;







|







|











|






|



|









|



|





|



|


|














|


|










|

|





|






|





|




|








|



|



|




|



|






|









|


>

|









|
>






|















|



>








<
|
<
<



|






|



|

|













|


|







2921
2922
2923
2924
2925
2926
2927
2928
2929
2930
2931
2932
2933
2934
2935
2936
2937
2938
2939
2940
2941
2942
2943
2944
2945
2946
2947
2948
2949
2950
2951
2952
2953
2954
2955
2956
2957
2958
2959
2960
2961
2962
2963
2964
2965
2966
2967
2968
2969
2970
2971
2972
2973
2974
2975
2976
2977
2978
2979
2980
2981
2982
2983
2984
2985
2986
2987
2988
2989
2990
2991
2992
2993
2994
2995
2996
2997
2998
2999
3000
3001
3002
3003
3004
3005
3006
3007
3008
3009
3010
3011
3012
3013
3014
3015
3016
3017
3018
3019
3020
3021
3022
3023
3024
3025
3026
3027
3028
3029
3030
3031
3032
3033
3034
3035
3036
3037
3038
3039
3040
3041
3042
3043
3044
3045
3046
3047
3048
3049
3050
3051
3052
3053
3054
3055
3056
3057
3058
3059
3060
3061
3062
3063
3064
3065
3066
3067
3068
3069
3070
3071
3072
3073
3074
3075
3076
3077
3078
3079
3080
3081
3082
3083
3084
3085
3086
3087
3088
3089
3090
3091
3092
3093
3094
3095
3096
3097
3098
3099
3100
3101
3102
3103
3104
3105
3106
3107
3108
3109
3110
3111
3112
3113
3114
3115
3116
3117
3118
3119
3120
3121
3122
3123
3124
3125
3126
3127
3128
3129
3130
3131
3132
3133
3134
3135

3136


3137
3138
3139
3140
3141
3142
3143
3144
3145
3146
3147
3148
3149
3150
3151
3152
3153
3154
3155
3156
3157
3158
3159
3160
3161
3162
3163
3164
3165
3166
3167
3168
3169
3170
3171
3172
3173
3174
3175
3176
3177
          *store++ = *ptr++;
        *store = '\0'; /* null-terminate */

        /* Check for special servers here. */

        if(strcasecompare(os, "OS/400")) {
          /* Force OS400 name format 1. */
          result = Curl_pp_sendf(data, &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(data, FTP_NAMEFMT);
          break;
        }
        /* 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(data, 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(data, conn);
        break;
      }

      state(data, 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(data, "QUOT command failed with %03d", ftpcode);
        result = CURLE_QUOTE_ERROR;
      }
      else
        result = ftp_state_quote(data, FALSE, ftpc->state);
      break;

    case FTP_CWD:
      if(ftpcode/100 != 2) {
        /* failure to CWD there */
        if(data->set.ftp_create_missing_dirs &&
           ftpc->cwdcount && !ftpc->count2) {
          /* try making it */
          ftpc->count2++; /* counter to prevent CWD-MKD loops */
          result = Curl_pp_sendf(data, &ftpc->pp, "MKD %s",
                                 ftpc->dirs[ftpc->cwdcount - 1]);
          if(!result)
            state(data, 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 */
          result = CURLE_REMOTE_ACCESS_DENIED;
        }
      }
      else {
        /* success */
        ftpc->count2 = 0;
        if(++ftpc->cwdcount <= ftpc->dirdepth)
          /* send next CWD */
          result = Curl_pp_sendf(data, &ftpc->pp, "CWD %s",
                                 ftpc->dirs[ftpc->cwdcount - 1]);
        else
          result = ftp_state_mdtm(data);
      }
      break;

    case FTP_MKD:
      if((ftpcode/100 != 2) && !ftpc->count3--) {
        /* failure to MKD the dir */
        failf(data, "Failed to MKD dir: %03d", ftpcode);
        result = CURLE_REMOTE_ACCESS_DENIED;
      }
      else {
        state(data, FTP_CWD);
        /* send CWD */
        result = Curl_pp_sendf(data, &ftpc->pp, "CWD %s",
                               ftpc->dirs[ftpc->cwdcount - 1]);
      }
      break;

    case FTP_MDTM:
      result = ftp_state_mdtm_resp(data, ftpcode);
      break;

    case FTP_TYPE:
    case FTP_LIST_TYPE:
    case FTP_RETR_TYPE:
    case FTP_STOR_TYPE:
      result = ftp_state_type_resp(data, ftpcode, ftpc->state);
      break;

    case FTP_SIZE:
    case FTP_RETR_SIZE:
    case FTP_STOR_SIZE:
      result = ftp_state_size_resp(data, ftpcode, ftpc->state);
      break;

    case FTP_REST:
    case FTP_RETR_REST:
      result = ftp_state_rest_resp(data, 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(data, conn);
      break;

    case FTP_PASV:
      result = ftp_state_pasv_resp(data, ftpcode);
      break;

    case FTP_PORT:
      result = ftp_state_port_resp(data, ftpcode);
      break;

    case FTP_LIST:
    case FTP_RETR:
      result = ftp_state_get_resp(data, ftpcode, ftpc->state);
      break;

    case FTP_STOR:
      result = ftp_state_stor_resp(data, ftpcode, ftpc->state);
      break;

    case FTP_QUIT:
      /* fallthrough, just stop! */
    default:
      /* internal error */
      state(data, FTP_STOP);
      break;
    }
  } /* if(ftpcode) */

  return result;
}


/* called repeatedly until done from multi.c */
static CURLcode ftp_multi_statemach(struct Curl_easy *data,
                                    bool *done)
{
  struct connectdata *conn = data->conn;
  struct ftp_conn *ftpc = &conn->proto.ftpc;
  CURLcode result = Curl_pp_statemach(data, &ftpc->pp, FALSE, FALSE);

  /* Check for the state outside of the Curl_socket_check() 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 Curl_easy *data,
                                    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(data, pp, TRUE, TRUE /* disconnecting */);
    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 Curl_easy *data,
                            bool *done) /* see description above */
{
  CURLcode result;
  struct connectdata *conn = data->conn;
  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");


  PINGPONG_SETUP(pp, ftp_statemachine, ftp_endofresp);



  if(conn->handler->flags & PROTOPT_SSL) {
    /* BLOCKING */
    result = Curl_ssl_connect(data, conn, FIRSTSOCKET);
    if(result)
      return result;
    conn->bits.ftp_use_control_ssl = TRUE;
  }

  Curl_pp_setup(pp); /* once per transfer */
  Curl_pp_init(data, pp); /* init the generic pingpong data */

  /* When we connect, we start in the state where we await the 220
     response */
  state(data, FTP_WAIT220);

  result = ftp_multi_statemach(data, 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 Curl_easy *data, CURLcode status,
                         bool premature)
{
  struct connectdata *conn = data->conn;
  struct FTP *ftp = data->req.p.ftp;
  struct ftp_conn *ftpc = &conn->proto.ftpc;
  struct pingpong *pp = &ftpc->pp;
  ssize_t nread;
  int ftpcode;
  CURLcode result = CURLE_OK;
  char *rawPath = NULL;
3242
3243
3244
3245
3246
3247
3248
3249
3250
3251
3252
3253
3254
3255
3256
3257
3258
3259
3260
3261
3262
3263
3264
3265
3266
3267
3268
3269
3270
3271
3272
3273
3274
3275
3276
3277
3278
3279
3280
3281
3282
3283
3284
3285
3286
3287
3288
3289
#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 */
    }
    close_secondarysocket(conn);
  }

  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.
     */
    timediff_t old_time = pp->response_time;

    pp->response_time = 60*1000; /* give it only a minute for now */
    pp->response = Curl_now(); /* 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 */







|











|




|















|







3267
3268
3269
3270
3271
3272
3273
3274
3275
3276
3277
3278
3279
3280
3281
3282
3283
3284
3285
3286
3287
3288
3289
3290
3291
3292
3293
3294
3295
3296
3297
3298
3299
3300
3301
3302
3303
3304
3305
3306
3307
3308
3309
3310
3311
3312
3313
3314
#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(data, 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(data, conn, SECONDARYSOCKET);

      /* Note that we keep "use" set to TRUE since that (next) connection is
         still requested to use SSL */
    }
    close_secondarysocket(data, conn);
  }

  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.
     */
    timediff_t old_time = pp->response_time;

    pp->response_time = 60*1000; /* give it only a minute for now */
    pp->response = Curl_now(); /* timeout relative now */

    result = Curl_GetFTPResponse(data, &nread, &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 */
3359
3360
3361
3362
3363
3364
3365
3366
3367
3368
3369
3370
3371
3372
3373
3374
3375
3376
3377
3378
3379
3380
3381

3382
3383
3384
3385
3386
3387
3388
3389

  /* 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);
  Curl_safefree(ftp->pathalloc);
  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;
  struct ftp_conn *ftpc = &conn->proto.ftpc;
  struct pingpong *pp = &ftpc->pp;

  item = quote;
  while(item) {







|















>
|







3384
3385
3386
3387
3388
3389
3390
3391
3392
3393
3394
3395
3396
3397
3398
3399
3400
3401
3402
3403
3404
3405
3406
3407
3408
3409
3410
3411
3412
3413
3414
3415

  /* 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(data, conn, data->set.postquote);
  Curl_safefree(ftp->pathalloc);
  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 Curl_easy *data,
                       struct connectdata *conn, struct curl_slist *quote)
{
  struct curl_slist *item;
  struct ftp_conn *ftpc = &conn->proto.ftpc;
  struct pingpong *pp = &ftpc->pp;

  item = quote;
  while(item) {
3400
3401
3402
3403
3404
3405
3406
3407
3408
3409
3410
3411
3412
3413
3414
3415
3416
3417
3418
3419
3420
3421
3422
3423
         is successful, whatever the server reponds. */

      if(cmd[0] == '*') {
        cmd++;
        acceptfail = TRUE;
      }

      result = Curl_pp_sendf(&ftpc->pp, "%s", cmd);
      if(!result) {
        pp->response = Curl_now(); /* 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;
  }








|


|





|







3426
3427
3428
3429
3430
3431
3432
3433
3434
3435
3436
3437
3438
3439
3440
3441
3442
3443
3444
3445
3446
3447
3448
3449
         is successful, whatever the server reponds. */

      if(cmd[0] == '*') {
        cmd++;
        acceptfail = TRUE;
      }

      result = Curl_pp_sendf(data, &ftpc->pp, "%s", cmd);
      if(!result) {
        pp->response = Curl_now(); /* timeout relative now */
        result = Curl_GetFTPResponse(data, &nread, &ftpcode);
      }
      if(result)
        return result;

      if(!acceptfail && (ftpcode >= 400)) {
        failf(data, "QUOT string not accepted: %s", cmd);
        return CURLE_QUOTE_ERROR;
      }
    }

    item = item->next;
  }

3440
3441
3442
3443
3444
3445
3446
3447

3448
3449
3450
3451
3452
3453
3454
3455
3456
3457
3458
3459
3460
3461
3462
3463
3464
3465
3466
3467
3468
3469
3470
3471
3472
3473
3474
3475
3476
3477
3478
3479
3480
3481
3482
3483
3484
3485
3486
3487
3488
3489
3490
3491
3492
3493
3494
3495
3496
3497
3498
3499
3500
3501
3502
3503
3504
3505
3506
3507
3508
3509
3510
3511
3512
3513
3514
3515
3516
3517
3518
3519
3520
3521
3522
3523
3524
3525
3526
3527
3528
3529
3530
3531
3532
3533
3534
3535
3536
3537
3538
3539
3540
3541
3542
3543
3544
3545
3546
3547
3548
3549
3550
3551
3552
3553
3554
3555
3556
3557
3558
3559
3560
3561
3562
 *
 * 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);
  }

  result = Curl_pp_sendf(&ftpc->pp, "TYPE %c", want);
  if(!result) {
    state(conn, newstate);

    /* keep track of our current transfer type */
    ftpc->transfertype = want;
  }
  return result;
}

/***************************************************************************
 *
 * 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,
                 struct 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

/*
 * 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 Curl_easy *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.p.ftp;

  /* if the second connection isn't done yet, wait for it */
  if(!conn->bits.tcpconnect[SECONDARYSOCKET]) {
    if(Curl_connect_ongoing(conn)) {
      /* As we're in TUNNEL_CONNECT state now, we know the proxy name and port
         aren't used so we blank their arguments. */
      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"));
    }
    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;
    }
  }

#ifndef CURL_DISABLE_PROXY
  result = Curl_proxy_connect(conn, SECONDARYSOCKET);
  if(result)
    return result;

  if(CONNECT_SECONDARYSOCKET_PROXY_SSL())
    return result;

  if(conn->bits.tunnel_proxy && conn->bits.httpproxy &&
     Curl_connect_ongoing(conn))
    return result;
#endif

  if(ftpc->state) {
    /* already in a state so skip the initial 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)
      return result;







|
>







|
|


|

|


















|






|














|

|













|




|









|






|














|







3466
3467
3468
3469
3470
3471
3472
3473
3474
3475
3476
3477
3478
3479
3480
3481
3482
3483
3484
3485
3486
3487
3488
3489
3490
3491
3492
3493
3494
3495
3496
3497
3498
3499
3500
3501
3502
3503
3504
3505
3506
3507
3508
3509
3510
3511
3512
3513
3514
3515
3516
3517
3518
3519
3520
3521
3522
3523
3524
3525
3526
3527
3528
3529
3530
3531
3532
3533
3534
3535
3536
3537
3538
3539
3540
3541
3542
3543
3544
3545
3546
3547
3548
3549
3550
3551
3552
3553
3554
3555
3556
3557
3558
3559
3560
3561
3562
3563
3564
3565
3566
3567
3568
3569
3570
3571
3572
3573
3574
3575
3576
3577
3578
3579
3580
3581
3582
3583
3584
3585
3586
3587
3588
3589
 *
 * 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 Curl_easy *data,
                            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(data, newstate);
    return ftp_state_type_resp(data, 200, newstate);
  }

  result = Curl_pp_sendf(data, &ftpc->pp, "TYPE %c", want);
  if(!result) {
    state(data, newstate);

    /* keep track of our current transfer type */
    ftpc->transfertype = want;
  }
  return result;
}

/***************************************************************************
 *
 * 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 Curl_easy *data,
                 struct Curl_addrinfo *ai,
                 char *newhost, /* ascii version */
                 int port)
{
  char buf[256];
  Curl_printable_address(ai, buf, sizeof(buf));
  infof(data, "Connecting to %s (%s) port %d\n", newhost, buf, port);
}
#endif

/*
 * 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 Curl_easy *data, int *completep)
{
  struct connectdata *conn = data->conn;
  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.p.ftp;

  /* if the second connection isn't done yet, wait for it */
  if(!conn->bits.tcpconnect[SECONDARYSOCKET]) {
    if(Curl_connect_ongoing(conn)) {
      /* As we're in TUNNEL_CONNECT state now, we know the proxy name and port
         aren't used so we blank their arguments. */
      result = Curl_proxyCONNECT(data, SECONDARYSOCKET, NULL, 0);

      return result;
    }

    result = Curl_is_connected(data, conn, SECONDARYSOCKET, &connected);

    /* Ready to do more? */
    if(connected) {
      DEBUGF(infof(data, "DO-MORE connected phase starts\n"));
    }
    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(data, conn);
      }
      return result;
    }
  }

#ifndef CURL_DISABLE_PROXY
  result = Curl_proxy_connect(data, SECONDARYSOCKET);
  if(result)
    return result;

  if(CONNECT_SECONDARYSOCKET_PROXY_SSL())
    return result;

  if(conn->bits.tunnel_proxy && conn->bits.httpproxy &&
     Curl_connect_ongoing(conn))
    return result;
#endif

  if(ftpc->state) {
    /* already in a state so skip the initial commands.
       They are only done to kickstart the do_more state */
    result = ftp_multi_statemach(data, &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)
      return result;
3570
3571
3572
3573
3574
3575
3576
3577
3578
3579
3580
3581
3582
3583
3584
3585
3586
3587
3588
3589
3590
3591
3592
3593
3594
3595
3596
3597
3598
3599
3600
3601
3602
3603
3604
3605
3606
3607
3608
3609
3610
3611
3612
3613
3614
3615
3616
3617
3618
3619
3620
3621
3622
3623
3624
3625
3626
3627
3628
3629
3630
3631

3632
3633
3634
3635
3636
3637
3638
3639
3640
3641
3642
3643
  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);
      /* ftpc->wait_data_conn is always false here */
      *completep = (int)complete;
    }
    else {
      /* download */
      ftp->downloadsize = -1; /* unknown as of yet */

      result = Curl_range(conn);

      if(result == CURLE_OK && data->req.maxdownload >= 0) {
        /* Don't check for successful transfer */
        ftpc->dont_check = TRUE;
      }

      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;
  }

  /* no data to transfer */
  Curl_setup_transfer(data, -1, -1, FALSE, -1);







|





|


|









|



|







|















|






|
>




|







3597
3598
3599
3600
3601
3602
3603
3604
3605
3606
3607
3608
3609
3610
3611
3612
3613
3614
3615
3616
3617
3618
3619
3620
3621
3622
3623
3624
3625
3626
3627
3628
3629
3630
3631
3632
3633
3634
3635
3636
3637
3638
3639
3640
3641
3642
3643
3644
3645
3646
3647
3648
3649
3650
3651
3652
3653
3654
3655
3656
3657
3658
3659
3660
3661
3662
3663
3664
3665
3666
3667
3668
3669
3670
3671
  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(data, &serv_conned);
      if(result)
        return result; /* Failed to accept data connection */

      if(serv_conned) {
        /* It looks data connection is established */
        result = AcceptServerConnect(data);
        ftpc->wait_data_conn = FALSE;
        if(!result)
          result = InitiateTransfer(data);

        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(data, conn, data->set.prefer_ascii, FTP_STOR_TYPE);
      if(result)
        return result;

      result = ftp_multi_statemach(data, &complete);
      /* ftpc->wait_data_conn is always false here */
      *completep = (int)complete;
    }
    else {
      /* download */
      ftp->downloadsize = -1; /* unknown as of yet */

      result = Curl_range(data);

      if(result == CURLE_OK && data->req.maxdownload >= 0) {
        /* Don't check for successful transfer */
        ftpc->dont_check = TRUE;
      }

      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(data, conn, TRUE, FTP_LIST_TYPE);
          if(result)
            return result;
        }
        /* otherwise just fall through */
      }
      else {
        result = ftp_nb_type(data, conn, data->set.prefer_ascii,
                             FTP_RETR_TYPE);
        if(result)
          return result;
      }

      result = ftp_multi_statemach(data, &complete);
      *completep = (int)complete;
    }
    return result;
  }

  /* no data to transfer */
  Curl_setup_transfer(data, -1, -1, FALSE, -1);
3658
3659
3660
3661
3662
3663
3664
3665
3666
3667
3668
3669
3670

3671
3672
3673
3674
3675
3676
3677
3678
3679
3680
3681
3682
3683
3684
3685
3686
3687
3688
3689
3690
3691
3692
3693
3694
3695
3696
3697
3698
3699
3700
3701
3702
3703
3704
3705
3706
3707
3708
3709
3710
3711
3712
3713
3714
3715
3716
3717
3718
3719
3720
3721
3722
3723
3724
3725
3726
3727
3728
3729
3730
3731
3732
3733
3734
3735
3736
3737
3738
3739
3740
3741
3742
3743
3744
3745
3746
 * 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.p.ftp;
    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 *ftpwc = ptr;
  if(ftpwc && ftpwc->parser)
    Curl_ftp_parselist_data_free(&ftpwc->parser);
  free(ftpwc);
}

static CURLcode init_wc_data(struct connectdata *conn)
{
  char *last_slash;
  struct FTP *ftp = conn->data->req.p.ftp;
  char *path = ftp->path;
  struct WildcardData *wildcard = &(conn->data->wildcard);
  CURLcode result = CURLE_OK;
  struct ftp_wc *ftpwc = NULL;

  last_slash = strrchr(ftp->path, '/');
  if(last_slash) {
    last_slash++;
    if(last_slash[0] == '\0') {
      wildcard->state = CURLWC_CLEAN;
      result = ftp_parse_url_path(conn);
      return result;
    }
    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 */








|





>

|

|

|






|




|



|


|












|


|

|








|
















|







3686
3687
3688
3689
3690
3691
3692
3693
3694
3695
3696
3697
3698
3699
3700
3701
3702
3703
3704
3705
3706
3707
3708
3709
3710
3711
3712
3713
3714
3715
3716
3717
3718
3719
3720
3721
3722
3723
3724
3725
3726
3727
3728
3729
3730
3731
3732
3733
3734
3735
3736
3737
3738
3739
3740
3741
3742
3743
3744
3745
3746
3747
3748
3749
3750
3751
3752
3753
3754
3755
3756
3757
3758
3759
3760
3761
3762
3763
3764
3765
3766
3767
3768
3769
3770
3771
3772
3773
3774
3775
 * 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 Curl_easy *data,
                     bool *connected,  /* connect status after PASV / PORT */
                     bool *dophase_done)
{
  /* this is FTP and no proxy */
  CURLcode result = CURLE_OK;
  struct connectdata *conn = data->conn;

  DEBUGF(infof(data, "DO phase starts\n"));

  if(data->set.opt_no_body) {
    /* requested no body means no transfer... */
    struct FTP *ftp = data->req.p.ftp;
    ftp->transfer = FTPTRANSFER_INFO;
  }

  *dophase_done = FALSE; /* not done yet */

  /* start the first command in the DO phase */
  result = ftp_state_quote(data, TRUE, FTP_QUOTE);
  if(result)
    return result;

  /* run the state-machine */
  result = ftp_multi_statemach(data, dophase_done);

  *connected = conn->bits.tcpconnect[SECONDARYSOCKET];

  infof(data, "ftp_perform ends with SECONDARY: %d\n", *connected);

  if(*dophase_done)
    DEBUGF(infof(data, "DO phase is complete1\n"));

  return result;
}

static void wc_data_dtor(void *ptr)
{
  struct ftp_wc *ftpwc = ptr;
  if(ftpwc && ftpwc->parser)
    Curl_ftp_parselist_data_free(&ftpwc->parser);
  free(ftpwc);
}

static CURLcode init_wc_data(struct Curl_easy *data)
{
  char *last_slash;
  struct FTP *ftp = data->req.p.ftp;
  char *path = ftp->path;
  struct WildcardData *wildcard = &(data->wildcard);
  CURLcode result = CURLE_OK;
  struct ftp_wc *ftpwc = NULL;

  last_slash = strrchr(ftp->path, '/');
  if(last_slash) {
    last_slash++;
    if(last_slash[0] == '\0') {
      wildcard->state = CURLWC_CLEAN;
      result = ftp_parse_url_path(data);
      return result;
    }
    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(data);
      return result;
    }
  }

  /* program continues only if URL is not ending with slash, allocate needed
     resources for wildcard transfer */

3758
3759
3760
3761
3762
3763
3764
3765
3766
3767
3768
3769
3770
3771
3772
3773
3774
3775
3776
3777
3778
3779
3780
3781
3782
3783
3784
3785
3786
3787
3788
3789
3790
3791
3792
3793
3794
3795
3796
3797
3798
3799
3800
3801
3802
3803
3804
3805

3806
3807
3808
3809
3810
3811
3812
3813
3814
3815
3816
3817
3818
3819
3820
3821
3822
3823
3824
3825
3826
3827
3828
3829
3830
    goto fail;
  }

  wildcard->protdata = ftpwc; /* put it to the WildcardData tmp pointer */
  wildcard->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) {
    goto fail;
  }

  wildcard->path = strdup(ftp->path);
  if(!wildcard->path) {
    result = CURLE_OUT_OF_MEMORY;
    goto fail;
  }

  /* backup old write_function */
  ftpwc->backup.write_function = conn->data->set.fwrite_func;
  /* parsing write function */
  conn->data->set.fwrite_func = Curl_ftp_parselist;
  /* backup old file descriptor */
  ftpwc->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;

  fail:
  if(ftpwc) {
    Curl_ftp_parselist_data_free(&ftpwc->parser);
    free(ftpwc);
  }
  Curl_safefree(wildcard->pattern);
  wildcard->dtor = ZERO_NULL;
  wildcard->protdata = NULL;
  return result;
}

static CURLcode wc_statemach(struct connectdata *conn)
{
  struct WildcardData * const wildcard = &(conn->data->wildcard);

  CURLcode result = CURLE_OK;

  for(;;) {
    switch(wildcard->state) {
    case CURLWC_INIT:
      result = init_wc_data(conn);
      if(wildcard->state == CURLWC_CLEAN)
        /* only listing! */
        return result;
      wildcard->state = result ? CURLWC_ERROR : CURLWC_MATCHING;
      return result;

    case CURLWC_MATCHING: {
      /* In this state is LIST response successfully parsed, so lets restore
         previous WRITEFUNCTION callback and WRITEDATA pointer */
      struct ftp_wc *ftpwc = wildcard->protdata;
      conn->data->set.fwrite_func = ftpwc->backup.write_function;
      conn->data->set.out = ftpwc->backup.file_descriptor;
      ftpwc->backup.write_function = ZERO_NULL;
      ftpwc->backup.file_descriptor = NULL;
      wildcard->state = CURLWC_DOWNLOADING;

      if(Curl_ftp_parselist_geterror(ftpwc->parser)) {
        /* error found in LIST parsing */
        wildcard->state = CURLWC_CLEAN;







|
|


|











|

|

|
|
|

|













|

|
>





|










|
|







3787
3788
3789
3790
3791
3792
3793
3794
3795
3796
3797
3798
3799
3800
3801
3802
3803
3804
3805
3806
3807
3808
3809
3810
3811
3812
3813
3814
3815
3816
3817
3818
3819
3820
3821
3822
3823
3824
3825
3826
3827
3828
3829
3830
3831
3832
3833
3834
3835
3836
3837
3838
3839
3840
3841
3842
3843
3844
3845
3846
3847
3848
3849
3850
3851
3852
3853
3854
3855
3856
3857
3858
3859
3860
    goto fail;
  }

  wildcard->protdata = ftpwc; /* put it to the WildcardData tmp pointer */
  wildcard->dtor = wc_data_dtor;

  /* wildcard does not support NOCWD option (assert it?) */
  if(data->set.ftp_filemethod == FTPFILE_NOCWD)
    data->set.ftp_filemethod = FTPFILE_MULTICWD;

  /* try to parse ftp url */
  result = ftp_parse_url_path(data);
  if(result) {
    goto fail;
  }

  wildcard->path = strdup(ftp->path);
  if(!wildcard->path) {
    result = CURLE_OUT_OF_MEMORY;
    goto fail;
  }

  /* backup old write_function */
  ftpwc->backup.write_function = data->set.fwrite_func;
  /* parsing write function */
  data->set.fwrite_func = Curl_ftp_parselist;
  /* backup old file descriptor */
  ftpwc->backup.file_descriptor = data->set.out;
  /* let the writefunc callback know the transfer */
  data->set.out = data;

  infof(data, "Wildcard - Parsing started\n");
  return CURLE_OK;

  fail:
  if(ftpwc) {
    Curl_ftp_parselist_data_free(&ftpwc->parser);
    free(ftpwc);
  }
  Curl_safefree(wildcard->pattern);
  wildcard->dtor = ZERO_NULL;
  wildcard->protdata = NULL;
  return result;
}

static CURLcode wc_statemach(struct Curl_easy *data)
{
  struct WildcardData * const wildcard = &(data->wildcard);
  struct connectdata *conn = data->conn;
  CURLcode result = CURLE_OK;

  for(;;) {
    switch(wildcard->state) {
    case CURLWC_INIT:
      result = init_wc_data(data);
      if(wildcard->state == CURLWC_CLEAN)
        /* only listing! */
        return result;
      wildcard->state = result ? CURLWC_ERROR : CURLWC_MATCHING;
      return result;

    case CURLWC_MATCHING: {
      /* In this state is LIST response successfully parsed, so lets restore
         previous WRITEFUNCTION callback and WRITEDATA pointer */
      struct ftp_wc *ftpwc = wildcard->protdata;
      data->set.fwrite_func = ftpwc->backup.write_function;
      data->set.out = ftpwc->backup.file_descriptor;
      ftpwc->backup.write_function = ZERO_NULL;
      ftpwc->backup.file_descriptor = NULL;
      wildcard->state = CURLWC_DOWNLOADING;

      if(Curl_ftp_parselist_geterror(ftpwc->parser)) {
        /* error found in LIST parsing */
        wildcard->state = CURLWC_CLEAN;
3838
3839
3840
3841
3842
3843
3844
3845
3846
3847
3848
3849
3850
3851
3852
3853
3854
3855
3856
3857
3858
3859
3860
3861
3862
3863
3864
3865
3866
3867
3868
3869
3870
3871
3872
3873
3874
3875
3876
3877
3878
3879
3880
3881
3882
3883
3884
3885
3886
3887
3888
3889
3890
3891
3892
3893
3894
3895
3896
3897
3898
3899
3900
3901
3902
3903
3904
3905
3906
3907
3908
      continue;
    }

    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;
      struct FTP *ftp = conn->data->req.p.ftp;

      char *tmp_path = aprintf("%s%s", wildcard->path, finfo->filename);
      if(!tmp_path)
        return CURLE_OUT_OF_MEMORY;

      /* switch default ftp->path and tmp_path */
      free(ftp->pathalloc);
      ftp->pathalloc = ftp->path = tmp_path;

      infof(conn->data, "Wildcard - START of \"%s\"\n", finfo->filename);
      if(conn->data->set.chunk_bgn) {
        long userresponse;
        Curl_set_in_callback(conn->data, true);
        userresponse = conn->data->set.chunk_bgn(
          finfo, wildcard->customptr, (int)wildcard->filelist.size);
        Curl_set_in_callback(conn->data, false);
        switch(userresponse) {
        case CURL_CHUNK_BGN_FUNC_SKIP:
          infof(conn->data, "Wildcard - \"%s\" skipped by user\n",
                finfo->filename);
          wildcard->state = CURLWC_SKIP;
          continue;
        case CURL_CHUNK_BGN_FUNC_FAIL:
          return CURLE_CHUNK_FAILED;
        }
      }

      if(finfo->filetype != CURLFILETYPE_FILE) {
        wildcard->state = CURLWC_SKIP;
        continue;
      }

      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;
      }
      return result;
    }

    case CURLWC_SKIP: {
      if(conn->data->set.chunk_end) {
        Curl_set_in_callback(conn->data, true);
        conn->data->set.chunk_end(conn->data->wildcard.customptr);
        Curl_set_in_callback(conn->data, false);
      }
      Curl_llist_remove(&wildcard->filelist, wildcard->filelist.head, NULL);
      wildcard->state = (wildcard->filelist.size == 0) ?
        CURLWC_CLEAN : CURLWC_DOWNLOADING;
      continue;
    }








|









|
|

|
|

|


|
















|
















|
|
|
|







3868
3869
3870
3871
3872
3873
3874
3875
3876
3877
3878
3879
3880
3881
3882
3883
3884
3885
3886
3887
3888
3889
3890
3891
3892
3893
3894
3895
3896
3897
3898
3899
3900
3901
3902
3903
3904
3905
3906
3907
3908
3909
3910
3911
3912
3913
3914
3915
3916
3917
3918
3919
3920
3921
3922
3923
3924
3925
3926
3927
3928
3929
3930
3931
3932
3933
3934
3935
3936
3937
3938
      continue;
    }

    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;
      struct FTP *ftp = data->req.p.ftp;

      char *tmp_path = aprintf("%s%s", wildcard->path, finfo->filename);
      if(!tmp_path)
        return CURLE_OUT_OF_MEMORY;

      /* switch default ftp->path and tmp_path */
      free(ftp->pathalloc);
      ftp->pathalloc = ftp->path = tmp_path;

      infof(data, "Wildcard - START of \"%s\"\n", finfo->filename);
      if(data->set.chunk_bgn) {
        long userresponse;
        Curl_set_in_callback(data, true);
        userresponse = data->set.chunk_bgn(
          finfo, wildcard->customptr, (int)wildcard->filelist.size);
        Curl_set_in_callback(data, false);
        switch(userresponse) {
        case CURL_CHUNK_BGN_FUNC_SKIP:
          infof(data, "Wildcard - \"%s\" skipped by user\n",
                finfo->filename);
          wildcard->state = CURLWC_SKIP;
          continue;
        case CURL_CHUNK_BGN_FUNC_FAIL:
          return CURLE_CHUNK_FAILED;
        }
      }

      if(finfo->filetype != CURLFILETYPE_FILE) {
        wildcard->state = CURLWC_SKIP;
        continue;
      }

      if(finfo->flags & CURLFINFOFLAG_KNOWN_SIZE)
        ftpc->known_filesize = finfo->size;

      result = ftp_parse_url_path(data);
      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;
      }
      return result;
    }

    case CURLWC_SKIP: {
      if(data->set.chunk_end) {
        Curl_set_in_callback(data, true);
        data->set.chunk_end(data->wildcard.customptr);
        Curl_set_in_callback(data, false);
      }
      Curl_llist_remove(&wildcard->filelist, wildcard->filelist.head, NULL);
      wildcard->state = (wildcard->filelist.size == 0) ?
        CURLWC_CLEAN : CURLWC_DOWNLOADING;
      continue;
    }

3932
3933
3934
3935
3936
3937
3938
3939
3940
3941

3942
3943
3944
3945
3946
3947
3948
3949
3950
3951
3952
3953
3954
3955
3956
3957
3958
3959
3960
3961
3962
3963
3964
3965
3966
3967
3968
3969
3970
3971
3972
3973
3974
3975
3976
3977
3978
3979
3980
3981
3982
3983
3984
3985
3986
3987
3988
3989
3990
3991
3992
3993
3994
3995
3996
3997
3998
3999
4000
4001
4002
4003
4004
4005
4006
4007
4008


4009
4010
4011
4012
4013
4014
4015
4016
4017
4018
4019
4020
4021
4022
4023
4024
4025
4026
4027
4028
4029
4030
4031
4032
4033
4034
 * 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->state.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;
}

/***********************************************************************
 *
 * 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 Curl_easy *data = conn->data;
    if(data->state.most_recent_ftp_entrypath == ftpc->entrypath) {
      data->state.most_recent_ftp_entrypath = NULL;
    }
    Curl_safefree(ftpc->entrypath);
  }

  freedirs(ftpc);







|


>





|
|
|
|







|




|














|




|

|



|



|

|












|
>
>















|


<







3962
3963
3964
3965
3966
3967
3968
3969
3970
3971
3972
3973
3974
3975
3976
3977
3978
3979
3980
3981
3982
3983
3984
3985
3986
3987
3988
3989
3990
3991
3992
3993
3994
3995
3996
3997
3998
3999
4000
4001
4002
4003
4004
4005
4006
4007
4008
4009
4010
4011
4012
4013
4014
4015
4016
4017
4018
4019
4020
4021
4022
4023
4024
4025
4026
4027
4028
4029
4030
4031
4032
4033
4034
4035
4036
4037
4038
4039
4040
4041
4042
4043
4044
4045
4046
4047
4048
4049
4050
4051
4052
4053
4054
4055
4056
4057
4058
4059

4060
4061
4062
4063
4064
4065
4066
 * 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 Curl_easy *data, bool *done)
{
  CURLcode result = CURLE_OK;
  struct connectdata *conn = data->conn;
  struct ftp_conn *ftpc = &conn->proto.ftpc;

  *done = FALSE; /* default to false */
  ftpc->wait_data_conn = FALSE; /* default to no such wait */

  if(data->state.wildcardmatch) {
    result = wc_statemach(data);
    if(data->wildcard.state == CURLWC_SKIP ||
      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(data);
    if(result)
      return result;
  }

  result = ftp_regular_transfer(data, done);

  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 Curl_easy *data, struct connectdata *conn)
{
  CURLcode result = CURLE_OK;

  if(conn->proto.ftpc.ctl_valid) {
    result = Curl_pp_sendf(data, &conn->proto.ftpc.pp, "%s", "QUIT");
    if(result) {
      failf(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(data, FTP_STOP);
      return result;
    }

    state(data, FTP_QUIT);

    result = ftp_block_statemach(data, conn);
  }

  return result;
}

/***********************************************************************
 *
 * ftp_disconnect()
 *
 * Disconnect from an FTP server. Cleanup protocol-specific per-connection
 * resources. BLOCKING.
 */
static CURLcode ftp_disconnect(struct Curl_easy *data,
                               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(data, conn); /* ignore errors on the QUIT */

  if(ftpc->entrypath) {

    if(data->state.most_recent_ftp_entrypath == ftpc->entrypath) {
      data->state.most_recent_ftp_entrypath = NULL;
    }
    Curl_safefree(ftpc->entrypath);
  }

  freedirs(ftpc);
4043
4044
4045
4046
4047
4048
4049
4050
4051
4052
4053
4054

4055
4056
4057
4058
4059
4060
4061
 *
 * ftp_parse_url_path()
 *
 * Parse the URL path into separate path components.
 *
 */
static
CURLcode ftp_parse_url_path(struct connectdata *conn)
{
  struct Curl_easy *data = conn->data;
  /* the ftp struct is already inited in ftp_connect() */
  struct FTP *ftp = data->req.p.ftp;

  struct ftp_conn *ftpc = &conn->proto.ftpc;
  const char *slashPos = NULL;
  const char *fileName = NULL;
  CURLcode result = CURLE_OK;
  char *rawPath = NULL; /* url-decoded "raw" path */
  size_t pathLen = 0;








|

<


>







4075
4076
4077
4078
4079
4080
4081
4082
4083

4084
4085
4086
4087
4088
4089
4090
4091
4092
4093
 *
 * ftp_parse_url_path()
 *
 * Parse the URL path into separate path components.
 *
 */
static
CURLcode ftp_parse_url_path(struct Curl_easy *data)
{

  /* the ftp struct is already inited in ftp_connect() */
  struct FTP *ftp = data->req.p.ftp;
  struct connectdata *conn = data->conn;
  struct ftp_conn *ftpc = &conn->proto.ftpc;
  const char *slashPos = NULL;
  const char *fileName = NULL;
  CURLcode result = CURLE_OK;
  char *rawPath = NULL; /* url-decoded "raw" path */
  size_t pathLen = 0;

4189
4190
4191
4192
4193
4194
4195
4196
4197
4198

4199
4200
4201
4202
4203
4204
4205
4206
4207
4208
4209
4210
4211
4212
4213
4214
4215
4216
4217
4218
4219
4220
4221
4222
4223
4224
4225
4226
4227
4228
4229
4230
4231
4232
4233
4234
4235
4236
4237
4238
4239
4240
4241
4242
4243
4244
4245
4246
4247
4248
4249
4250
4251
4252
4253
4254
4255
4256
4257
4258
4259
4260
4261
4262
4263
4264
4265
4266
4267
4268
4269
4270
4271
4272
4273
4274
4275
4276
4277
4278
4279
4280
4281
4282
4283
4284
4285
4286
4287
4288
4289
4290

4291
4292
4293
4294
4295
4296
4297
4298
4299
4300
4301
4302
4303
  }

  free(rawPath);
  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.p.ftp;
  struct ftp_conn *ftpc = &conn->proto.ftpc;

  if(connected) {
    int completed;
    CURLcode result = ftp_do_more(conn, &completed);

    if(result) {
      close_secondarysocket(conn);
      return result;
    }
  }

  if(ftp->transfer != FTPTRANSFER_BODY)
    /* no data to transfer */
    Curl_setup_transfer(conn->data, -1, -1, FALSE, -1);
  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 Curl_easy *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 Curl_easy *data = conn->data;
  char *type;
  struct FTP *ftp;

  conn->data->req.p.ftp = ftp = calloc(sizeof(struct FTP), 1);
  if(NULL == ftp)
    return CURLE_OUT_OF_MEMORY;

  ftp->path = &data->state.up.path[1]; /* don't include the initial slash */

  /* FTP URLs support an extension like ";type=<typecode>" that
   * we'll try to get now! */







|
<

>
|




|


|






|










|


|


|

|

|

















|




|










|









|










|
>

<



|







4221
4222
4223
4224
4225
4226
4227
4228

4229
4230
4231
4232
4233
4234
4235
4236
4237
4238
4239
4240
4241
4242
4243
4244
4245
4246
4247
4248
4249
4250
4251
4252
4253
4254
4255
4256
4257
4258
4259
4260
4261
4262
4263
4264
4265
4266
4267
4268
4269
4270
4271
4272
4273
4274
4275
4276
4277
4278
4279
4280
4281
4282
4283
4284
4285
4286
4287
4288
4289
4290
4291
4292
4293
4294
4295
4296
4297
4298
4299
4300
4301
4302
4303
4304
4305
4306
4307
4308
4309
4310
4311
4312
4313
4314
4315
4316
4317
4318
4319
4320
4321
4322
4323
4324

4325
4326
4327
4328
4329
4330
4331
4332
4333
4334
4335
  }

  free(rawPath);
  return CURLE_OK;
}

/* call this when the DO phase has completed */
static CURLcode ftp_dophase_done(struct Curl_easy *data, bool connected)

{
  struct connectdata *conn = data->conn;
  struct FTP *ftp = data->req.p.ftp;
  struct ftp_conn *ftpc = &conn->proto.ftpc;

  if(connected) {
    int completed;
    CURLcode result = ftp_do_more(data, &completed);

    if(result) {
      close_secondarysocket(data, conn);
      return result;
    }
  }

  if(ftp->transfer != FTPTRANSFER_BODY)
    /* no data to transfer */
    Curl_setup_transfer(data, -1, -1, FALSE, -1);
  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 Curl_easy *data,
                          bool *dophase_done)
{
  CURLcode result = ftp_multi_statemach(data, dophase_done);

  if(result)
    DEBUGF(infof(data, "DO phase failed\n"));
  else if(*dophase_done) {
    result = ftp_dophase_done(data, FALSE /* not connected */);

    DEBUGF(infof(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 Curl_easy *data,
                              bool *dophase_done)
{
  CURLcode result = CURLE_OK;
  bool connected = FALSE;
  struct connectdata *conn = data->conn;
  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(data,
                       &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(data, connected);

    if(result)
      return result;
  }
  else
    freedirs(ftpc);

  return result;
}

static CURLcode ftp_setup_connection(struct Curl_easy *data,
                                     struct connectdata *conn)
{

  char *type;
  struct FTP *ftp;

  data->req.p.ftp = ftp = calloc(sizeof(struct FTP), 1);
  if(NULL == ftp)
    return CURLE_OUT_OF_MEMORY;

  ftp->path = &data->state.up.path[1]; /* don't include the initial slash */

  /* FTP URLs support an extension like ";type=<typecode>" that
   * we'll try to get now! */
Changes to jni/curl/lib/ftp.h.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#ifndef HEADER_CURL_FTP_H
#define HEADER_CURL_FTP_H
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2020, 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 https://curl.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









|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#ifndef HEADER_CURL_FTP_H
#define HEADER_CURL_FTP_H
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2021, 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 https://curl.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
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
#ifndef CURL_DISABLE_FTP
extern const struct Curl_handler Curl_handler_ftp;

#ifdef USE_SSL
extern const struct Curl_handler Curl_handler_ftps;
#endif

CURLcode Curl_GetFTPResponse(ssize_t *nread, struct connectdata *conn,
                             int *ftpcode);
#endif /* CURL_DISABLE_FTP */

/****************************************************************************
 * FTP unique setup
 ***************************************************************************/
typedef enum {







|







27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
#ifndef CURL_DISABLE_FTP
extern const struct Curl_handler Curl_handler_ftp;

#ifdef USE_SSL
extern const struct Curl_handler Curl_handler_ftps;
#endif

CURLcode Curl_GetFTPResponse(struct Curl_easy *data, ssize_t *nread,
                             int *ftpcode);
#endif /* CURL_DISABLE_FTP */

/****************************************************************************
 * FTP unique setup
 ***************************************************************************/
typedef enum {
112
113
114
115
116
117
118

119
120
121
122
123
124
125
126
127
128
129
130
131
132
133




134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156


/* 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 */
  char *file;    /* url-decoded file name (or path) */
  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 */
  int cwdcount;     /* number of CWD commands issued */
  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;   /* url-decoded 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 */







>


<












>
>
>
>














<
<
<
<





112
113
114
115
116
117
118
119
120
121

122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151




152
153
154
155
156


/* 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 *file;    /* url-decoded file name (or path) */
  char **dirs;   /* realloc()ed array for path components */
  int dirdepth;  /* number of entries used in the 'dirs' array */

  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 */
  int cwdcount;     /* number of CWD commands issued */
  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 */
  /* newhost is the (allocated) IP addr or host name to connect the data
     connection to */
  unsigned short newport;
  char *newhost;
  char *prevpath;   /* url-decoded 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 */




};

#define DEFAULT_ACCEPT_TIMEOUT   60000 /* milliseconds == one minute */

#endif /* HEADER_CURL_FTP_H */
Changes to jni/curl/lib/ftplistparser.c.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2020, 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 https://curl.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







|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2021, 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 https://curl.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
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
    permissions |= 1 << 9;
  else if(str[8] != '-')
    permissions |= FTP_LP_MALFORMATED_PERM;

  return permissions;
}

static CURLcode ftp_pl_insert_finfo(struct connectdata *conn,
                                    struct fileinfo *infop)
{
  curl_fnmatch_callback compare;
  struct WildcardData *wc = &conn->data->wildcard;
  struct ftp_wc *ftpwc = wc->protdata;
  struct Curl_llist *llist = &wc->filelist;
  struct ftp_parselist_data *parser = ftpwc->parser;
  bool add = TRUE;
  struct curl_fileinfo *finfo = &infop->info;

  /* 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 */
  Curl_set_in_callback(conn->data, true);
  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;
  }
  Curl_set_in_callback(conn->data, false);

  if(add) {
    Curl_llist_insert_next(llist, llist->tail, finfo, &infop->list);
  }
  else {
    Curl_fileinfo_cleanup(infop);
  }

  ftpwc->parser->file_data = NULL;
  return CURLE_OK;
}

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 *ftpwc = conn->data->wildcard.protdata;
  struct ftp_parselist_data *parser = ftpwc->parser;
  struct fileinfo *infop;
  struct curl_fileinfo *finfo;
  unsigned long i = 0;
  CURLcode result;
  size_t retsize = bufflen;








|



|




















|




|
|










|
















|
|







264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
    permissions |= 1 << 9;
  else if(str[8] != '-')
    permissions |= FTP_LP_MALFORMATED_PERM;

  return permissions;
}

static CURLcode ftp_pl_insert_finfo(struct Curl_easy *data,
                                    struct fileinfo *infop)
{
  curl_fnmatch_callback compare;
  struct WildcardData *wc = &data->wildcard;
  struct ftp_wc *ftpwc = wc->protdata;
  struct Curl_llist *llist = &wc->filelist;
  struct ftp_parselist_data *parser = ftpwc->parser;
  bool add = TRUE;
  struct curl_fileinfo *finfo = &infop->info;

  /* 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 = data->set.fnmatch;
  if(!compare)
    compare = Curl_fnmatch;

  /* filter pattern-corresponding filenames */
  Curl_set_in_callback(data, true);
  if(compare(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;
  }
  Curl_set_in_callback(data, false);

  if(add) {
    Curl_llist_insert_next(llist, llist->tail, finfo, &infop->list);
  }
  else {
    Curl_fileinfo_cleanup(infop);
  }

  ftpwc->parser->file_data = NULL;
  return CURLE_OK;
}

size_t Curl_ftp_parselist(char *buffer, size_t size, size_t nmemb,
                          void *connptr)
{
  size_t bufflen = size*nmemb;
  struct Curl_easy *data = (struct Curl_easy *)connptr;
  struct ftp_wc *ftpwc = data->wildcard.protdata;
  struct ftp_parselist_data *parser = ftpwc->parser;
  struct fileinfo *infop;
  struct curl_fileinfo *finfo;
  unsigned long i = 0;
  CURLcode result;
  size_t retsize = bufflen;

724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
          if(c == '\r') {
            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, infop);
            if(result) {
              parser->error = result;
              goto fail;
            }
          }
          break;
        case PL_UNIX_FILENAME_WINDOWSEOL:
          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, infop);
            if(result) {
              parser->error = result;
              goto fail;
            }
          }
          else {
            parser->error = CURLE_FTP_BAD_FILE_LIST;







|











|







724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
          if(c == '\r') {
            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(data, infop);
            if(result) {
              parser->error = result;
              goto fail;
            }
          }
          break;
        case PL_UNIX_FILENAME_WINDOWSEOL:
          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(data, infop);
            if(result) {
              parser->error = result;
              goto fail;
            }
          }
          else {
            parser->error = CURLE_FTP_BAD_FILE_LIST;
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
          parser->item_length++;
          if(c == '\r') {
            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, infop);
            if(result) {
              parser->error = result;
              goto fail;
            }
            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, infop);
            if(result) {
              parser->error = result;
              goto fail;
            }
            parser->state.UNIX.main = PL_UNIX_FILETYPE;
          }
          else {







|











|







831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
          parser->item_length++;
          if(c == '\r') {
            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(data, infop);
            if(result) {
              parser->error = result;
              goto fail;
            }
            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(data, infop);
            if(result) {
              parser->error = result;
              goto fail;
            }
            parser->state.UNIX.main = PL_UNIX_FILETYPE;
          }
          else {
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
            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, infop);
            if(result) {
              parser->error = result;
              goto fail;
            }
            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, infop);
            if(result) {
              parser->error = result;
              goto fail;
            }
            parser->state.NT.main = PL_WINNT_DATE;
            parser->state.NT.sub.filename = PL_WINNT_FILENAME_PRESPACE;
          }







|











|







963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
            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(data, infop);
            if(result) {
              parser->error = result;
              goto fail;
            }
            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(data, infop);
            if(result) {
              parser->error = result;
              goto fail;
            }
            parser->state.NT.main = PL_WINNT_DATE;
            parser->state.NT.sub.filename = PL_WINNT_FILENAME_PRESPACE;
          }
Changes to jni/curl/lib/getinfo.c.
97
98
99
100
101
102
103

104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122

123
124
125
126
127
128
129
    *param_charp = data->change.url?data->change.url:(char *)"";
    break;
  case CURLINFO_EFFECTIVE_METHOD: {
    const char *m = data->set.str[STRING_CUSTOMREQUEST];
    if(!m) {
      if(data->set.opt_no_body)
        m = "HEAD";

      else {
        switch(data->state.httpreq) {
        case HTTPREQ_POST:
        case HTTPREQ_POST_FORM:
        case HTTPREQ_POST_MIME:
          m = "POST";
          break;
        case HTTPREQ_PUT:
          m = "PUT";
          break;
        default: /* this should never happen */
        case HTTPREQ_GET:
          m = "GET";
          break;
        case HTTPREQ_HEAD:
          m = "HEAD";
          break;
        }
      }

    }
    *param_charp = m;
  }
    break;
  case CURLINFO_CONTENT_TYPE:
    *param_charp = data->info.contenttype;
    break;







>



















>







97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
    *param_charp = data->change.url?data->change.url:(char *)"";
    break;
  case CURLINFO_EFFECTIVE_METHOD: {
    const char *m = data->set.str[STRING_CUSTOMREQUEST];
    if(!m) {
      if(data->set.opt_no_body)
        m = "HEAD";
#ifndef CURL_DISABLE_HTTP
      else {
        switch(data->state.httpreq) {
        case HTTPREQ_POST:
        case HTTPREQ_POST_FORM:
        case HTTPREQ_POST_MIME:
          m = "POST";
          break;
        case HTTPREQ_PUT:
          m = "PUT";
          break;
        default: /* this should never happen */
        case HTTPREQ_GET:
          m = "GET";
          break;
        case HTTPREQ_HEAD:
          m = "HEAD";
          break;
        }
      }
#endif
    }
    *param_charp = m;
  }
    break;
  case CURLINFO_CONTENT_TYPE:
    *param_charp = data->info.contenttype;
    break;
Changes to jni/curl/lib/gopher.c.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2020, 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 https://curl.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







|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2021, 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 https://curl.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
29
30
31
32
33
34
35

36
37
38
39
40
41
42
43
44
45
46
47
48




49
50
51
52
53
54
55
#include "transfer.h"
#include "sendf.h"
#include "connect.h"
#include "progress.h"
#include "gopher.h"
#include "select.h"
#include "strdup.h"

#include "url.h"
#include "escape.h"
#include "warnless.h"
#include "curl_printf.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.
 */








>












|
>
>
>
>







29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
#include "transfer.h"
#include "sendf.h"
#include "connect.h"
#include "progress.h"
#include "gopher.h"
#include "select.h"
#include "strdup.h"
#include "vtls/vtls.h"
#include "url.h"
#include "escape.h"
#include "warnless.h"
#include "curl_printf.h"
#include "curl_memory.h"
/* The last #include file should be: */
#include "memdebug.h"

/*
 * Forward declarations.
 */

static CURLcode gopher_do(struct Curl_easy *data, bool *done);
#ifdef USE_SSL
static CURLcode gopher_connect(struct Curl_easy *data, bool *done);
static CURLcode gopher_connecting(struct Curl_easy *data, bool *done);
#endif

/*
 * Gopher protocol handler.
 * This is also a nice simple template to build off for simple
 * connect-command-download protocols.
 */

71
72
73
74
75
76
77









































78
79
80
81
82
83
84
85
86
87
88
  ZERO_NULL,                            /* connection_check */
  PORT_GOPHER,                          /* defport */
  CURLPROTO_GOPHER,                     /* protocol */
  CURLPROTO_GOPHER,                     /* family */
  PROTOPT_NONE                          /* flags */
};










































static CURLcode gopher_do(struct connectdata *conn, bool *done)
{
  CURLcode result = CURLE_OK;
  struct Curl_easy *data = conn->data;
  curl_socket_t sockfd = conn->sock[FIRSTSOCKET];
  char *gopherpath;
  char *path = data->state.up.path;
  char *query = data->state.up.query;
  char *sel = NULL;
  char *sel_org = NULL;
  timediff_t timeout_ms;







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|


|







76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
  ZERO_NULL,                            /* connection_check */
  PORT_GOPHER,                          /* defport */
  CURLPROTO_GOPHER,                     /* protocol */
  CURLPROTO_GOPHER,                     /* family */
  PROTOPT_NONE                          /* flags */
};

#ifdef USE_SSL
const struct Curl_handler Curl_handler_gophers = {
  "GOPHERS",                            /* scheme */
  ZERO_NULL,                            /* setup_connection */
  gopher_do,                            /* do_it */
  ZERO_NULL,                            /* done */
  ZERO_NULL,                            /* do_more */
  gopher_connect,                       /* connect_it */
  gopher_connecting,                    /* 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 */
  ZERO_NULL,                            /* connection_check */
  PORT_GOPHER,                          /* defport */
  CURLPROTO_GOPHERS,                    /* protocol */
  CURLPROTO_GOPHER,                     /* family */
  PROTOPT_SSL                           /* flags */
};

static CURLcode gopher_connect(struct Curl_easy *data, bool *done)
{
  (void)data;
  (void)done;
  return CURLE_OK;
}

static CURLcode gopher_connecting(struct Curl_easy *data, bool *done)
{
  struct connectdata *conn = data->conn;
  CURLcode result = Curl_ssl_connect(data, conn, FIRSTSOCKET);
  if(result)
    connclose(conn, "Failed TLS connection");
  *done = TRUE;
  return result;
}
#endif

static CURLcode gopher_do(struct Curl_easy *data, bool *done)
{
  CURLcode result = CURLE_OK;
  struct connectdata *conn = data->conn;
  curl_socket_t sockfd = conn->sock[FIRSTSOCKET];
  char *gopherpath;
  char *path = data->state.up.path;
  char *query = data->state.up.query;
  char *sel = NULL;
  char *sel_org = NULL;
  timediff_t timeout_ms;
123
124
125
126
127
128
129





130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
      return result;
    sel_org = sel;
  }

  k = curlx_uztosz(len);

  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)
        break;

      k -= amount;
      sel += amount;
      if(k < 1)
        break; /* but it did write it all */
    }
    else
      break;

    timeout_ms = Curl_timeleft(conn->data, NULL, FALSE);
    if(timeout_ms < 0) {
      result = CURLE_OPERATION_TIMEDOUT;
      break;
    }
    if(!timeout_ms)
      timeout_ms = TIMEDIFF_T_MAX;








>
>
>
>
>
|

|











|







169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
      return result;
    sel_org = sel;
  }

  k = curlx_uztosz(len);

  for(;;) {
    /* Break out of the loop if the selector is empty because OpenSSL and/or
       LibreSSL fail with errno 0 if this is the case. */
    if(strlen(sel) < 1)
      break;

    result = Curl_write(data, sockfd, sel, k, &amount);
    if(!result) { /* Which may not have written it all! */
      result = Curl_client_write(data, CLIENTWRITE_HEADER, sel, amount);
      if(result)
        break;

      k -= amount;
      sel += amount;
      if(k < 1)
        break; /* but it did write it all */
    }
    else
      break;

    timeout_ms = Curl_timeleft(data, NULL, FALSE);
    if(timeout_ms < 0) {
      result = CURLE_OPERATION_TIMEDOUT;
      break;
    }
    if(!timeout_ms)
      timeout_ms = TIMEDIFF_T_MAX;

165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
      break;
    }
  }

  free(sel_org);

  if(!result)
    result = Curl_write(conn, sockfd, "\r\n", 2, &amount);
  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(data, FIRSTSOCKET, -1, FALSE, -1);
  return CURLE_OK;
}
#endif /*CURL_DISABLE_GOPHER*/







|




|







216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
      break;
    }
  }

  free(sel_org);

  if(!result)
    result = Curl_write(data, sockfd, "\r\n", 2, &amount);
  if(result) {
    failf(data, "Failed sending Gopher request");
    return result;
  }
  result = Curl_client_write(data, CLIENTWRITE_HEADER, (char *)"\r\n", 2);
  if(result)
    return result;

  Curl_setup_transfer(data, FIRSTSOCKET, -1, FALSE, -1);
  return CURLE_OK;
}
#endif /*CURL_DISABLE_GOPHER*/
Changes to jni/curl/lib/gopher.h.
20
21
22
23
24
25
26



27
28
29
 * 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 */







>
>
>



20
21
22
23
24
25
26
27
28
29
30
31
32
 * 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;
#ifdef USE_SSL
extern const struct Curl_handler Curl_handler_gophers;
#endif
#endif

#endif /* HEADER_CURL_GOPHER_H */
Changes to jni/curl/lib/hash.c.
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
      }
    }
  }

  return NULL;
}

#if defined(DEBUGBUILD) && defined(AGGRESIVE_TEST)
void
Curl_hash_apply(Curl_hash *h, void *user,
                void (*cb)(void *user, void *ptr))
{
  struct Curl_llist_element  *le;
  int                  i;








|







171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
      }
    }
  }

  return NULL;
}

#if defined(DEBUGBUILD) && defined(AGGRESSIVE_TEST)
void
Curl_hash_apply(Curl_hash *h, void *user,
                void (*cb)(void *user, void *ptr))
{
  struct Curl_llist_element  *le;
  int                  i;

Changes to jni/curl/lib/hostasyn.c.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2020, 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 https://curl.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







|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2021, 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 https://curl.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
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
 *
 * 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.
 */
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 Curl_easy *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(data->share)
        Curl_share_unlock(data, CURL_LOCK_DATA_DNS);

      if(!dns) {
        /* failed to store, cleanup and return error */
        Curl_freeaddrinfo(ai);
        result = CURLE_OUT_OF_MEMORY;
      }
    }
    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;
}

/*
 * 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
 */
struct 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 */







|






|



<
<




|
|














|




|












|




|



62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79


80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
 *
 * 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.
 */
CURLcode Curl_addrinfo_callback(struct Curl_easy *data,
                                int status,
                                struct Curl_addrinfo *ai)
{
  struct Curl_dns_entry *dns = NULL;
  CURLcode result = CURLE_OK;

  data->state.async.status = status;

  if(CURL_ASYNC_SUCCESS == status) {
    if(ai) {


      if(data->share)
        Curl_share_lock(data, CURL_LOCK_DATA_DNS, CURL_LOCK_ACCESS_SINGLE);

      dns = Curl_cache_addr(data, ai,
                            data->state.async.hostname,
                            data->state.async.port);
      if(data->share)
        Curl_share_unlock(data, CURL_LOCK_DATA_DNS);

      if(!dns) {
        /* failed to store, cleanup and return error */
        Curl_freeaddrinfo(ai);
        result = CURLE_OUT_OF_MEMORY;
      }
    }
    else {
      result = CURLE_OUT_OF_MEMORY;
    }
  }

  data->state.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 */
  data->state.async.done = TRUE;

  /* IPv4: The input hostent struct will be freed by ares when we return from
     this function */
  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
 */
struct Curl_addrinfo *Curl_getaddrinfo(struct Curl_easy *data,
                                       const char *hostname,
                                       int port,
                                       int *waitp)
{
  return Curl_resolver_getaddrinfo(data, hostname, port, waitp);
}

#endif /* CURLRES_ASYNCH */
Changes to jni/curl/lib/hostip.c.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2020, 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 https://curl.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







|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2021, 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 https://curl.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
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
/* 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)
{
  struct Curl_dns_entry *dns = NULL;
  size_t entry_len;
  struct Curl_easy *data = conn->data;
  char entry_id[MAX_HOSTCACHE_LEN];

  /* Create an entry id, based upon the hostname and port */
  create_hostcache_id(hostname, port, entry_id, sizeof(entry_id));
  entry_len = strlen(entry_id);

  /* See if its already in our dns cache */







|
<
|
|



<







249
250
251
252
253
254
255
256

257
258
259
260
261

262
263
264
265
266
267
268
/* 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 Curl_easy *data,

                                         const char *hostname,
                                         int port)
{
  struct Curl_dns_entry *dns = NULL;
  size_t entry_len;

  char entry_id[MAX_HOSTCACHE_LEN];

  /* Create an entry id, based upon the hostname and port */
  create_hostcache_id(hostname, port, entry_id, sizeof(entry_id));
  entry_len = strlen(entry_id);

  /* See if its already in our dns cache */
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
 *
 * 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!
 */
struct Curl_dns_entry *
Curl_fetch_addr(struct connectdata *conn,
                const char *hostname,
                int port)
{
  struct Curl_easy *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);








|



<





|







305
306
307
308
309
310
311
312
313
314
315

316
317
318
319
320
321
322
323
324
325
326
327
328
 *
 * 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!
 */
struct Curl_dns_entry *
Curl_fetch_addr(struct Curl_easy *data,
                const char *hostname,
                int port)
{

  struct Curl_dns_entry *dns = NULL;

  if(data->share)
    Curl_share_lock(data, CURL_LOCK_DATA_DNS, CURL_LOCK_ACCESS_SINGLE);

  dns = fetch_addr(data, hostname, port);

  if(dns)
    dns->inuse++; /* we use it! */

  if(data->share)
    Curl_share_unlock(data, CURL_LOCK_DATA_DNS);

440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
  create_hostcache_id(hostname, port, entry_id, sizeof(entry_id));
  entry_len = strlen(entry_id);

  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);
    return NULL;







|







437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
  create_hostcache_id(hostname, port, entry_id, sizeof(entry_id));
  entry_len = strlen(entry_id);

  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 permanent 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);
    return NULL;
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492

493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
 * Return codes:
 *
 * CURLRESOLV_ERROR   (-1) = error, no pointer
 * CURLRESOLV_RESOLVED (0) = OK, pointer provided
 * CURLRESOLV_PENDING  (1) = waiting for response, no pointer
 */

enum resolve_t Curl_resolv(struct connectdata *conn,
                           const char *hostname,
                           int port,
                           bool allowDOH,
                           struct Curl_dns_entry **entry)
{
  struct Curl_dns_entry *dns = NULL;
  struct Curl_easy *data = conn->data;
  CURLcode result;
  enum resolve_t rc = CURLRESOLV_ERROR; /* default to failure */


  *entry = NULL;
  conn->bits.doh = FALSE; /* default is not */

  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;
  }








|






<


>







|







473
474
475
476
477
478
479
480
481
482
483
484
485
486

487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
 * Return codes:
 *
 * CURLRESOLV_ERROR   (-1) = error, no pointer
 * CURLRESOLV_RESOLVED (0) = OK, pointer provided
 * CURLRESOLV_PENDING  (1) = waiting for response, no pointer
 */

enum resolve_t Curl_resolv(struct Curl_easy *data,
                           const char *hostname,
                           int port,
                           bool allowDOH,
                           struct Curl_dns_entry **entry)
{
  struct Curl_dns_entry *dns = NULL;

  CURLcode result;
  enum resolve_t rc = CURLRESOLV_ERROR; /* default to failure */
  struct connectdata *conn = data->conn;

  *entry = NULL;
  conn->bits.doh = FALSE; /* default is not */

  if(data->share)
    Curl_share_lock(data, CURL_LOCK_DATA_DNS, CURL_LOCK_ACCESS_SINGLE);

  dns = fetch_addr(data, hostname, port);

  if(dns) {
    infof(data, "Hostname %s was found in DNS cache\n", hostname);
    dns->inuse++; /* we use it! */
    rc = CURLRESOLV_RESOLVED;
  }

519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
#endif
      bool ipnum = FALSE;

    /* notify the resolver start callback */
    if(data->set.resolver_start) {
      int st;
      Curl_set_in_callback(data, true);
      st = data->set.resolver_start(data->state.resolver, NULL,
                                    data->set.resolver_start_client);
      Curl_set_in_callback(data, false);
      if(st)
        return CURLRESOLV_ERROR;
    }

#ifndef USE_RESOLVE_ON_IPS







|







516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
#endif
      bool ipnum = FALSE;

    /* notify the resolver start callback */
    if(data->set.resolver_start) {
      int st;
      Curl_set_in_callback(data, true);
      st = data->set.resolver_start(data->state.async.resolver, NULL,
                                    data->set.resolver_start_client);
      Curl_set_in_callback(data, false);
      if(st)
        return CURLRESOLV_ERROR;
    }

#ifndef USE_RESOLVE_ON_IPS
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
#endif /* ENABLE_IPV6 */

#endif /* !USE_RESOLVE_ON_IPS */

    if(!addr) {
      /* 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(allowDOH && data->set.doh && !ipnum) {
        addr = Curl_doh(conn, hostname, port, &respwait);
      }
      else {
        /* 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_resolv_check(conn, &dns);
        if(result) /* error detected */
          return CURLRESOLV_ERROR;
        if(dns)
          rc = CURLRESOLV_RESOLVED; /* pointer provided */
        else
          rc = CURLRESOLV_PENDING; /* no info yet */
      }







|



|





|













|







558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
#endif /* ENABLE_IPV6 */

#endif /* !USE_RESOLVE_ON_IPS */

    if(!addr) {
      /* Check what IP specifics the app has requested and if we can provide
       * it. If not, bail out. */
      if(!Curl_ipvalid(data, conn))
        return CURLRESOLV_ERROR;

      if(allowDOH && data->set.doh && !ipnum) {
        addr = Curl_doh(data, hostname, port, &respwait);
      }
      else {
        /* 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(data,
#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_resolv_check(data, &dns);
        if(result) /* error detected */
          return CURLRESOLV_ERROR;
        if(dns)
          rc = CURLRESOLV_RESOLVED; /* pointer provided */
        else
          rc = CURLRESOLV_PENDING; /* no info yet */
      }
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
 *
 * 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
 */

enum resolve_t Curl_resolv_timeout(struct connectdata *conn,
                                   const char *hostname,
                                   int port,
                                   struct Curl_dns_entry **entry,
                                   timediff_t timeoutms)
{
#ifdef USE_ALARM_TIMEOUT
#ifdef HAVE_SIGACTION
  struct sigaction keep_sigact;   /* store the old struct here */
  volatile bool keep_copysig = FALSE; /* whether 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 Curl_easy *data = conn->data;
#endif /* USE_ALARM_TIMEOUT */
  enum resolve_t 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 > LONG_MAX) ? LONG_MAX : (long)timeoutms;

  if(!timeout)
    /* USE_ALARM_TIMEOUT defined, but no timeout actually requested */
    return Curl_resolv(conn, hostname, port, TRUE, 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. */
    failf(data,
        "remaining timeout of %ld too small to resolve via SIGALRM method",
        timeout);







|

















<


















|







651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675

676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
 *
 * 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
 */

enum resolve_t Curl_resolv_timeout(struct Curl_easy *data,
                                   const char *hostname,
                                   int port,
                                   struct Curl_dns_entry **entry,
                                   timediff_t timeoutms)
{
#ifdef USE_ALARM_TIMEOUT
#ifdef HAVE_SIGACTION
  struct sigaction keep_sigact;   /* store the old struct here */
  volatile bool keep_copysig = FALSE; /* whether 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;

#endif /* USE_ALARM_TIMEOUT */
  enum resolve_t 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 > LONG_MAX) ? LONG_MAX : (long)timeoutms;

  if(!timeout)
    /* USE_ALARM_TIMEOUT defined, but no timeout actually requested */
    return Curl_resolv(data, hostname, port, TRUE, 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. */
    failf(data,
        "remaining timeout of %ld too small to resolve via SIGALRM method",
        timeout);
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
     *************************************************************/
#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, TRUE, entry);

#ifdef USE_ALARM_TIMEOUT
clean_up:

  if(!prev_alarm)
    /* deactivate a possibly active alarm before uninstalling the handler */
    alarm(0);







|



















|








|







720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
     *************************************************************/
#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 behavior! */
    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(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(data, hostname, port, TRUE, entry);

#ifdef USE_ALARM_TIMEOUT
clean_up:

  if(!prev_alarm)
    /* deactivate a possibly active alarm before uninstalling the handler */
    alarm(0);
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
#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 */
    timediff_t elapsed_secs = Curl_timediff(Curl_now(),
                                            conn->created) / 1000;

    /* the alarm period is counted in even number of seconds */
    unsigned long alarm_set = (unsigned long)(prev_alarm - elapsed_secs);

    if(!alarm_set ||
       ((alarm_set >= 0x80000000) && (prev_alarm < 0x80000000)) ) {
      /* if the alarm time-left reached zero or turned "negative" (counted







|







776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
#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 */
    timediff_t elapsed_secs = Curl_timediff(Curl_now(),
                                            data->conn->created) / 1000;

    /* the alarm period is counted in even number of seconds */
    unsigned long alarm_set = (unsigned long)(prev_alarm - elapsed_secs);

    if(!alarm_set ||
       ((alarm_set >= 0x80000000) && (prev_alarm < 0x80000000)) ) {
      /* if the alarm time-left reached zero or turned "negative" (counted
912
913
914
915
916
917
918


919
920
921
922





923
924
925
926
927
928
929
930
931
932
933
934
935
936
#if !defined(CURL_DISABLE_VERBOSE_STRINGS)
      char *addresses = NULL;
#endif
      char *addr_begin;
      char *addr_end;
      char *port_ptr;
      char *end_ptr;


      char *host_end;
      unsigned long tmp_port;
      bool error = true;






      host_end = strchr(hostp->data, ':');
      if(!host_end ||
         ((host_end - hostp->data) >= (ptrdiff_t)sizeof(hostname)))
        goto err;

      memcpy(hostname, hostp->data, host_end - hostp->data);
      hostname[host_end - hostp->data] = '\0';

      port_ptr = host_end + 1;
      tmp_port = strtoul(port_ptr, &end_ptr, 10);
      if(tmp_port > USHRT_MAX || end_ptr == port_ptr || *end_ptr != ':')
        goto err;

      port = (int)tmp_port;







>
>




>
>
>
>
>
|

|


|
|







908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
#if !defined(CURL_DISABLE_VERBOSE_STRINGS)
      char *addresses = NULL;
#endif
      char *addr_begin;
      char *addr_end;
      char *port_ptr;
      char *end_ptr;
      bool permanent = TRUE;
      char *host_begin;
      char *host_end;
      unsigned long tmp_port;
      bool error = true;

      host_begin = hostp->data;
      if(host_begin[0] == '+') {
        host_begin++;
        permanent = FALSE;
      }
      host_end = strchr(host_begin, ':');
      if(!host_end ||
         ((host_end - host_begin) >= (ptrdiff_t)sizeof(hostname)))
        goto err;

      memcpy(hostname, host_begin, host_end - host_begin);
      hostname[host_end - host_begin] = '\0';

      port_ptr = host_end + 1;
      tmp_port = strtoul(port_ptr, &end_ptr, 10);
      if(tmp_port > USHRT_MAX || end_ptr == port_ptr || *end_ptr != ':')
        goto err;

      port = (int)tmp_port;
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022




1023
1024
1025
1026
1027
1028
1029

1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095

1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
      /* Create an entry id, based upon the hostname and port */
      create_hostcache_id(hostname, port, entry_id, sizeof(entry_id));
      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);

      if(dns) {
        infof(data, "RESOLVE %s:%d is - old addresses discarded!\n",
                hostname, port);
        /* delete old entry entry, there are two reasons for this
         1. old entry may have different addresses.
         2. even if entry with correct addresses is already in the cache,
            but if it is close to expire, then by the time next http
            request is made, it can get expired and pruned because old
            entry is not necessarily marked as added by CURLOPT_RESOLVE. */





        Curl_hash_delete(data->dns.hostcache, entry_id, entry_len + 1);
      }

      /* put this new host in the cache */
      dns = Curl_cache_addr(data, head, 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--;
      }

      if(data->share)
        Curl_share_unlock(data, CURL_LOCK_DATA_DNS);

      if(!dns) {
        Curl_freeaddrinfo(head);
        return CURLE_OUT_OF_MEMORY;
      }
      infof(data, "Added %s:%d:%s to DNS cache\n",
            hostname, port, addresses);

      /* Wildcard hostname */
      if(hostname[0] == '*' && hostname[1] == '\0') {
        infof(data, "RESOLVE %s:%d is wildcard, enabling wildcard checks\n",
              hostname, port);
        data->change.wildcard_resolve = true;
      }
    }
  }
  data->change.resolve = NULL; /* dealt with now */

  return CURLE_OK;
}

CURLcode Curl_resolv_check(struct connectdata *conn,
                           struct Curl_dns_entry **dns)
{
#if defined(CURL_DISABLE_DOH) && !defined(CURLRES_ASYNCH)
  (void)dns;
#endif

  if(conn->bits.doh)
    return Curl_doh_is_resolved(conn, dns);
  return Curl_resolver_is_resolved(conn, dns);
}

int Curl_resolv_getsock(struct connectdata *conn,
                        curl_socket_t *socks)
{
#ifdef CURLRES_ASYNCH
  if(conn->bits.doh)
    /* nothing to wait for during DOH resolve, those handles have their own
       sockets */
    return GETSOCK_BLANK;
  return Curl_resolver_getsock(conn, socks);
#else
  (void)conn;
  (void)socks;
  return GETSOCK_BLANK;
#endif
}

/* 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 */
CURLcode Curl_once_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) {
    struct Curl_easy *data = conn->data;
    DEBUGASSERT(data);
    Curl_detach_connnection(data);
    Curl_conncache_remove_conn(data, conn, TRUE);
    Curl_disconnect(data, conn, TRUE);
  }
  return result;
}







|





|




|
>
>
>
>







>
|


|









|
|














|






|
|
|


|



|



|

|










|
<


>

|
|
|


|


<
<






1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100

1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112


1113
1114
1115
1116
1117
1118
      /* Create an entry id, based upon the hostname and port */
      create_hostcache_id(hostname, port, entry_id, sizeof(entry_id));
      entry_len = strlen(entry_id);

      if(data->share)
        Curl_share_lock(data, CURL_LOCK_DATA_DNS, CURL_LOCK_ACCESS_SINGLE);

      /* See if it's already in our dns cache */
      dns = Curl_hash_pick(data->dns.hostcache, entry_id, entry_len + 1);

      if(dns) {
        infof(data, "RESOLVE %s:%d is - old addresses discarded!\n",
                hostname, port);
        /* delete old entry, there are two reasons for this
         1. old entry may have different addresses.
         2. even if entry with correct addresses is already in the cache,
            but if it is close to expire, then by the time next http
            request is made, it can get expired and pruned because old
            entry is not necessarily marked as permanent.
         3. when adding a non-permanent entry, we want it to remove and
            replace an existing permanent entry.
         4. when adding a non-permanent entry, we want it to get a "fresh"
            timeout that starts _now_. */

        Curl_hash_delete(data->dns.hostcache, entry_id, entry_len + 1);
      }

      /* put this new host in the cache */
      dns = Curl_cache_addr(data, head, hostname, port);
      if(dns) {
        if(permanent)
          dns->timestamp = 0; /* mark as permanent */
        /* release the returned reference; the cache itself will keep the
         * entry alive: */
        dns->inuse--;
      }

      if(data->share)
        Curl_share_unlock(data, CURL_LOCK_DATA_DNS);

      if(!dns) {
        Curl_freeaddrinfo(head);
        return CURLE_OUT_OF_MEMORY;
      }
      infof(data, "Added %s:%d:%s to DNS cache%s\n",
            hostname, port, addresses, permanent ? "" : " (non-permanent)");

      /* Wildcard hostname */
      if(hostname[0] == '*' && hostname[1] == '\0') {
        infof(data, "RESOLVE %s:%d is wildcard, enabling wildcard checks\n",
              hostname, port);
        data->change.wildcard_resolve = true;
      }
    }
  }
  data->change.resolve = NULL; /* dealt with now */

  return CURLE_OK;
}

CURLcode Curl_resolv_check(struct Curl_easy *data,
                           struct Curl_dns_entry **dns)
{
#if defined(CURL_DISABLE_DOH) && !defined(CURLRES_ASYNCH)
  (void)dns;
#endif

  if(data->conn->bits.doh)
    return Curl_doh_is_resolved(data, dns);
  return Curl_resolver_is_resolved(data, dns);
}

int Curl_resolv_getsock(struct Curl_easy *data,
                        curl_socket_t *socks)
{
#ifdef CURLRES_ASYNCH
  if(data->conn->bits.doh)
    /* nothing to wait for during DOH resolve, those handles have their own
       sockets */
    return GETSOCK_BLANK;
  return Curl_resolver_getsock(data, socks);
#else
  (void)data;
  (void)socks;
  return GETSOCK_BLANK;
#endif
}

/* 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 */
CURLcode Curl_once_resolved(struct Curl_easy *data, bool *protocol_done)

{
  CURLcode result;
  struct connectdata *conn = data->conn;

  if(data->state.async.dns) {
    conn->dns_entry = data->state.async.dns;
    data->state.async.dns = NULL;
  }

  result = Curl_setup_conn(data, protocol_done);

  if(result) {


    Curl_detach_connnection(data);
    Curl_conncache_remove_conn(data, conn, TRUE);
    Curl_disconnect(data, conn, TRUE);
  }
  return result;
}
Changes to jni/curl/lib/hostip.h.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#ifndef HEADER_CURL_HOSTIP_H
#define HEADER_CURL_HOSTIP_H
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2020, 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 https://curl.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









|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#ifndef HEADER_CURL_HOSTIP_H
#define HEADER_CURL_HOSTIP_H
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2021, 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 https://curl.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
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
 *
 * Returns a struct Curl_hash pointer on success, NULL on failure.
 */
struct Curl_hash *Curl_global_host_cache_init(void);

struct Curl_dns_entry {
  struct 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 */
enum resolve_t {
  CURLRESOLV_TIMEDOUT = -2,
  CURLRESOLV_ERROR    = -1,
  CURLRESOLV_RESOLVED =  0,
  CURLRESOLV_PENDING  =  1
};
enum resolve_t Curl_resolv(struct connectdata *conn,
                           const char *hostname,
                           int port,
                           bool allowDOH,
                           struct Curl_dns_entry **dnsentry);
enum resolve_t Curl_resolv_timeout(struct connectdata *conn,
                                   const char *hostname, int port,
                                   struct Curl_dns_entry **dnsentry,
                                   timediff_t timeoutms);

#ifdef CURLRES_IPV6
/*
 * Curl_ipv6works() returns TRUE if IPv6 seems to work.
 */
bool Curl_ipv6works(struct connectdata *conn);
#else
#define Curl_ipv6works(x) FALSE
#endif

/*
 * Curl_ipvalid() checks what CURL_IPRESOLVE_* requirements that might've
 * been set and returns TRUE if they are OK.
 */
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
 */
struct Curl_addrinfo *Curl_getaddrinfo(struct connectdata *conn,
                                       const char *hostname,
                                       int port,
                                       int *waitp);


/* unlock a previously resolved dns entry */
void Curl_resolv_unlock(struct Curl_easy *data,







|



















|




|








|








|








|







61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
 *
 * Returns a struct Curl_hash pointer on success, NULL on failure.
 */
struct Curl_hash *Curl_global_host_cache_init(void);

struct Curl_dns_entry {
  struct Curl_addrinfo *addr;
  /* timestamp == 0 -- permanent CURLOPT_RESOLVE entry (doesn't time out) */
  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 */
enum resolve_t {
  CURLRESOLV_TIMEDOUT = -2,
  CURLRESOLV_ERROR    = -1,
  CURLRESOLV_RESOLVED =  0,
  CURLRESOLV_PENDING  =  1
};
enum resolve_t Curl_resolv(struct Curl_easy *data,
                           const char *hostname,
                           int port,
                           bool allowDOH,
                           struct Curl_dns_entry **dnsentry);
enum resolve_t Curl_resolv_timeout(struct Curl_easy *data,
                                   const char *hostname, int port,
                                   struct Curl_dns_entry **dnsentry,
                                   timediff_t timeoutms);

#ifdef CURLRES_IPV6
/*
 * Curl_ipv6works() returns TRUE if IPv6 seems to work.
 */
bool Curl_ipv6works(struct Curl_easy *data);
#else
#define Curl_ipv6works(x) FALSE
#endif

/*
 * Curl_ipvalid() checks what CURL_IPRESOLVE_* requirements that might've
 * been set and returns TRUE if they are OK.
 */
bool Curl_ipvalid(struct Curl_easy *data, 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
 */
struct Curl_addrinfo *Curl_getaddrinfo(struct Curl_easy *data,
                                       const char *hostname,
                                       int port,
                                       int *waitp);


/* unlock a previously resolved dns entry */
void Curl_resolv_unlock(struct Curl_easy *data,
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
                       GETNAMEINFO_TYPE_ARG7 flags,
                       int line, const char *source);
#endif

/* IPv4 threadsafe resolve function used for synch and asynch builds */
struct Curl_addrinfo *Curl_ipv4_resolve_r(const char *hostname, int port);

CURLcode Curl_once_resolved(struct connectdata *conn, bool *protocol_connect);

/*
 * 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.
 */
CURLcode Curl_addrinfo_callback(struct connectdata *conn,
                                int status,
                                struct 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.
 */
void Curl_printable_address(const struct 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!
 */
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.







|







|




















|







144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
                       GETNAMEINFO_TYPE_ARG7 flags,
                       int line, const char *source);
#endif

/* IPv4 threadsafe resolve function used for synch and asynch builds */
struct Curl_addrinfo *Curl_ipv4_resolve_r(const char *hostname, int port);

CURLcode Curl_once_resolved(struct Curl_easy *data, bool *protocol_connect);

/*
 * 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.
 */
CURLcode Curl_addrinfo_callback(struct Curl_easy *data,
                                int status,
                                struct 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.
 */
void Curl_printable_address(const struct 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!
 */
struct Curl_dns_entry *
Curl_fetch_addr(struct Curl_easy *data,
                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.
236
237
238
239
240
241
242
243
244
245
246
247
248
249
 */
void Curl_hostcache_clean(struct Curl_easy *data, struct Curl_hash *hash);

/*
 * Populate the cache with specified entries from CURLOPT_RESOLVE.
 */
CURLcode Curl_loadhostpairs(struct Curl_easy *data);

CURLcode Curl_resolv_check(struct connectdata *conn,
                           struct Curl_dns_entry **dns);
int Curl_resolv_getsock(struct connectdata *conn,
                        curl_socket_t *socks);

#endif /* HEADER_CURL_HOSTIP_H */







<
|

|



236
237
238
239
240
241
242

243
244
245
246
247
248
 */
void Curl_hostcache_clean(struct Curl_easy *data, struct Curl_hash *hash);

/*
 * Populate the cache with specified entries from CURLOPT_RESOLVE.
 */
CURLcode Curl_loadhostpairs(struct Curl_easy *data);

CURLcode Curl_resolv_check(struct Curl_easy *data,
                           struct Curl_dns_entry **dns);
int Curl_resolv_getsock(struct Curl_easy *data,
                        curl_socket_t *socks);

#endif /* HEADER_CURL_HOSTIP_H */
Changes to jni/curl/lib/hostip4.c.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2020, 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 https://curl.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







|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2021, 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 https://curl.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
57
58
59
60
61
62
63
64
65

66
67
68
69
70
71
72
#include "curl_memory.h"
#include "memdebug.h"

/*
 * Curl_ipvalid() checks what CURL_IPRESOLVE_* requirements that might've
 * been set and returns TRUE if they are OK.
 */
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 */
}








|

>







57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
#include "curl_memory.h"
#include "memdebug.h"

/*
 * Curl_ipvalid() checks what CURL_IPRESOLVE_* requirements that might've
 * been set and returns TRUE if they are OK.
 */
bool Curl_ipvalid(struct Curl_easy *data, struct connectdata *conn)
{
  (void)data;
  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 */
}

84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
 * 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.
 *
 */
struct Curl_addrinfo *Curl_getaddrinfo(struct connectdata *conn,
                                       const char *hostname,
                                       int port,
                                       int *waitp)
{
  struct 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)







|







|






|







85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
 * 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.
 *
 */
struct Curl_addrinfo *Curl_getaddrinfo(struct Curl_easy *data,
                                       const char *hostname,
                                       int port,
                                       int *waitp)
{
  struct Curl_addrinfo *ai = NULL;

#ifdef CURL_DISABLE_VERBOSE_STRINGS
  (void)data;
#endif

  *waitp = 0; /* synchronous response only */

  ai = Curl_ipv4_resolve_r(hostname, port);
  if(!ai)
    infof(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)
Changes to jni/curl/lib/hostip6.c.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2020, 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 https://curl.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







|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2021, 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 https://curl.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
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
#include "curl_printf.h"
#include "curl_memory.h"
#include "memdebug.h"

/*
 * Curl_ipv6works() returns TRUE if IPv6 seems to work.
 */
bool Curl_ipv6works(struct connectdata *conn)
{
  if(conn) {
    /* 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 */
    DEBUGASSERT(conn);
    DEBUGASSERT(conn->data);
    DEBUGASSERT(conn->data->multi);
    return conn->data->multi->ipv6_works;
  }
  else {
    int ipv6_works = -1;
    /* 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.
 */
bool Curl_ipvalid(struct connectdata *conn)
{
  if(conn->ip_version == CURL_IPRESOLVE_V6)
    return Curl_ipv6works(conn);

  return TRUE;
}

#if defined(CURLRES_SYNCH)

#ifdef DEBUG_ADDRINFO







|

|



|
|
<
|










|









|


|







58
59
60
61
62
63
64
65
66
67
68
69
70
71
72

73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
#include "curl_printf.h"
#include "curl_memory.h"
#include "memdebug.h"

/*
 * Curl_ipv6works() returns TRUE if IPv6 seems to work.
 */
bool Curl_ipv6works(struct Curl_easy *data)
{
  if(data) {
    /* 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 */
    DEBUGASSERT(data);
    DEBUGASSERT(data->multi);

    return data->multi->ipv6_works;
  }
  else {
    int ipv6_works = -1;
    /* 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;
      sclose(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.
 */
bool Curl_ipvalid(struct Curl_easy *data, struct connectdata *conn)
{
  if(conn->ip_version == CURL_IPRESOLVE_V6)
    return Curl_ipv6works(data);

  return TRUE;
}

#if defined(CURLRES_SYNCH)

#ifdef DEBUG_ADDRINFO
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
 * 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.
 */
struct Curl_addrinfo *Curl_getaddrinfo(struct connectdata *conn,
                                       const char *hostname,
                                       int port,
                                       int *waitp)
{
  struct addrinfo hints;
  struct Curl_addrinfo *res;
  int error;
  char sbuf[12];
  char *sbufptr = NULL;
#ifndef USE_RESOLVE_ON_IPS
  char addrbuf[128];
#endif
  int pf;
#if !defined(CURL_DISABLE_VERBOSE_STRINGS)
  struct Curl_easy *data = conn->data;
#endif

  *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(conn))
    /* 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->transport == TRNSPRT_TCP) ?
    SOCK_STREAM : SOCK_DGRAM;

#ifndef USE_RESOLVE_ON_IPS
  /*
   * The AI_NUMERICHOST must not be set to get synthesized IPv6 address from
   * an IPv4 address on iOS and Mac OS X.
   */







|













<
<
<




|











|





|







123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143



144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
 * 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.
 */
struct Curl_addrinfo *Curl_getaddrinfo(struct Curl_easy *data,
                                       const char *hostname,
                                       int port,
                                       int *waitp)
{
  struct addrinfo hints;
  struct Curl_addrinfo *res;
  int error;
  char sbuf[12];
  char *sbufptr = NULL;
#ifndef USE_RESOLVE_ON_IPS
  char addrbuf[128];
#endif
  int pf;




  *waitp = 0; /* synchronous response only */

  /* Check if a limited name resolve has been requested */
  switch(data->set.ipver) {
  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(data))
    /* The stack seems to be a non-IPv6 one */
    pf = PF_INET;

  memset(&hints, 0, sizeof(hints));
  hints.ai_family = pf;
  hints.ai_socktype = (data->conn->transport == TRNSPRT_TCP) ?
    SOCK_STREAM : SOCK_DGRAM;

#ifndef USE_RESOLVE_ON_IPS
  /*
   * The AI_NUMERICHOST must not be set to get synthesized IPv6 address from
   * an IPv4 address on iOS and Mac OS X.
   */
Changes to jni/curl/lib/hsts.c.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 2020, 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 https://curl.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







|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 2020 - 2021, 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 https://curl.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
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
  char *tempstore;
  unsigned char randsuffix[9];

  if(!h)
    /* no cache activated */
    return CURLE_OK;

  /* if not new name is given, use the one we stored from the load */
  if(!file && h->filename)
    file = h->filename;

  if((h->flags & CURLHSTS_READONLYFILE) || !file || !file[0])
    /* marked as read-only, no file or zero length file name */
    goto skipsave;








|







321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
  char *tempstore;
  unsigned char randsuffix[9];

  if(!h)
    /* no cache activated */
    return CURLE_OK;

  /* if no new name is given, use the one we stored from the load */
  if(!file && h->filename)
    file = h->filename;

  if((h->flags & CURLHSTS_READONLYFILE) || !file || !file[0])
    /* marked as read-only, no file or zero length file name */
    goto skipsave;

453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
}

/*
 * Load the HSTS cache from the given file. The text based line-oriented file
 * format is documented here:
 * https://github.com/curl/curl/wiki/HSTS
 *
 * This function only returns error on major problems that prevents hsts
 * handling to work completely. It will ignore individual syntactical errors
 * etc.
 */
static CURLcode hsts_load(struct hsts *h, const char *file)
{
  CURLcode result = CURLE_OK;
  char *line = NULL;







|







453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
}

/*
 * Load the HSTS cache from the given file. The text based line-oriented file
 * format is documented here:
 * https://github.com/curl/curl/wiki/HSTS
 *
 * This function only returns error on major problems that prevent hsts
 * handling to work completely. It will ignore individual syntactical errors
 * etc.
 */
static CURLcode hsts_load(struct hsts *h, const char *file)
{
  CURLcode result = CURLE_OK;
  char *line = NULL;
Changes to jni/curl/lib/http.c.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2020, 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 https://curl.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







|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2021, 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 https://curl.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
40
41
42
43
44
45
46




47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62

63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80

81
82
83
84
85
86
87
88
89
90
91

92
93
94
95
96
97
98
99
100
101

102
103
104
105
106

107
108
109
110
111
112
113
#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 "mime.h"
#include "progress.h"
#include "curl_base64.h"
#include "cookie.h"
#include "vauth/vauth.h"
#include "vtls/vtls.h"
#include "http_digest.h"
#include "http_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 "strcase.h"
#include "content_encoding.h"
#include "http_proxy.h"
#include "warnless.h"
#include "non-ascii.h"
#include "http2.h"
#include "connect.h"
#include "strdup.h"
#include "altsvc.h"
#include "hsts.h"


/* The last 3 #include files should be in this order */
#include "curl_printf.h"
#include "curl_memory.h"
#include "memdebug.h"

/*
 * Forward declarations.
 */

static int http_getsock_do(struct connectdata *conn,

                           curl_socket_t *socks);
static int http_should_fail(struct connectdata *conn);

#ifndef CURL_DISABLE_PROXY
static CURLcode add_haproxy_protocol_header(struct connectdata *conn);
#endif

#ifdef USE_SSL
static CURLcode https_connecting(struct connectdata *conn, bool *done);
static int https_getsock(struct connectdata *conn,

                         curl_socket_t *socks);
#else
#define https_connecting(x,y) CURLE_COULDNT_CONNECT
#endif
static CURLcode http_setup_conn(struct connectdata *conn);


/*
 * HTTP handler interface.
 */
const struct Curl_handler Curl_handler_http = {
  "HTTP",                               /* scheme */
  http_setup_conn,                      /* setup_connection */







>
>
>
>
















>


















>










|
>

|


|



|
|
>




|
>







40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
#ifdef HAVE_SYS_IOCTL_H
#include <sys/ioctl.h>
#endif

#ifdef HAVE_SYS_PARAM_H
#include <sys/param.h>
#endif

#ifdef USE_HYPER
#include <hyper.h>
#endif

#include "urldata.h"
#include <curl/curl.h>
#include "transfer.h"
#include "sendf.h"
#include "formdata.h"
#include "mime.h"
#include "progress.h"
#include "curl_base64.h"
#include "cookie.h"
#include "vauth/vauth.h"
#include "vtls/vtls.h"
#include "http_digest.h"
#include "http_ntlm.h"
#include "curl_ntlm_wb.h"
#include "http_negotiate.h"
#include "http_aws_sigv4.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 "strcase.h"
#include "content_encoding.h"
#include "http_proxy.h"
#include "warnless.h"
#include "non-ascii.h"
#include "http2.h"
#include "connect.h"
#include "strdup.h"
#include "altsvc.h"
#include "hsts.h"
#include "c-hyper.h"

/* The last 3 #include files should be in this order */
#include "curl_printf.h"
#include "curl_memory.h"
#include "memdebug.h"

/*
 * Forward declarations.
 */

static int http_getsock_do(struct Curl_easy *data,
                           struct connectdata *conn,
                           curl_socket_t *socks);
static bool http_should_fail(struct Curl_easy *data);

#ifndef CURL_DISABLE_PROXY
static CURLcode add_haproxy_protocol_header(struct Curl_easy *data);
#endif

#ifdef USE_SSL
static CURLcode https_connecting(struct Curl_easy *data, bool *done);
static int https_getsock(struct Curl_easy *data,
                         struct connectdata *conn,
                         curl_socket_t *socks);
#else
#define https_connecting(x,y) CURLE_COULDNT_CONNECT
#endif
static CURLcode http_setup_conn(struct Curl_easy *data,
                                struct connectdata *conn);

/*
 * HTTP handler interface.
 */
const struct Curl_handler Curl_handler_http = {
  "HTTP",                               /* scheme */
  http_setup_conn,                      /* setup_connection */
155
156
157
158
159
160
161
162

163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
  CURLPROTO_HTTPS,                      /* protocol */
  CURLPROTO_HTTP,                       /* family */
  PROTOPT_SSL | PROTOPT_CREDSPERREQUEST | PROTOPT_ALPN_NPN | /* flags */
  PROTOPT_USERPWDCTRL
};
#endif

static CURLcode http_setup_conn(struct connectdata *conn)

{
  /* allocate the HTTP-specific struct for the Curl_easy, only to survive
     during this request */
  struct HTTP *http;
  struct Curl_easy *data = conn->data;
  DEBUGASSERT(data->req.p.http == NULL);

  http = calloc(1, sizeof(struct HTTP));
  if(!http)
    return CURLE_OUT_OF_MEMORY;

  Curl_mime_initpart(&http->form, conn->data);
  data->req.p.http = http;

  if(data->set.httpversion == CURL_HTTP_VERSION_3) {
    if(conn->handler->flags & PROTOPT_SSL)
      /* Only go HTTP/3 directly on HTTPS URLs. It needs a UDP socket and does
         the QUIC dance. */
      conn->transport = TRNSPRT_QUIC;







|
>




<






|







164
165
166
167
168
169
170
171
172
173
174
175
176

177
178
179
180
181
182
183
184
185
186
187
188
189
190
  CURLPROTO_HTTPS,                      /* protocol */
  CURLPROTO_HTTP,                       /* family */
  PROTOPT_SSL | PROTOPT_CREDSPERREQUEST | PROTOPT_ALPN_NPN | /* flags */
  PROTOPT_USERPWDCTRL
};
#endif

static CURLcode http_setup_conn(struct Curl_easy *data,
                                struct connectdata *conn)
{
  /* allocate the HTTP-specific struct for the Curl_easy, only to survive
     during this request */
  struct HTTP *http;

  DEBUGASSERT(data->req.p.http == NULL);

  http = calloc(1, sizeof(struct HTTP));
  if(!http)
    return CURLE_OUT_OF_MEMORY;

  Curl_mime_initpart(&http->form, data);
  data->req.p.http = http;

  if(data->set.httpversion == CURL_HTTP_VERSION_3) {
    if(conn->handler->flags & PROTOPT_SSL)
      /* Only go HTTP/3 directly on HTTPS URLs. It needs a UDP socket and does
         the QUIC dance. */
      conn->transport = TRNSPRT_QUIC;
195
196
197
198
199
200
201
202
203
204
205
206

207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232

#ifndef CURL_DISABLE_PROXY
/*
 * 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 Curl_easy simply to
 * know if this is a proxy request or not, as it then might check a different
 * header list. Provide the header prefix without colon!.
 */
char *Curl_checkProxyheaders(const struct connectdata *conn,

                             const char *thisheader)
{
  struct curl_slist *head;
  size_t thislen = strlen(thisheader);
  struct Curl_easy *data = conn->data;

  for(head = (conn->bits.proxy && data->set.sep_headers) ?
        data->set.proxyheaders : data->set.headers;
      head; head = head->next) {
    if(strncasecompare(head->data, thisheader, thislen) &&
       Curl_headersep(head->data[thislen]))
      return head->data;
  }

  return NULL;
}
#else
/* disabled */
#define Curl_checkProxyheaders(x,y) NULL
#endif

/*
 * 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.







|
|
|

|
>




<













|







204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220

221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241

#ifndef CURL_DISABLE_PROXY
/*
 * 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 to see if this is a proxy request or
 * not, as it then might check a different header list. Provide the header
 * prefix without colon!
 */
char *Curl_checkProxyheaders(struct Curl_easy *data,
                             const struct connectdata *conn,
                             const char *thisheader)
{
  struct curl_slist *head;
  size_t thislen = strlen(thisheader);


  for(head = (conn->bits.proxy && data->set.sep_headers) ?
        data->set.proxyheaders : data->set.headers;
      head; head = head->next) {
    if(strncasecompare(head->data, thisheader, thislen) &&
       Curl_headersep(head->data[thislen]))
      return head->data;
  }

  return NULL;
}
#else
/* disabled */
#define Curl_checkProxyheaders(x,y,z) NULL
#endif

/*
 * 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.
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
#ifndef CURL_DISABLE_HTTP_AUTH
/*
 * 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 Curl_easy *data = conn->data;
  char **userp;
  const char *user;
  const char *pwd;
  CURLcode result;
  char *out;

  if(proxy) {







|



|







290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
#ifndef CURL_DISABLE_HTTP_AUTH
/*
 * http_output_basic() sets up an Authorization: header (or the proxy version)
 * for HTTP Basic authentication.
 *
 * Returns CURLcode.
 */
static CURLcode http_output_basic(struct Curl_easy *data, bool proxy)
{
  size_t size = 0;
  char *authorization = NULL;
  struct connectdata *conn = data->conn;
  char **userp;
  const char *user;
  const char *pwd;
  CURLcode result;
  char *out;

  if(proxy) {
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364

/*
 * http_output_bearer() sets up an Authorization: header
 * for HTTP Bearer authentication.
 *
 * Returns CURLcode.
 */
static CURLcode http_output_bearer(struct connectdata *conn)
{
  char **userp;
  CURLcode result = CURLE_OK;
  struct Curl_easy *data = conn->data;

  userp = &data->state.aptr.userpwd;
  free(*userp);
  *userp = aprintf("Authorization: Bearer %s\r\n",
                   conn->data->set.str[STRING_BEARER]);

  if(!*userp) {
    result = CURLE_OUT_OF_MEMORY;
    goto fail;
  }

  fail:







|



<




|







350
351
352
353
354
355
356
357
358
359
360

361
362
363
364
365
366
367
368
369
370
371
372

/*
 * http_output_bearer() sets up an Authorization: header
 * for HTTP Bearer authentication.
 *
 * Returns CURLcode.
 */
static CURLcode http_output_bearer(struct Curl_easy *data)
{
  char **userp;
  CURLcode result = CURLE_OK;


  userp = &data->state.aptr.userpwd;
  free(*userp);
  *userp = aprintf("Authorization: Bearer %s\r\n",
                   data->set.str[STRING_BEARER]);

  if(!*userp) {
    result = CURLE_OUT_OF_MEMORY;
    goto fail;
  }

  fail:
389
390
391
392
393
394
395


396
397
398
399
400
401
402
    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;







>
>







397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
    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 if(avail & CURLAUTH_AWS_SIGV4)
    pick->picked = CURLAUTH_AWS_SIGV4;
  else {
    pick->picked = CURLAUTH_PICKNONE; /* we select to use nothing */
    picked = FALSE;
  }
  pick->avail = CURLAUTH_NONE; /* clear it here */

  return picked;
421
422
423
424
425
426
427
428

429
430
431
432
433
434
435
436
437
 *     }
 *     else {
 *       rewind internally so that the operation can restart fine
 *     }
 *   }
 * }
 */
static CURLcode http_perhapsrewind(struct connectdata *conn)

{
  struct Curl_easy *data = conn->data;
  struct HTTP *http = data->req.p.http;
  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 */







|
>

<







431
432
433
434
435
436
437
438
439
440

441
442
443
444
445
446
447
 *     }
 *     else {
 *       rewind internally so that the operation can restart fine
 *     }
 *   }
 * }
 */
static CURLcode http_perhapsrewind(struct Curl_easy *data,
                                   struct connectdata *conn)
{

  struct HTTP *http = data->req.p.http;
  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 */
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569

    /* 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.
 */

CURLcode Curl_http_auth_act(struct connectdata *conn)
{
  struct Curl_easy *data = conn->data;
  bool pickhost = FALSE;
  bool pickproxy = FALSE;
  CURLcode result = CURLE_OK;
  unsigned long authmask = ~0ul;

  if(!data->set.str[STRING_BEARER])
    authmask &= (unsigned long)~CURLAUTH_BEARER;







|











|

|







551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579

    /* 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(data);

  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.
 */

CURLcode Curl_http_auth_act(struct Curl_easy *data)
{
  struct connectdata *conn = data->conn;
  bool pickhost = FALSE;
  bool pickproxy = FALSE;
  CURLcode result = CURLE_OK;
  unsigned long authmask = ~0ul;

  if(!data->set.str[STRING_BEARER])
    authmask &= (unsigned long)~CURLAUTH_BEARER;
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
    pickhost = pickoneauth(&data->state.authhost, authmask);
    if(!pickhost)
      data->state.authproblem = TRUE;
    if(data->state.authhost.picked == CURLAUTH_NTLM &&
       conn->httpversion > 11) {
      infof(data, "Forcing HTTP/1.1 for NTLM");
      connclose(conn, "Force HTTP/1.1 connection");
      conn->data->set.httpversion = CURL_HTTP_VERSION_1_1;
    }
  }
#ifndef CURL_DISABLE_PROXY
  if(conn->bits.proxy_user_passwd &&
     ((data->req.httpcode == 407) ||
      (conn->bits.authneg && data->req.httpcode < 300))) {
    pickproxy = pickoneauth(&data->state.authproxy,
                            authmask & ~CURLAUTH_BEARER);
    if(!pickproxy)
      data->state.authproblem = TRUE;
  }
#endif

  if(pickhost || pickproxy) {
    if((data->state.httpreq != HTTPREQ_GET) &&
       (data->state.httpreq != HTTPREQ_HEAD) &&
       !conn->bits.rewindaftersend) {
      result = http_perhapsrewind(conn);
      if(result)
        return result;
    }
    /* 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);







|

















|







591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
    pickhost = pickoneauth(&data->state.authhost, authmask);
    if(!pickhost)
      data->state.authproblem = TRUE;
    if(data->state.authhost.picked == CURLAUTH_NTLM &&
       conn->httpversion > 11) {
      infof(data, "Forcing HTTP/1.1 for NTLM");
      connclose(conn, "Force HTTP/1.1 connection");
      data->set.httpversion = CURL_HTTP_VERSION_1_1;
    }
  }
#ifndef CURL_DISABLE_PROXY
  if(conn->bits.proxy_user_passwd &&
     ((data->req.httpcode == 407) ||
      (conn->bits.authneg && data->req.httpcode < 300))) {
    pickproxy = pickoneauth(&data->state.authproxy,
                            authmask & ~CURLAUTH_BEARER);
    if(!pickproxy)
      data->state.authproblem = TRUE;
  }
#endif

  if(pickhost || pickproxy) {
    if((data->state.httpreq != HTTPREQ_GET) &&
       (data->state.httpreq != HTTPREQ_HEAD) &&
       !conn->bits.rewindaftersend) {
      result = http_perhapsrewind(data, conn);
      if(result)
        return result;
    }
    /* 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);
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648

649
650
651
652
653
654
655
656
657
658
659
660
661






662


663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693

694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
       (data->state.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;
}

#ifndef CURL_DISABLE_HTTP_AUTH
/*
 * 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;
  struct Curl_easy *data = conn->data;

#ifdef CURL_DISABLE_CRYPTO_AUTH
  (void)request;
  (void)path;
#endif









#ifdef USE_SPNEGO
  if(authstatus->picked == CURLAUTH_NEGOTIATE) {
    auth = "Negotiate";
    result = Curl_output_negotiate(conn, proxy);
    if(result)
      return result;
  }
  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(
#ifndef CURL_DISABLE_PROXY
      (proxy && conn->bits.proxy_user_passwd &&
       !Curl_checkProxyheaders(conn, "Proxy-authorization")) ||
#endif
      (!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(authstatus->picked == CURLAUTH_BEARER) {
    /* Bearer */
    if((!proxy && data->set.str[STRING_BEARER] &&
        !Curl_checkheaders(conn, "Authorization:"))) {
      auth = "Bearer";
      result = http_output_bearer(conn);
      if(result)
        return result;
    }

    /* NOTE: this function should set 'done' TRUE, as the other auth
       functions work that way */
    authstatus->done = TRUE;







|














|
>







<





>
>
>
>
>
>
|
>
>



|








|








|








|
>













|


|

|











|

|







636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666

667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
       (data->state.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(data)) {
    failf(data, "The requested URL returned error: %d",
          data->req.httpcode);
    result = CURLE_HTTP_RETURNED_ERROR;
  }

  return result;
}

#ifndef CURL_DISABLE_HTTP_AUTH
/*
 * 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 Curl_easy *data,
                    struct connectdata *conn,
                    struct auth *authstatus,
                    const char *request,
                    const char *path,
                    bool proxy)
{
  const char *auth = NULL;
  CURLcode result = CURLE_OK;


#ifdef CURL_DISABLE_CRYPTO_AUTH
  (void)request;
  (void)path;
#endif
#ifndef CURL_DISABLE_CRYPTO_AUTH
  if(authstatus->picked == CURLAUTH_AWS_SIGV4) {
    auth = "AWS_SIGV4";
    result = Curl_output_aws_sigv4(data, proxy);
    if(result)
      return result;
  }
  else
#endif
#ifdef USE_SPNEGO
  if(authstatus->picked == CURLAUTH_NEGOTIATE) {
    auth = "Negotiate";
    result = Curl_output_negotiate(data, conn, proxy);
    if(result)
      return result;
  }
  else
#endif
#ifdef USE_NTLM
  if(authstatus->picked == CURLAUTH_NTLM) {
    auth = "NTLM";
    result = Curl_output_ntlm(data, 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(data, conn, proxy);
    if(result)
      return result;
  }
  else
#endif
#ifndef CURL_DISABLE_CRYPTO_AUTH
  if(authstatus->picked == CURLAUTH_DIGEST) {
    auth = "Digest";
    result = Curl_output_digest(data,
                                conn,
                                proxy,
                                (const unsigned char *)request,
                                (const unsigned char *)path);
    if(result)
      return result;
  }
  else
#endif
  if(authstatus->picked == CURLAUTH_BASIC) {
    /* Basic */
    if(
#ifndef CURL_DISABLE_PROXY
      (proxy && conn->bits.proxy_user_passwd &&
       !Curl_checkProxyheaders(data, conn, "Proxy-authorization")) ||
#endif
      (!proxy && conn->bits.user_passwd &&
       !Curl_checkheaders(data, "Authorization"))) {
      auth = "Basic";
      result = http_output_basic(data, proxy);
      if(result)
        return result;
    }

    /* NOTE: this function should set 'done' TRUE, as the other auth
       functions work that way */
    authstatus->done = TRUE;
  }
  if(authstatus->picked == CURLAUTH_BEARER) {
    /* Bearer */
    if((!proxy && data->set.str[STRING_BEARER] &&
        !Curl_checkheaders(data, "Authorization:"))) {
      auth = "Bearer";
      result = http_output_bearer(data);
      if(result)
        return result;
    }

    /* NOTE: this function should set 'done' TRUE, as the other auth
       functions work that way */
    authstatus->done = TRUE;
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769

770

771
772
773
774
775
776
777
778
779
780
781
782
783

  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; should include query part
 * @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 Curl_easy *data = conn->data;
  struct auth *authhost;
  struct auth *authproxy;

  DEBUGASSERT(data);

  authhost = &data->state.authhost;
  authproxy = &data->state.authproxy;







|











|
>

>





<







769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796

797
798
799
800
801
802
803

  return CURLE_OK;
}

/**
 * Curl_http_output_auth() setups the authentication headers for the
 * host/proxy and the correct authentication
 * method. 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; should include query part
 * @param proxytunnel boolean if this is the request setting up a "proxy
 * tunnel"
 *
 * @returns CURLcode
 */
CURLcode
Curl_http_output_auth(struct Curl_easy *data,
                      struct connectdata *conn,
                      const char *request,
                      Curl_HttpReq httpreq,
                      const char *path,
                      bool proxytunnel) /* TRUE if this is the request setting
                                           up the proxy tunnel */
{
  CURLcode result = CURLE_OK;

  struct auth *authhost;
  struct auth *authproxy;

  DEBUGASSERT(data);

  authhost = &data->state.authhost;
  authproxy = &data->state.authproxy;
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835











836
837
838
839
840
841
842
       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 == (bit)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.allow_auth_to_other_hosts ||
     strcasecompare(data->state.first_host, conn->host.name)) {
    result = output_auth_headers(conn, authhost, request, path, FALSE);
  }
  else
    authhost->done = TRUE;












  return result;
}

#else
/* when disabled */
CURLcode







|


















|



>
>
>
>
>
>
>
>
>
>
>







826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
       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 == (bit)proxytunnel)) {
    result = output_auth_headers(data, 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.allow_auth_to_other_hosts ||
     strcasecompare(data->state.first_host, conn->host.name)) {
    result = output_auth_headers(data, conn, authhost, request, path, FALSE);
  }
  else
    authhost->done = TRUE;

  if(((authhost->multipass && !authhost->done) ||
      (authproxy->multipass && !authproxy->done)) &&
     (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;

  return result;
}

#else
/* when disabled */
CURLcode
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875


876
877
878
879
880
881
882

/*
 * 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 Curl_easy *data = conn->data;

#ifdef USE_SPNEGO
  curlnegotiate *negstate = proxy ? &conn->proxy_negotiate_state :
                                    &conn->http_negotiate_state;
#endif
  unsigned long *availp;
  struct auth *authp;



  if(proxy) {
    availp = &data->info.proxyauthavail;
    authp = &data->state.authproxy;
  }
  else {
    availp = &data->info.httpauthavail;







|





<
|






>
>







886
887
888
889
890
891
892
893
894
895
896
897
898

899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914

/*
 * 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 Curl_easy *data, bool proxy,
                              const char *auth) /* the first non-space */
{
  /*
   * This resource requires authentication
   */

  struct connectdata *conn = data->conn;
#ifdef USE_SPNEGO
  curlnegotiate *negstate = proxy ? &conn->proxy_negotiate_state :
                                    &conn->http_negotiate_state;
#endif
  unsigned long *availp;
  struct auth *authp;

  (void) conn; /* In case conditionals make it unused. */

  if(proxy) {
    availp = &data->info.proxyauthavail;
    authp = &data->state.authproxy;
  }
  else {
    availp = &data->info.httpauthavail;
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
    if(checkprefix("Negotiate", auth)) {
      if((authp->avail & CURLAUTH_NEGOTIATE) ||
         Curl_auth_is_spnego_supported()) {
        *availp |= CURLAUTH_NEGOTIATE;
        authp->avail |= CURLAUTH_NEGOTIATE;

        if(authp->picked == CURLAUTH_NEGOTIATE) {
          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 */







|







936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
    if(checkprefix("Negotiate", auth)) {
      if((authp->avail & CURLAUTH_NEGOTIATE) ||
         Curl_auth_is_spnego_supported()) {
        *availp |= CURLAUTH_NEGOTIATE;
        authp->avail |= CURLAUTH_NEGOTIATE;

        if(authp->picked == CURLAUTH_NEGOTIATE) {
          CURLcode result = Curl_input_negotiate(data, 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 */
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
           Curl_auth_is_ntlm_supported()) {
          *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;

                result = Curl_input_ntlm_wb(conn, proxy, auth);
                if(result) {
                  infof(data, "Authentication problem. Ignoring this.\n");
                  data->state.authproblem = TRUE;
                }
              }
#endif
            }







|









|







965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
           Curl_auth_is_ntlm_supported()) {
          *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(data, 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;

                result = Curl_input_ntlm_wb(data, conn, proxy, auth);
                if(result) {
                  infof(data, "Authentication problem. Ignoring this.\n");
                  data->state.authproblem = TRUE;
                }
              }
#endif
            }
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
            *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 going to use
             * Digest */
            result = Curl_input_digest(conn, proxy, auth);
            if(result) {
              infof(data, "Authentication problem. Ignoring this.\n");
              data->state.authproblem = TRUE;
            }
          }
        }
        else







|







1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
            *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 going to use
             * Digest */
            result = Curl_input_digest(data, proxy, auth);
            if(result) {
              infof(data, "Authentication problem. Ignoring this.\n");
              data->state.authproblem = TRUE;
            }
          }
        }
        else
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073

/**
 * 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 Curl_easy *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));

  /*







|

|

|

<

<
|
<
|








|





|






|







1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070

1071

1072

1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102

/**
 * 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 FALSE communications should continue
 *
 * @retval TRUE communications should not continue
 */
static bool http_should_fail(struct Curl_easy *data)
{

  int httpcode;

  DEBUGASSERT(data);

  DEBUGASSERT(data->conn);

  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 FALSE;

  /*
  ** Any code < 400 is never terminal.
  */
  if(httpcode < 400)
    return FALSE;

  /*
  ** Any code >= 400 that's not 401 or 407 is always
  ** a terminal error
  */
  if((httpcode != 401) && (httpcode != 407))
    return TRUE;

  /*
  ** All we have left to deal with is 401 and 407
  */
  DEBUGASSERT((httpcode == 401) || (httpcode == 407));

  /*
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100

1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
  ** 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;
#ifndef CURL_DISABLE_PROXY
  if((httpcode == 407) && !conn->bits.proxy_user_passwd)
    return TRUE;
#endif

  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.p.http;
  size_t fullsize = size * nitems;

  if(!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->data->state.fread_func = http->backup.fread_func;
      conn->data->state.in = http->backup.fread_in;

      http->sending++; /* move one step up */

      http->backup.postsize = 0;
    }
    else
      http->postsize = 0;







|


|






>













|
|







|









|
|







1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
  ** 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) && !data->conn->bits.user_passwd)
    return TRUE;
#ifndef CURL_DISABLE_PROXY
  if((httpcode == 407) && !data->conn->bits.proxy_user_passwd)
    return TRUE;
#endif

  return data->state.authproblem;
}

#ifndef USE_HYPER
/*
 * 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 Curl_easy *data = (struct Curl_easy *)userp;
  struct HTTP *http = data->req.p.http;
  size_t fullsize = size * nitems;

  if(!http->postsize)
    /* nothing to return */
    return 0;

  /* make sure that a HTTP request is never sent away chunked! */
  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;
      data->state.fread_func = http->backup.fread_func;
      data->state.in = http->backup.fread_in;

      http->sending++; /* move one step up */

      http->backup.postsize = 0;
    }
    else
      http->postsize = 0;
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
/*
 * Curl_buffer_send() sends a header buffer and frees all associated
 * memory.  Body data may be appended to the header data if desired.
 *
 * Returns CURLcode
 */
CURLcode Curl_buffer_send(struct dynbuf *in,
                          struct connectdata *conn,
                          /* add the number of sent bytes to this
                             counter */
                          curl_off_t *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 Curl_easy *data = conn->data;
  struct HTTP *http = data->req.p.http;
  size_t sendsize;
  curl_socket_t sockfd;
  size_t headersize;

  DEBUGASSERT(socketindex <= SECONDARYSOCKET);








|











|







1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
/*
 * Curl_buffer_send() sends a header buffer and frees all associated
 * memory.  Body data may be appended to the header data if desired.
 *
 * Returns CURLcode
 */
CURLcode Curl_buffer_send(struct dynbuf *in,
                          struct Curl_easy *data,
                          /* add the number of sent bytes to this
                             counter */
                          curl_off_t *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 connectdata *conn = data->conn;
  struct HTTP *http = data->req.p.http;
  size_t sendsize;
  curl_socket_t sockfd;
  size_t headersize;

  DEBUGASSERT(socketindex <= SECONDARYSOCKET);

1225
1226
1227
1228
1229
1230
1231
1232


1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
      return result;
    }
    memcpy(data->state.ulbuf, ptr, sendsize);
    ptr = data->state.ulbuf;
  }
  else {
#ifdef CURLDEBUG
    /* Allow debug builds override this logic to force short initial sends */


    char *p = getenv("CURL_SMALLREQSEND");
    if(p) {
      size_t altsize = (size_t)strtoul(p, NULL, 10);
      if(altsize)
        sendsize = CURLMIN(size, altsize);
      else
        sendsize = size;
    }
    else
#endif
    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).
     */







|
>
>













|







1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
      return result;
    }
    memcpy(data->state.ulbuf, ptr, sendsize);
    ptr = data->state.ulbuf;
  }
  else {
#ifdef CURLDEBUG
    /* Allow debug builds to override this logic to force short initial
       sends
     */
    char *p = getenv("CURL_SMALLREQSEND");
    if(p) {
      size_t altsize = (size_t)strtoul(p, NULL, 10);
      if(altsize)
        sendsize = CURLMIN(size, altsize);
      else
        sendsize = size;
    }
    else
#endif
    sendsize = size;
  }

  result = Curl_write(data, 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).
     */
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296



1297
1298
1299
1300
1301
1302
1303
        http->backup.fread_func = data->state.fread_func;
        http->backup.fread_in = data->state.in;
        http->backup.postdata = http->postdata;
        http->backup.postsize = http->postsize;

        /* set the new pointers for the request-sending */
        data->state.fread_func = (curl_read_callback)readmoredata;
        data->state.in = (void *)conn;
        http->postdata = ptr;
        http->postsize = (curl_off_t)size;




        http->send_buffer = *in; /* copy the whole struct */
        http->sending = HTTPSEND_REQUEST;

        return CURLE_OK;
      }
      http->sending = HTTPSEND_BODY;
      /* the full buffer was sent, clean up and return */







|



>
>
>







1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
        http->backup.fread_func = data->state.fread_func;
        http->backup.fread_in = data->state.in;
        http->backup.postdata = http->postdata;
        http->backup.postsize = http->postsize;

        /* set the new pointers for the request-sending */
        data->state.fread_func = (curl_read_callback)readmoredata;
        data->state.in = (void *)data;
        http->postdata = ptr;
        http->postsize = (curl_off_t)size;

        /* this much data is remaining header: */
        data->req.pendingheader = headersize - headlen;

        http->send_buffer = *in; /* copy the whole struct */
        http->sending = HTTPSEND_REQUEST;

        return CURLE_OK;
      }
      http->sending = HTTPSEND_BODY;
      /* the full buffer was sent, clean up and return */
1312
1313
1314
1315
1316
1317
1318


1319
1320


1321
1322
1323
1324
1325
1326
1327
           This needs FIXing.
        */
        return CURLE_SEND_ERROR;
    }
  }
  Curl_dyn_free(in);



  return result;
}



/* end of the add_buffer functions */
/* ------------------------------------------------------------------------- */



/*







>
>


>
>







1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
           This needs FIXing.
        */
        return CURLE_SEND_ERROR;
    }
  }
  Curl_dyn_free(in);

  /* no remaining header data */
  data->req.pendingheader = 0;
  return result;
}

#endif

/* end of the add_buffer functions */
/* ------------------------------------------------------------------------- */



/*
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388

1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434

1435
1436
1437

1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448

1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483

1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501

1502
1503

1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539

1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554


1555
1556
1557
1558
1559
1560
1561
  return FALSE; /* no match */
}

/*
 * Curl_http_connect() performs HTTP stuff to do at connect-time, called from
 * the generic Curl_connect().
 */
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");

#ifndef CURL_DISABLE_PROXY
  /* the CONNECT procedure might not have been completed */
  result = Curl_proxy_connect(conn, FIRSTSOCKET);
  if(result)
    return result;

  if(conn->bits.proxy_connect_closed)
    /* this is not an error, just part of the connection negotiation */
    return CURLE_OK;

  if(CONNECT_FIRSTSOCKET_PROXY_SSL())
    return CURLE_OK; /* wait for HTTPS proxy SSL initialization to complete */

  if(Curl_connect_ongoing(conn))
    /* nothing else to do except wait right now - we're not done here. */
    return CURLE_OK;

  if(conn->data->set.haproxyprotocol) {
    /* add HAProxy PROXY protocol header */
    result = add_haproxy_protocol_header(conn);
    if(result)
      return result;
  }
#endif

  if(conn->given->protocol & CURLPROTO_HTTPS) {
    /* 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)
{
  /* write mode */

  socks[0] = conn->sock[FIRSTSOCKET];
  return GETSOCK_WRITESOCK(0);
}

#ifndef CURL_DISABLE_PROXY
static CURLcode add_haproxy_protocol_header(struct connectdata *conn)
{
  char proxy_header[128];
  struct dynbuf req;
  CURLcode result;
  char tcp_version[5];


  /* Emit the correct prefix for IPv6 */
  if(conn->bits.ipv6) {
    strcpy(tcp_version, "TCP6");
  }
  else {
    strcpy(tcp_version, "TCP4");
  }

  msnprintf(proxy_header,
            sizeof(proxy_header),
            "PROXY %s %s %s %li %li\r\n",
            tcp_version,
            conn->data->info.conn_local_ip,
            conn->data->info.conn_primary_ip,
            conn->data->info.conn_local_port,
            conn->data->info.conn_primary_port);

  Curl_dyn_init(&req, DYN_HAXPROXY);

  result = Curl_dyn_add(&req, proxy_header);
  if(result)
    return result;

  result = Curl_buffer_send(&req, conn, &conn->data->info.request_size,
                            0, FIRSTSOCKET);

  return result;
}
#endif

#ifdef USE_SSL
static CURLcode https_connecting(struct connectdata *conn, bool *done)
{
  CURLcode result;

  DEBUGASSERT((conn) && (conn->handler->flags & PROTOPT_SSL));

#ifdef ENABLE_QUIC
  if(conn->transport == TRNSPRT_QUIC) {
    *done = TRUE;
    return CURLE_OK;
  }
#endif

  /* perform SSL initialization for this socket */
  result = Curl_ssl_connect_nonblocking(conn, FIRSTSOCKET, done);
  if(result)
    connclose(conn, "Failed HTTPS connection");

  return result;
}

static int https_getsock(struct connectdata *conn,

                         curl_socket_t *socks)
{

  if(conn->handler->flags & PROTOPT_SSL)
    return Curl_ssl_getsock(conn, socks);
  return GETSOCK_BLANK;
}
#endif /* USE_SSL */

/*
 * Curl_http_done() gets called after a single HTTP request has been
 * performed.
 */

CURLcode Curl_http_done(struct connectdata *conn,
                        CURLcode status, bool premature)
{
  struct Curl_easy *data = conn->data;
  struct HTTP *http = data->req.p.http;

  /* Clear multipass flag. If authentication isn't done yet, then it will get
   * a chance to be set back to true when we output the next auth header */
  data->state.authhost.multipass = FALSE;
  data->state.authproxy.multipass = FALSE;

  Curl_unencode_cleanup(conn);

  /* set the proper values (possibly modified on POST) */
  conn->seek_func = data->set.seek_func; /* restore */
  conn->seek_client = data->set.seek_client; /* restore */

  if(!http)
    return CURLE_OK;

  Curl_dyn_free(&http->send_buffer);
  Curl_http2_done(data, premature);
  Curl_quic_done(data, premature);
  Curl_mime_cleanpart(&http->form);
  Curl_dyn_reset(&data->state.headerb);


  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 &&
     (data->req.bytecount +
      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;
}

/*







|


>







|














|

|







|












|
>



>





|





>


|










|
|
|
|







|







|


>
|









|






|
>


>











|


|







|













>















>
>







1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
  return FALSE; /* no match */
}

/*
 * Curl_http_connect() performs HTTP stuff to do at connect-time, called from
 * the generic Curl_connect().
 */
CURLcode Curl_http_connect(struct Curl_easy *data, bool *done)
{
  CURLcode result;
  struct connectdata *conn = data->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, "HTTP default");

#ifndef CURL_DISABLE_PROXY
  /* the CONNECT procedure might not have been completed */
  result = Curl_proxy_connect(data, FIRSTSOCKET);
  if(result)
    return result;

  if(conn->bits.proxy_connect_closed)
    /* this is not an error, just part of the connection negotiation */
    return CURLE_OK;

  if(CONNECT_FIRSTSOCKET_PROXY_SSL())
    return CURLE_OK; /* wait for HTTPS proxy SSL initialization to complete */

  if(Curl_connect_ongoing(conn))
    /* nothing else to do except wait right now - we're not done here. */
    return CURLE_OK;

  if(data->set.haproxyprotocol) {
    /* add HAProxy PROXY protocol header */
    result = add_haproxy_protocol_header(data);
    if(result)
      return result;
  }
#endif

  if(conn->given->protocol & CURLPROTO_HTTPS) {
    /* perform SSL initialization */
    result = https_connecting(data, 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 Curl_easy *data,
                           struct connectdata *conn,
                           curl_socket_t *socks)
{
  /* write mode */
  (void)data;
  socks[0] = conn->sock[FIRSTSOCKET];
  return GETSOCK_WRITESOCK(0);
}

#ifndef CURL_DISABLE_PROXY
static CURLcode add_haproxy_protocol_header(struct Curl_easy *data)
{
  char proxy_header[128];
  struct dynbuf req;
  CURLcode result;
  char tcp_version[5];
  DEBUGASSERT(data->conn);

  /* Emit the correct prefix for IPv6 */
  if(data->conn->bits.ipv6) {
    strcpy(tcp_version, "TCP6");
  }
  else {
    strcpy(tcp_version, "TCP4");
  }

  msnprintf(proxy_header,
            sizeof(proxy_header),
            "PROXY %s %s %s %li %li\r\n",
            tcp_version,
            data->info.conn_local_ip,
            data->info.conn_primary_ip,
            data->info.conn_local_port,
            data->info.conn_primary_port);

  Curl_dyn_init(&req, DYN_HAXPROXY);

  result = Curl_dyn_add(&req, proxy_header);
  if(result)
    return result;

  result = Curl_buffer_send(&req, data, &data->info.request_size,
                            0, FIRSTSOCKET);

  return result;
}
#endif

#ifdef USE_SSL
static CURLcode https_connecting(struct Curl_easy *data, bool *done)
{
  CURLcode result;
  struct connectdata *conn = data->conn;
  DEBUGASSERT((data) && (data->conn->handler->flags & PROTOPT_SSL));

#ifdef ENABLE_QUIC
  if(conn->transport == TRNSPRT_QUIC) {
    *done = TRUE;
    return CURLE_OK;
  }
#endif

  /* perform SSL initialization for this socket */
  result = Curl_ssl_connect_nonblocking(data, conn, FIRSTSOCKET, done);
  if(result)
    connclose(conn, "Failed HTTPS connection");

  return result;
}

static int https_getsock(struct Curl_easy *data,
                         struct connectdata *conn,
                         curl_socket_t *socks)
{
  (void)data;
  if(conn->handler->flags & PROTOPT_SSL)
    return Curl_ssl_getsock(conn, socks);
  return GETSOCK_BLANK;
}
#endif /* USE_SSL */

/*
 * Curl_http_done() gets called after a single HTTP request has been
 * performed.
 */

CURLcode Curl_http_done(struct Curl_easy *data,
                        CURLcode status, bool premature)
{
  struct connectdata *conn = data->conn;
  struct HTTP *http = data->req.p.http;

  /* Clear multipass flag. If authentication isn't done yet, then it will get
   * a chance to be set back to true when we output the next auth header */
  data->state.authhost.multipass = FALSE;
  data->state.authproxy.multipass = FALSE;

  Curl_unencode_cleanup(data);

  /* set the proper values (possibly modified on POST) */
  conn->seek_func = data->set.seek_func; /* restore */
  conn->seek_client = data->set.seek_client; /* restore */

  if(!http)
    return CURLE_OK;

  Curl_dyn_free(&http->send_buffer);
  Curl_http2_done(data, premature);
  Curl_quic_done(data, premature);
  Curl_mime_cleanpart(&http->form);
  Curl_dyn_reset(&data->state.headerb);
  Curl_hyper_done(data);

  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 &&
     (data->req.bytecount +
      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");
    /* Mark it as closed to avoid the "left intact" message */
    streamclose(conn, "Empty reply from server");
    return CURLE_GOT_NOTHING;
  }

  return CURLE_OK;
}

/*
1575
1576
1577
1578
1579
1580
1581

1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600

1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
  if((data->set.httpversion == CURL_HTTP_VERSION_1_0) &&
     (conn->httpversion <= 10))
    return FALSE;
  return ((data->set.httpversion == CURL_HTTP_VERSION_NONE) ||
          (data->set.httpversion >= CURL_HTTP_VERSION_1_1));
}


static const char *get_http_string(const struct Curl_easy *data,
                                   const struct connectdata *conn)
{
#ifdef ENABLE_QUIC
  if((data->set.httpversion == CURL_HTTP_VERSION_3) ||
     (conn->httpversion == 30))
    return "3";
#endif

#ifdef USE_NGHTTP2
  if(conn->proto.httpc.h2)
    return "2";
#endif

  if(use_http_1_1plus(data, conn))
    return "1.1";

  return "1.0";
}


/* check and possibly add an Expect: header */
static CURLcode expect100(struct Curl_easy *data,
                          struct connectdata *conn,
                          struct dynbuf *req)
{
  CURLcode result = CURLE_OK;
  data->state.expect100header = FALSE; /* default to false unless it is set
                                          to TRUE below */
  if(!data->state.disableexpect && 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) */
    const char *ptr = Curl_checkheaders(conn, "Expect");
    if(ptr) {
      data->state.expect100header =
        Curl_compareheader(ptr, "Expect:", "100-continue");
    }
    else {
      result = Curl_dyn_add(req, "Expect: 100-continue\r\n");
      if(!result)







>



















>














|







1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
  if((data->set.httpversion == CURL_HTTP_VERSION_1_0) &&
     (conn->httpversion <= 10))
    return FALSE;
  return ((data->set.httpversion == CURL_HTTP_VERSION_NONE) ||
          (data->set.httpversion >= CURL_HTTP_VERSION_1_1));
}

#ifndef USE_HYPER
static const char *get_http_string(const struct Curl_easy *data,
                                   const struct connectdata *conn)
{
#ifdef ENABLE_QUIC
  if((data->set.httpversion == CURL_HTTP_VERSION_3) ||
     (conn->httpversion == 30))
    return "3";
#endif

#ifdef USE_NGHTTP2
  if(conn->proto.httpc.h2)
    return "2";
#endif

  if(use_http_1_1plus(data, conn))
    return "1.1";

  return "1.0";
}
#endif

/* check and possibly add an Expect: header */
static CURLcode expect100(struct Curl_easy *data,
                          struct connectdata *conn,
                          struct dynbuf *req)
{
  CURLcode result = CURLE_OK;
  data->state.expect100header = FALSE; /* default to false unless it is set
                                          to TRUE below */
  if(!data->state.disableexpect && 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) */
    const char *ptr = Curl_checkheaders(data, "Expect");
    if(ptr) {
      data->state.expect100header =
        Curl_compareheader(ptr, "Expect:", "100-continue");
    }
    else {
      result = Curl_dyn_add(req, "Expect: 100-continue\r\n");
      if(!result)
1674
1675
1676
1677
1678
1679
1680
1681
1682

1683




1684

1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
      infof(handle, "Malformatted trailing header ! Skipping trailer.");
    trailers = trailers->next;
  }
  result = Curl_dyn_add(b, endofline_network);
  return result;
}

CURLcode Curl_add_custom_headers(struct connectdata *conn,
                                 bool is_connect,

                                 struct dynbuf *req)




{

  char *ptr;
  struct curl_slist *h[2];
  struct curl_slist *headers;
  int numlists = 1; /* by default */
  struct Curl_easy *data = conn->data;
  int i;

#ifndef CURL_DISABLE_PROXY
  enum proxy_use proxy;

  if(is_connect)
    proxy = HEADER_CONNECT;







|

>
|
>
>
>
>

>




<







1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745

1746
1747
1748
1749
1750
1751
1752
      infof(handle, "Malformatted trailing header ! Skipping trailer.");
    trailers = trailers->next;
  }
  result = Curl_dyn_add(b, endofline_network);
  return result;
}

CURLcode Curl_add_custom_headers(struct Curl_easy *data,
                                 bool is_connect,
#ifndef USE_HYPER
                                 struct dynbuf *req
#else
                                 void *req
#endif
  )
{
  struct connectdata *conn = data->conn;
  char *ptr;
  struct curl_slist *h[2];
  struct curl_slist *headers;
  int numlists = 1; /* by default */

  int i;

#ifndef CURL_DISABLE_PROXY
  enum proxy_use proxy;

  if(is_connect)
    proxy = HEADER_CONNECT;
1743
1744
1745
1746
1747
1748
1749

1750

1751
1752
1753
1754
1755
1756
1757
            optr = NULL;
          }
          else {
            if(*(--ptr) == ';') {
              /* copy the source */
              semicolonp = strdup(headers->data);
              if(!semicolonp) {

                Curl_dyn_free(req);

                return CURLE_OUT_OF_MEMORY;
              }
              /* put a colon where the semicolon is */
              semicolonp[ptr - headers->data] = ':';
              /* point at the colon */
              optr = &semicolonp [ptr - headers->data];
            }







>

>







1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
            optr = NULL;
          }
          else {
            if(*(--ptr) == ';') {
              /* copy the source */
              semicolonp = strdup(headers->data);
              if(!semicolonp) {
#ifndef USE_HYPER
                Curl_dyn_free(req);
#endif
                return CURLE_OUT_OF_MEMORY;
              }
              /* put a colon where the semicolon is */
              semicolonp[ptr - headers->data] = ':';
              /* point at the colon */
              optr = &semicolonp [ptr - headers->data];
            }
1804
1805
1806
1807
1808
1809
1810



1811

1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827

1828




1829
1830
1831
1832
1833
1834
1835
1836
1837
                     other hosts */
                  (data->state.this_is_a_follow &&
                   data->state.first_host &&
                   !data->set.allow_auth_to_other_hosts &&
                   !strcasecompare(data->state.first_host, conn->host.name)))
            ;
          else {



            result = Curl_dyn_addf(req, "%s\r\n", compare);

          }
          if(semicolonp)
            free(semicolonp);
          if(result)
            return result;
        }
      }
      headers = headers->next;
    }
  }

  return CURLE_OK;
}

#ifndef CURL_DISABLE_PARSEDATE
CURLcode Curl_add_timecondition(const struct connectdata *conn,

                                struct dynbuf *req)




{
  struct Curl_easy *data = conn->data;
  const struct tm *tm;
  struct tm keeptime;
  CURLcode result;
  char datestr[80];
  const char *condp;

  if(data->set.timecondition == CURL_TIMECOND_NONE)







>
>
>

>















|
>
|
>
>
>
>

<







1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896

1897
1898
1899
1900
1901
1902
1903
                     other hosts */
                  (data->state.this_is_a_follow &&
                   data->state.first_host &&
                   !data->set.allow_auth_to_other_hosts &&
                   !strcasecompare(data->state.first_host, conn->host.name)))
            ;
          else {
#ifdef USE_HYPER
            result = Curl_hyper_header(data, req, compare);
#else
            result = Curl_dyn_addf(req, "%s\r\n", compare);
#endif
          }
          if(semicolonp)
            free(semicolonp);
          if(result)
            return result;
        }
      }
      headers = headers->next;
    }
  }

  return CURLE_OK;
}

#ifndef CURL_DISABLE_PARSEDATE
CURLcode Curl_add_timecondition(struct Curl_easy *data,
#ifndef USE_HYPER
                                struct dynbuf *req
#else
                                void *req
#endif
  )
{

  const struct tm *tm;
  struct tm keeptime;
  CURLcode result;
  char datestr[80];
  const char *condp;

  if(data->set.timecondition == CURL_TIMECOND_NONE)
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
    condp = "If-Unmodified-Since";
    break;
  case CURL_TIMECOND_LASTMOD:
    condp = "Last-Modified";
    break;
  }

  if(Curl_checkheaders(conn, condp)) {
    /* A custom header was specified; it will be sent instead. */
    return CURLE_OK;
  }

  /* 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







|







1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
    condp = "If-Unmodified-Since";
    break;
  case CURL_TIMECOND_LASTMOD:
    condp = "Last-Modified";
    break;
  }

  if(Curl_checkheaders(data, condp)) {
    /* A custom header was specified; it will be sent instead. */
    return CURLE_OK;
  }

  /* 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
1880
1881
1882
1883
1884
1885
1886

1887



1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907

1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025


2026



2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
            tm->tm_mday,
            Curl_month[tm->tm_mon],
            tm->tm_year + 1900,
            tm->tm_hour,
            tm->tm_min,
            tm->tm_sec);


  result = Curl_dyn_add(req, datestr);




  return result;
}
#else
/* disabled */
CURLcode Curl_add_timecondition(const struct connectdata *conn,
                                struct dynbuf *req)
{
  (void)conn;
  (void)req;
  return CURLE_OK;
}
#endif

/*
 * Curl_http() gets called from the generic multi_do() function when a HTTP
 * request is to be performed. This creates and sends a properly constructed
 * HTTP request.
 */
CURLcode Curl_http(struct connectdata *conn, bool *done)

{
  struct Curl_easy *data = conn->data;
  CURLcode result = CURLE_OK;
  struct HTTP *http;
  const char *path = data->state.up.path;
  const char *query = data->state.up.query;
  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->state.httpreq;
#if !defined(CURL_DISABLE_COOKIES)
  char *addcookies = NULL;
#endif
  curl_off_t included_body = 0;
  const char *httpstring;
  struct dynbuf req;
  curl_off_t postsize = 0; /* curl_off_t to handle large file sizes */
  char *altused = NULL;

  /* 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->transport != TRNSPRT_QUIC) {
    if(conn->httpversion < 20) { /* unless the connection is re-used and
                                    already http2 */
      switch(conn->negnpn) {
      case CURL_HTTP_VERSION_2:
        conn->httpversion = 20; /* we know we're on HTTP/2 now */

        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:
        /* Check if user wants to use HTTP/2 with clear TCP*/
#ifdef USE_NGHTTP2
        if(conn->data->set.httpversion ==
           CURL_HTTP_VERSION_2_PRIOR_KNOWLEDGE) {
#ifndef CURL_DISABLE_PROXY
          if(conn->bits.httpproxy && !conn->bits.tunnel_proxy) {
            /* We don't support HTTP/2 proxies yet. Also it's debatable
               whether or not this setting should apply to HTTP/2 proxies. */
            infof(data, "Ignoring HTTP/2 prior knowledge due to proxy\n");
            break;
          }
#endif
          DEBUGF(infof(data, "HTTP/2 over clean TCP\n"));
          conn->httpversion = 20;

          result = Curl_http2_switched(conn, NULL, 0);
          if(result)
            return result;
        }
#endif
        break;
      }
    }
    else {
      /* prepare for a http2 request */
      result = Curl_http2_setup(conn);
      if(result)
        return result;
    }
  }
  http = data->req.p.http;
  DEBUGASSERT(http);

  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;

    data->state.first_remote_port = conn->remote_port;
  }

  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:
      case HTTPREQ_POST_MIME:
        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(data->state.aptr.uagent);
    data->state.aptr.uagent = NULL;
  }

  /* setup the authentication headers */
  {
    char *pq = NULL;
    if(query && *query) {
      pq = aprintf("%s?%s", path, query);
      if(!pq)
        return CURLE_OUT_OF_MEMORY;
    }
    result = Curl_http_output_auth(conn, request, (pq ? pq : path), FALSE);
    free(pq);
    if(result)
      return result;
  }

  if(((data->state.authhost.multipass && !data->state.authhost.done)
      || (data->state.authproxy.multipass && !data->state.authproxy.done)) &&
     (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(data->state.aptr.ref);
  if(data->change.referer && !Curl_checkheaders(conn, "Referer")) {
    data->state.aptr.ref = aprintf("Referer: %s\r\n", data->change.referer);
    if(!data->state.aptr.ref)
      return CURLE_OUT_OF_MEMORY;
  }
  else
    data->state.aptr.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(data->state.aptr.accept_encoding);
    data->state.aptr.accept_encoding =
      aprintf("Accept-Encoding: %s\r\n", data->set.str[STRING_ENCODING]);
    if(!data->state.aptr.accept_encoding)
      return CURLE_OUT_OF_MEMORY;
  }
  else {
    Curl_safefree(data->state.aptr.accept_encoding);
    data->state.aptr.accept_encoding = NULL;
  }

#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(data->state.aptr.te);

    if(cptr) {
      cptr = Curl_copy_header_value(cptr);
      if(!cptr)
        return CURLE_OUT_OF_MEMORY;
    }

    /* Create the (updated) Connection: header */
    data->state.aptr.te = aprintf("Connection: %s%sTE\r\n" TE_HEADER,
                                cptr ? cptr : "", (cptr && *cptr) ? ", ":"");

    free(cptr);
    if(!data->state.aptr.te)
      return CURLE_OUT_OF_MEMORY;
  }
#endif

  switch(httpreq) {
  case HTTPREQ_POST_MIME:
    http->sendit = &data->set.mimepost;
    break;
  case HTTPREQ_POST_FORM:
    /* Convert the form structure into a mime structure. */
    Curl_mime_cleanpart(&http->form);
    result = Curl_getformdata(data, &http->form, data->set.httppost,
                              data->state.fread_func);
    if(result)
      return result;
    http->sendit = &http->form;
    break;
  default:
    http->sendit = NULL;
  }

#ifndef CURL_DISABLE_MIME
  if(http->sendit) {
    const char *cthdr = Curl_checkheaders(conn, "Content-Type");

    /* Read and seek body only. */
    http->sendit->flags |= MIME_BODY_ONLY;

    /* Prepare the mime structure headers & set content type. */

    if(cthdr)
      for(cthdr += 13; *cthdr == ' '; cthdr++)
        ;
    else if(http->sendit->kind == MIMEKIND_MULTIPART)
      cthdr = "multipart/form-data";

    curl_mime_headers(http->sendit, data->set.headers, 0);
    result = Curl_mime_prepare_headers(http->sendit, cthdr,
                                       NULL, MIMESTRATEGY_FORM);
    curl_mime_headers(http->sendit, NULL, 0);
    if(!result)
      result = Curl_mime_rewind(http->sendit);
    if(result)
      return result;
    http->postsize = Curl_mime_size(http->sendit);
  }
#endif

  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) &&
       (((httpreq == HTTPREQ_POST_MIME || httpreq == HTTPREQ_POST_FORM) &&
         http->postsize < 0) ||
        ((data->set.upload || httpreq == HTTPREQ_POST) &&
         data->state.infilesize == -1))) {
      if(conn->bits.authneg)
        /* don't enable chunked during auth neg */
        ;
      else if(use_http_1_1plus(data, conn)) {
        if(conn->httpversion < 20)
          /* 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(data->state.aptr.host);

  ptr = Curl_checkheaders(conn, "Host");
  if(ptr && (!data->state.this_is_a_follow ||
             strcasecompare(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







>

>
>
>














<
<
<
<
<
|
>

<
<
<
<
<
<
<
<
<
<
<

<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<

|

<








|



















>
>
|
>
>
>




|



<
<
<
<
<
<
<
|
|
<
<
<
<
|

<
<
<
<
<
<
<
<
<
<
|
<
<
<
<
<
<
<
<
|
<
<
<
<
|
<
<
<
<
<
|
<
<
<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
|
|
<
<
<
<
<
|
<
<

<


|







1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971





1972
1973
1974











1975




1976




































































1977
1978
1979

1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021







2022
2023




2024
2025










2026








2027




2028





2029






2030













2031














2032










2033














































2034










2035
2036





2037


2038

2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
            tm->tm_mday,
            Curl_month[tm->tm_mon],
            tm->tm_year + 1900,
            tm->tm_hour,
            tm->tm_min,
            tm->tm_sec);

#ifndef USE_HYPER
  result = Curl_dyn_add(req, datestr);
#else
  result = Curl_hyper_header(data, req, datestr);
#endif

  return result;
}
#else
/* disabled */
CURLcode Curl_add_timecondition(const struct connectdata *conn,
                                struct dynbuf *req)
{
  (void)conn;
  (void)req;
  return CURLE_OK;
}
#endif






void Curl_http_method(struct Curl_easy *data, struct connectdata *conn,
                      const char **method, Curl_HttpReq *reqp)
{











  Curl_HttpReq httpreq = data->state.httpreq;




  const char *request;




































































  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_GET) && (httpreq <= HTTPREQ_HEAD));
      switch(httpreq) {
      case HTTPREQ_POST:
      case HTTPREQ_POST_FORM:
      case HTTPREQ_POST_MIME:
        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;
      }
    }
  }
  *method = request;
  *reqp = httpreq;
}

CURLcode Curl_http_useragent(struct Curl_easy *data)
{
  /* 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(data, "User-Agent")) {
    free(data->state.aptr.uagent);
    data->state.aptr.uagent = NULL;
  }







  return CURLE_OK;
}
















CURLcode Curl_http_host(struct Curl_easy *data, struct connectdata *conn)








{




  const char *ptr;





  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;






    data->state.first_remote_port = conn->remote_port;


  }

  Curl_safefree(data->state.aptr.host);

  ptr = Curl_checkheaders(data, "Host");
  if(ptr && (!data->state.this_is_a_follow ||
             strcasecompare(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
2242
2243
2244
2245
2246
2247
2248

2249
2250
2251
2252
2253
2254
2255
    else
      /* when clearing the header */
      data->state.aptr.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 */







>







2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
    else
      /* when clearing the header */
      data->state.aptr.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. */
    const char *host = conn->host.name;

    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 */
2264
2265
2266
2267
2268
2269
2270


















2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281

2282
2283
2284
2285
2286
2287
2288
                                    conn->bits.ipv6_ip?"]":"",
                                    conn->remote_port);

    if(!data->state.aptr.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! */

    /* and no fragment part */
    CURLUcode uc;

    CURLU *h = curl_url_dup(data->state.uh);
    if(!h)
      return CURLE_OUT_OF_MEMORY;

    if(conn->host.dispname != conn->host.name) {
      uc = curl_url_set(h, CURLUPART_HOST, conn->host.name, 0);
      if(uc) {







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>











>







2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
                                    conn->bits.ipv6_ip?"]":"",
                                    conn->remote_port);

    if(!data->state.aptr.host)
      /* without Host: we can't make a nice request */
      return CURLE_OUT_OF_MEMORY;
  }
  return CURLE_OK;
}

/*
 * Append the request-target to the HTTP request
 */
CURLcode Curl_http_target(struct Curl_easy *data,
                          struct connectdata *conn,
                          struct dynbuf *r)
{
  CURLcode result = CURLE_OK;
  const char *path = data->state.up.path;
  const char *query = data->state.up.query;

  if(data->set.str[STRING_TARGET]) {
    path = data->set.str[STRING_TARGET];
    query = NULL;
  }

#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! */

    /* and no fragment part */
    CURLUcode uc;
    char *url;
    CURLU *h = curl_url_dup(data->state.uh);
    if(!h)
      return CURLE_OUT_OF_MEMORY;

    if(conn->host.dispname != conn->host.name) {
      uc = curl_url_set(h, CURLUPART_HOST, conn->host.name, 0);
      if(uc) {
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321







2322
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337




























2338


2339
















2340



2341


2342

2343





2344
















































































2345




2346
2347
























2348




2349








2350
2351
















2352












































































2353












2354



2355




































































































































































































































































2356
2357
2358
2359
2360
2361
2362
        curl_url_cleanup(h);
        return CURLE_OUT_OF_MEMORY;
      }
    }
    /* Extract the URL to use in the request. Store in STRING_TEMP_URL for
       clean-up reasons if the function returns before the free() further
       down. */
    uc = curl_url_get(h, CURLUPART_URL, &data->set.str[STRING_TEMP_URL], 0);
    if(uc) {
      curl_url_cleanup(h);
      return CURLE_OUT_OF_MEMORY;
    }

    curl_url_cleanup(h);








    if(strcasecompare("ftp", data->state.up.scheme)) {
      if(data->set.proxy_transfer_mode) {
        /* when doing ftp, append ;type=<a|i> if not present */
        char *type = strstr(path, ";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.up.path && path[strlen(path) - 1] != '/') {


            *p++ = '/';

          }





          msnprintf(p, sizeof(ftp_typecode) - 1, ";type=%c",
















































































                    data->set.prefer_ascii ? 'a' : 'i');




        }
      }
























      if(conn->bits.user_passwd)




        paste_ftp_userpwd = TRUE;








    }
  }
















#endif /* CURL_DISABLE_PROXY */

























































































  http->p_accept = Curl_checkheaders(conn, "Accept")?NULL:"Accept: */*\r\n";








































































































































































































































































  if((HTTPREQ_POST == 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







|






>
>
>
>
>
>
>
















>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
|
>
>
|
>
|
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
|
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
|
>
>
>
>
>
>
>
>

|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
2370
2371
2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
2384
2385
2386
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
2450
2451
2452
2453
2454
2455
2456
2457
2458
2459
2460
2461
2462
2463
2464
2465
2466
2467
2468
2469
2470
2471
2472
2473
2474
2475
2476
2477
2478
2479
2480
2481
2482
2483
2484
2485
2486
2487
2488
2489
2490
2491
2492
2493
2494
2495
2496
2497
2498
2499
2500
2501
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
2539
2540
2541
2542
2543
2544
2545
2546
2547
2548
2549
2550
2551
2552
2553
2554
2555
2556
2557
2558
2559
2560
2561
2562
2563
2564
2565
2566
2567
2568
2569
2570
2571
2572
2573
2574
2575
2576
2577
2578
2579
2580
2581
2582
2583
2584
2585
2586
2587
2588
2589
2590
2591
2592
2593
2594
2595
2596
2597
2598
2599
2600
2601
2602
2603
2604
2605
2606
2607
2608
2609
2610
2611
2612
2613
2614
2615
2616
2617
2618
2619
2620
2621
2622
2623
2624
2625
2626
2627
2628
2629
2630
2631
2632
2633
2634
2635
2636
2637
2638
2639
2640
2641
2642
2643
2644
2645
2646
2647
2648
2649
2650
2651
2652
2653
2654
2655
2656
2657
2658
2659
2660
2661
2662
2663
2664
2665
2666
2667
2668
2669
2670
2671
2672
2673
2674
2675
2676
2677
2678
2679
2680
2681
2682
2683
2684
2685
2686
2687
2688
2689
2690
2691
2692
2693
2694
2695
2696
2697
2698
2699
2700
2701
2702
2703
2704
2705
2706
2707
2708
2709
2710
2711
2712
2713
2714
2715
2716
2717
2718
2719
2720
2721
2722
2723
2724
2725
2726
2727
2728
2729
2730
2731
2732
2733
2734
2735
2736
2737
2738
2739
2740
2741
2742
2743
2744
2745
2746
2747
2748
2749
2750
2751
2752
2753
2754
2755
2756
2757
2758
2759
2760
2761
2762
2763
2764
2765
2766
2767
2768
2769
2770
2771
2772
2773
2774
2775
        curl_url_cleanup(h);
        return CURLE_OUT_OF_MEMORY;
      }
    }
    /* Extract the URL to use in the request. Store in STRING_TEMP_URL for
       clean-up reasons if the function returns before the free() further
       down. */
    uc = curl_url_get(h, CURLUPART_URL, &url, 0);
    if(uc) {
      curl_url_cleanup(h);
      return CURLE_OUT_OF_MEMORY;
    }

    curl_url_cleanup(h);

    /* target or url */
    result = Curl_dyn_add(r, data->set.str[STRING_TARGET]?
      data->set.str[STRING_TARGET]:url);
    free(url);
    if(result)
      return (result);

    if(strcasecompare("ftp", data->state.up.scheme)) {
      if(data->set.proxy_transfer_mode) {
        /* when doing ftp, append ;type=<a|i> if not present */
        char *type = strstr(path, ";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) {
          result = Curl_dyn_addf(r, ";type=%c",
                                 data->set.prefer_ascii ? 'a' : 'i');
          if(result)
            return result;
        }
      }
    }
  }

  else
#else
    (void)conn; /* not used in disabled-proxy builds */
#endif
  {
    result = Curl_dyn_add(r, path);
    if(result)
      return result;
    if(query)
      result = Curl_dyn_addf(r, "?%s", query);
  }

  return result;
}

CURLcode Curl_http_body(struct Curl_easy *data, struct connectdata *conn,
                        Curl_HttpReq httpreq, const char **tep)
{
  CURLcode result = CURLE_OK;
  const char *ptr;
  struct HTTP *http = data->req.p.http;
  http->postsize = 0;

  switch(httpreq) {
  case HTTPREQ_POST_MIME:
    http->sendit = &data->set.mimepost;
    break;
  case HTTPREQ_POST_FORM:
    /* Convert the form structure into a mime structure. */
    Curl_mime_cleanpart(&http->form);
    result = Curl_getformdata(data, &http->form, data->set.httppost,
                              data->state.fread_func);
    if(result)
      return result;
    http->sendit = &http->form;
    break;
  default:
    http->sendit = NULL;
  }

#ifndef CURL_DISABLE_MIME
  if(http->sendit) {
    const char *cthdr = Curl_checkheaders(data, "Content-Type");

    /* Read and seek body only. */
    http->sendit->flags |= MIME_BODY_ONLY;

    /* Prepare the mime structure headers & set content type. */

    if(cthdr)
      for(cthdr += 13; *cthdr == ' '; cthdr++)
        ;
    else if(http->sendit->kind == MIMEKIND_MULTIPART)
      cthdr = "multipart/form-data";

    curl_mime_headers(http->sendit, data->set.headers, 0);
    result = Curl_mime_prepare_headers(http->sendit, cthdr,
                                       NULL, MIMESTRATEGY_FORM);
    curl_mime_headers(http->sendit, NULL, 0);
    if(!result)
      result = Curl_mime_rewind(http->sendit);
    if(result)
      return result;
    http->postsize = Curl_mime_size(http->sendit);
  }
#endif

  ptr = Curl_checkheaders(data, "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) &&
       (((httpreq == HTTPREQ_POST_MIME || httpreq == HTTPREQ_POST_FORM) &&
         http->postsize < 0) ||
        ((data->set.upload || httpreq == HTTPREQ_POST) &&
         data->state.infilesize == -1))) {
      if(conn->bits.authneg)
        /* don't enable chunked during auth neg */
        ;
      else if(use_http_1_1plus(data, conn)) {
        if(conn->httpversion < 20)
          /* 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)
      *tep = "Transfer-Encoding: chunked\r\n";
  }
  return result;
}

CURLcode Curl_http_bodysend(struct Curl_easy *data, struct connectdata *conn,
                            struct dynbuf *r, Curl_HttpReq httpreq)
{
#ifndef USE_HYPER
  /* Hyper always handles the body separately */
  curl_off_t included_body = 0;
#endif
  CURLcode result = CURLE_OK;
  struct HTTP *http = data->req.p.http;
  const char *ptr;

  /* 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_PUT: /* Let's PUT the data to the server! */

    if(conn->bits.authneg)
      http->postsize = 0;
    else
      http->postsize = data->state.infilesize;

    if((http->postsize != -1) && !data->req.upload_chunky &&
       (conn->bits.authneg || !Curl_checkheaders(data, "Content-Length"))) {
      /* only add Content-Length if not uploading chunked */
      result = Curl_dyn_addf(r, "Content-Length: %" CURL_FORMAT_CURL_OFF_T
                             "\r\n", http->postsize);
      if(result)
        return result;
    }

    if(http->postsize) {
      result = expect100(data, conn, r);
      if(result)
        return result;
    }

    /* end of headers */
    result = Curl_dyn_add(r, "\r\n");
    if(result)
      return result;

    /* set the upload size to the progress meter */
    Curl_pgrsSetUploadSize(data, http->postsize);

    /* this sends the buffer and frees all the buffer resources */
    result = Curl_buffer_send(r, data, &data->info.request_size, 0,
                              FIRSTSOCKET);
    if(result)
      failf(data, "Failed sending PUT request");
    else
      /* prepare for transfer */
      Curl_setup_transfer(data, FIRSTSOCKET, -1, TRUE,
                          http->postsize?FIRSTSOCKET:-1);
    if(result)
      return result;
    break;

  case HTTPREQ_POST_FORM:
  case HTTPREQ_POST_MIME:
    /* This is form posting using mime data. */
    if(conn->bits.authneg) {
      /* nothing to post! */
      result = Curl_dyn_add(r, "Content-Length: 0\r\n\r\n");
      if(result)
        return result;

      result = Curl_buffer_send(r, data, &data->info.request_size, 0,
                                FIRSTSOCKET);
      if(result)
        failf(data, "Failed sending POST request");
      else
        /* setup variables for the upcoming transfer */
        Curl_setup_transfer(data, FIRSTSOCKET, -1, TRUE, -1);
      break;
    }

    data->state.infilesize = http->postsize;

    /* 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(http->postsize != -1 && !data->req.upload_chunky &&
       (conn->bits.authneg || !Curl_checkheaders(data, "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_dyn_addf(r,
                             "Content-Length: %" CURL_FORMAT_CURL_OFF_T
                             "\r\n", http->postsize);
      if(result)
        return result;
    }

#ifndef CURL_DISABLE_MIME
    /* Output mime-generated headers. */
    {
      struct curl_slist *hdr;

      for(hdr = http->sendit->curlheaders; hdr; hdr = hdr->next) {
        result = Curl_dyn_addf(r, "%s\r\n", hdr->data);
        if(result)
          return result;
      }
    }
#endif

    /* 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(data, "Expect");
    if(ptr) {
      data->state.expect100header =
        Curl_compareheader(ptr, "Expect:", "100-continue");
    }
    else if(http->postsize > EXPECT_100_THRESHOLD || http->postsize < 0) {
      result = expect100(data, conn, r);
      if(result)
        return result;
    }
    else
      data->state.expect100header = FALSE;

    /* make the request end in a true CRLF */
    result = Curl_dyn_add(r, "\r\n");
    if(result)
      return result;

    /* set the upload size to the progress meter */
    Curl_pgrsSetUploadSize(data, http->postsize);

    /* Read from mime structure. */
    data->state.fread_func = (curl_read_callback) Curl_mime_read;
    data->state.in = (void *) http->sendit;
    http->sending = HTTPSEND_BODY;

    /* this sends the buffer and frees all the buffer resources */
    result = Curl_buffer_send(r, data, &data->info.request_size, 0,
                              FIRSTSOCKET);
    if(result)
      failf(data, "Failed sending POST request");
    else
      /* prepare for transfer */
      Curl_setup_transfer(data, FIRSTSOCKET, -1, TRUE,
                          http->postsize?FIRSTSOCKET:-1);
    if(result)
      return result;

    break;

  case HTTPREQ_POST:
    /* this is the simple POST, using x-www-form-urlencoded style */

    if(conn->bits.authneg)
      http->postsize = 0;
    else
      /* the size of the post body */
      http->postsize = data->state.infilesize;

    /* 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((http->postsize != -1) && !data->req.upload_chunky &&
       (conn->bits.authneg || !Curl_checkheaders(data, "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_dyn_addf(r, "Content-Length: %" CURL_FORMAT_CURL_OFF_T
                             "\r\n", http->postsize);
      if(result)
        return result;
    }

    if(!Curl_checkheaders(data, "Content-Type")) {
      result = Curl_dyn_add(r, "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(data, "Expect");
    if(ptr) {
      data->state.expect100header =
        Curl_compareheader(ptr, "Expect:", "100-continue");
    }
    else if(http->postsize > EXPECT_100_THRESHOLD || http->postsize < 0) {
      result = expect100(data, conn, r);
      if(result)
        return result;
    }
    else
      data->state.expect100header = FALSE;

#ifndef USE_HYPER
    /* With Hyper the body is always passed on separately */
    if(data->set.postfields) {

      /* In HTTP2, we send request body in DATA frame regardless of
         its size. */
      if(conn->httpversion != 20 &&
         !data->state.expect100header &&
         (http->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. */

        /* end of headers! */
        result = Curl_dyn_add(r, "\r\n");
        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_dyn_addn(r, data->set.postfields,
                                 (size_t)http->postsize);
          included_body = http->postsize;
        }
        else {
          if(http->postsize) {
            char chunk[16];
            /* Append the POST data chunky-style */
            msnprintf(chunk, sizeof(chunk), "%x\r\n", (int)http->postsize);
            result = Curl_dyn_add(r, chunk);
            if(!result) {
              included_body = http->postsize + strlen(chunk);
              result = Curl_dyn_addn(r, data->set.postfields,
                                     (size_t)http->postsize);
              if(!result)
                result = Curl_dyn_add(r, "\r\n");
              included_body += 2;
            }
          }
          if(!result) {
            result = Curl_dyn_add(r, "\x30\x0d\x0a\x0d\x0a");
            /* 0  CR  LF  CR  LF */
            included_body += 5;
          }
        }
        if(result)
          return result;
        /* Make sure the progress information is accurate */
        Curl_pgrsSetUploadSize(data, http->postsize);
      }
      else {
        /* A huge POST coming up, do data separate from the request */
        http->postdata = data->set.postfields;

        http->sending = HTTPSEND_BODY;

        data->state.fread_func = (curl_read_callback)readmoredata;
        data->state.in = (void *)data;

        /* set the upload size to the progress meter */
        Curl_pgrsSetUploadSize(data, http->postsize);

        /* end of headers! */
        result = Curl_dyn_add(r, "\r\n");
        if(result)
          return result;
      }
    }
    else
#endif
    {
       /* end of headers! */
      result = Curl_dyn_add(r, "\r\n");
      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_dyn_add(r, (char *)"\x30\x0d\x0a\x0d\x0a");
        /* 0  CR  LF  CR  LF */
        if(result)
          return result;
      }

      else if(data->state.infilesize) {
        /* set the upload size to the progress meter */
        Curl_pgrsSetUploadSize(data, http->postsize?http->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;
      }
    }
    /* issue the request */
    result = Curl_buffer_send(r, data, &data->info.request_size,
                              (size_t)included_body, FIRSTSOCKET);

    if(result)
      failf(data, "Failed sending HTTP POST request");
    else
      Curl_setup_transfer(data, FIRSTSOCKET, -1, TRUE,
                          http->postdata?FIRSTSOCKET:-1);
    break;

  default:
    result = Curl_dyn_add(r, "\r\n");
    if(result)
      return result;

    /* issue the request */
    result = Curl_buffer_send(r, data, &data->info.request_size, 0,
                              FIRSTSOCKET);

    if(result)
      failf(data, "Failed sending HTTP request");
    else
      /* HTTP GET/HEAD download: */
      Curl_setup_transfer(data, FIRSTSOCKET, -1, TRUE, -1);
  }

  return result;
}

#if !defined(CURL_DISABLE_COOKIES)
CURLcode Curl_http_cookies(struct Curl_easy *data,
                           struct connectdata *conn,
                           struct dynbuf *r)
{
  CURLcode result = CURLE_OK;
  char *addcookies = NULL;
  if(data->set.str[STRING_COOKIE] && !Curl_checkheaders(data, "Cookie"))
    addcookies = data->set.str[STRING_COOKIE];

  if(data->cookies || addcookies) {
    struct Cookie *co = NULL; /* no cookies from start */
    int count = 0;

    if(data->cookies && data->state.cookie_engine) {
      Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE);
      co = Curl_cookie_getlist(data->cookies,
                               data->state.aptr.cookiehost?
                               data->state.aptr.cookiehost:
                               conn->host.name,
                               data->state.up.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_dyn_add(r, "Cookie: ");
            if(result)
              break;
          }
          result = Curl_dyn_addf(r, "%s%s=%s", count?"; ":"",
                                 co->name, co->value);
          if(result)
            break;
          count++;
        }
        co = co->next; /* next cookie please */
      }
      Curl_cookie_freelist(store);
    }
    if(addcookies && !result) {
      if(!count)
        result = Curl_dyn_add(r, "Cookie: ");
      if(!result) {
        result = Curl_dyn_addf(r, "%s%s", count?"; ":"", addcookies);
        count++;
      }
    }
    if(count && !result)
      result = Curl_dyn_add(r, "\r\n");

    if(result)
      return result;
  }
  return result;
}
#endif

CURLcode Curl_http_range(struct Curl_easy *data,
                         Curl_HttpReq httpreq)
{
  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(data, "Range")) {
      /* if a line like this was already allocated, free the previous one */
      free(data->state.aptr.rangeline);
      data->state.aptr.rangeline = aprintf("Range: bytes=%s\r\n",
                                           data->state.range);
    }
    else if((httpreq == HTTPREQ_POST || httpreq == HTTPREQ_PUT) &&
            !Curl_checkheaders(data, "Content-Range")) {

      /* if a line like this was already allocated, free the previous one */
      free(data->state.aptr.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) */
        data->state.aptr.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;
        data->state.aptr.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 */
        data->state.aptr.rangeline =
          aprintf("Content-Range: bytes %s/%" CURL_FORMAT_CURL_OFF_T "\r\n",
                  data->state.range, data->state.infilesize);
      }
      if(!data->state.aptr.rangeline)
        return CURLE_OUT_OF_MEMORY;
    }
  }
  return CURLE_OK;
}

CURLcode Curl_http_resume(struct Curl_easy *data,
                          struct connectdata *conn,
                          Curl_HttpReq httpreq)
{
  if((HTTPREQ_POST == 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
2422
2423
2424
2425
2426
2427
2428


2429


2430
2431





2432
2433

2434








2435
2436
2437
2438









2439




2440

2441
2442




2443










2444

2445


2446







2447
2448
2449








2450


2451
2452
2453




2454

2455

















2456



2457

















2458



2459



2460

2461



2462
2463









2464



2465


2466







2467
2468
2469
2470

2471

2472


2473









2474
2475




2476
2477
2478























2479
2480
2481
2482
2483
2484
2485
2486
2487
2488
2489
2490
2491
2492
2493
2494
2495
2496
2497
2498
2499
2500
2501
2502
2503
2504
2505
2506
2507
2508
2509
2510

2511
2512
2513
2514
2515
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
2539
2540
2541
2542
2543
2544
2545
2546
2547
2548
2549
2550
2551
2552
2553
2554
2555
2556
2557
2558
2559
2560
2561
2562
2563
2564
2565
2566
2567

2568
2569
2570
2571
2572
2573
2574
2575
2576
2577
2578
2579
2580
2581
2582
2583

2584

2585
2586
2587
2588
2589
2590
2591
2592
2593
2594
2595
2596
2597
2598
2599
2600
2601
2602
2603
2604
2605
2606
2607
2608
2609
2610
2611
2612
2613
2614
2615
2616
2617
2618
2619
2620
2621
2622
2623
2624
2625
2626
2627
2628
2629
2630
2631
2632
2633
2634
2635
2636
2637
2638
2639
2640
2641
2642
2643
2644
2645
2646
2647
2648
2649
2650
2651
2652
2653
2654
2655
2656
2657
2658
2659
2660
2661
2662
2663
2664
2665
2666
2667
2668
2669
2670
2671
2672
2673
2674
2675
2676
2677
2678
2679
2680
2681
2682
2683
2684
2685
2686
2687
2688
2689
2690
2691
2692
2693
2694
2695
2696
2697
2698
2699
2700
2701
2702
2703
2704
2705
2706
2707
2708
2709
2710
2711
2712
2713
2714
2715
2716
2717
2718
2719
2720
2721
2722
2723
2724
2725
2726
2727
2728
2729
2730
2731
2732
2733
2734
2735
2736
2737
2738
2739
2740
2741
2742
2743
2744
2745
2746
2747
2748
2749
2750
2751
2752
2753
2754
2755
2756
2757
2758
2759
2760
2761
2762
2763
2764
2765
2766
2767
2768
2769
2770
2771
2772
2773
2774
2775
2776
2777
2778
2779
2780
2781
2782
2783
2784
2785
2786
2787
2788
2789
2790
2791
2792
2793
2794
2795
2796
2797
2798
2799
2800
2801
2802
2803
2804
2805
2806
2807
2808
2809
2810
2811
2812
2813
2814
2815
2816
2817
2818
2819
2820
2821
2822
2823
2824
2825
2826
2827
2828
2829
2830
2831
2832
2833
2834
2835
2836
2837
2838
2839
2840
2841
2842
2843
2844
2845
2846
2847
2848
2849
2850
2851
2852
2853
2854
2855
2856
2857
2858
2859
2860
2861
2862
2863
2864
2865
2866
2867
2868
2869
2870
2871
2872
2873
2874
2875
2876
2877
2878
2879
2880
2881
2882
2883
2884
2885
2886
2887
2888
2889
2890
2891
2892
2893
2894
2895
2896
2897
2898
2899
2900
2901
2902
2903
2904
2905
2906
2907
2908
2909
2910
2911
2912
2913
2914
2915
2916
2917
2918
2919
2920
2921
2922
2923
2924
2925
2926
2927
2928
2929
2930
2931
2932
2933
2934
2935
2936
2937
2938
2939
2940
2941
2942
2943
2944
2945
2946
2947
2948
2949
2950
2951
2952
2953
2954
2955
2956
2957
2958
2959
2960
2961
2962
2963
2964
2965
2966
2967
2968
2969
2970
2971

2972
2973
2974
2975
2976
2977
2978
2979
2980
2981
2982
2983
2984
2985
2986
2987
2988
2989
2990
2991
2992
2993
2994
2995
2996
2997
2998
2999
3000
3001


3002
3003
3004
3005
3006
3007
3008
          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(data->state.aptr.rangeline);









      data->state.aptr.rangeline = aprintf("Range: bytes=%s\r\n",




                                         data->state.range);

    }
    else if((httpreq == HTTPREQ_POST || httpreq == HTTPREQ_PUT) &&




            !Curl_checkheaders(conn, "Content-Range")) {












      /* if a line like this was already allocated, free the previous one */


      free(data->state.aptr.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) */
        data->state.aptr.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;



        data->state.aptr.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 */

        data->state.aptr.rangeline =

          aprintf("Content-Range: bytes %s/%" CURL_FORMAT_CURL_OFF_T "\r\n",


                  data->state.range, data->state.infilesize);









      }
      if(!data->state.aptr.rangeline)




        return CURLE_OUT_OF_MEMORY;
    }
  }
























  httpstring = get_http_string(data, conn);

  /* initialize a dynamic send-buffer */
  Curl_dyn_init(&req, DYN_HTTP_REQUEST);

  /* add the main request stuff */
  /* GET/HEAD/POST/PUT */
  result = Curl_dyn_addf(&req, "%s ", request);
  if(result)
    return result;

  if(data->set.str[STRING_TARGET]) {
    path = data->set.str[STRING_TARGET];
    query = NULL;
  }

#ifndef CURL_DISABLE_PROXY
  /* url */
  if(conn->bits.httpproxy && !conn->bits.tunnel_proxy) {
    char *url = data->set.str[STRING_TEMP_URL];
    result = Curl_dyn_add(&req, url);
    Curl_safefree(data->set.str[STRING_TEMP_URL]);
  }
  else
#endif
  if(paste_ftp_userpwd)
    result = Curl_dyn_addf(&req, "ftp://%s:%s@%s", conn->user, conn->passwd,
                           path + sizeof("ftp://") - 1);
  else {
    result = Curl_dyn_add(&req, path);
    if(result)

      return result;
    if(query)
      result = Curl_dyn_addf(&req, "?%s", query);
  }
  if(result)
    return result;

#ifndef CURL_DISABLE_ALTSVC
  if(conn->bits.altused && !Curl_checkheaders(conn, "Alt-Used")) {
    altused = aprintf("Alt-Used: %s:%d\r\n",
                      conn->conn_to_host.name, conn->conn_to_port);
    if(!altused) {
      Curl_dyn_free(&req);
      return CURLE_OUT_OF_MEMORY;
    }
  }
#endif
  result =
    Curl_dyn_addf(&req,
                  "%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 */
                  "%s",/* Alt-Used */

                  ftp_typecode,
                  httpstring,
                  (data->state.aptr.host?data->state.aptr.host:""),
                  data->state.aptr.proxyuserpwd?
                  data->state.aptr.proxyuserpwd:"",
                  data->state.aptr.userpwd?data->state.aptr.userpwd:"",
                  (data->state.use_range && data->state.aptr.rangeline)?
                  data->state.aptr.rangeline:"",
                  (data->set.str[STRING_USERAGENT] &&
                   *data->set.str[STRING_USERAGENT] &&
                   data->state.aptr.uagent)?
                  data->state.aptr.uagent:"",
                  http->p_accept?http->p_accept:"",
                  data->state.aptr.te?data->state.aptr.te:"",
                  (data->set.str[STRING_ENCODING] &&
                   *data->set.str[STRING_ENCODING] &&
                   data->state.aptr.accept_encoding)?
                  data->state.aptr.accept_encoding:"",
                  (data->change.referer && data->state.aptr.ref)?
                  data->state.aptr.ref:"" /* Referer: <data> */,
#ifndef CURL_DISABLE_PROXY
                  (conn->bits.httpproxy &&
                   !conn->bits.tunnel_proxy &&

                   !Curl_checkProxyheaders(conn, "Proxy-Connection"))?
                  "Proxy-Connection: Keep-Alive\r\n":"",
#else
                  "",
#endif
                  te,
                  altused ? altused : ""
      );

  /* clear userpwd and proxyuserpwd to avoid re-using old credentials
   * from re-used connections */
  Curl_safefree(data->state.aptr.userpwd);
  Curl_safefree(data->state.aptr.proxyuserpwd);
  free(altused);

  if(result)

    return result;


  if(!(conn->handler->flags&PROTOPT_SSL) &&
     conn->httpversion != 20 &&
     (data->set.httpversion == CURL_HTTP_VERSION_2)) {
    /* append HTTP2 upgrade magic stuff to the HTTP request if it isn't done
       over SSL */
    result = Curl_http2_request_upgrade(&req, 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 && data->state.cookie_engine) {
      Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE);
      co = Curl_cookie_getlist(data->cookies,
                               data->state.aptr.cookiehost?
                               data->state.aptr.cookiehost:host,
                               data->state.up.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_dyn_add(&req, "Cookie: ");
            if(result)
              break;
          }
          result = Curl_dyn_addf(&req, "%s%s=%s", count?"; ":"",
                                 co->name, co->value);
          if(result)
            break;
          count++;
        }
        co = co->next; /* next cookie please */
      }
      Curl_cookie_freelist(store);
    }
    if(addcookies && !result) {
      if(!count)
        result = Curl_dyn_add(&req, "Cookie: ");
      if(!result) {
        result = Curl_dyn_addf(&req, "%s%s", count?"; ":"", addcookies);
        count++;
      }
    }
    if(count && !result)
      result = Curl_dyn_add(&req, "\r\n");

    if(result)
      return result;
  }
#endif

  result = Curl_add_timecondition(conn, &req);
  if(result)
    return result;

  result = Curl_add_custom_headers(conn, FALSE, &req);
  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_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 &&
       (conn->bits.authneg || !Curl_checkheaders(conn, "Content-Length"))) {
      /* only add Content-Length if not uploading chunked */
      result = Curl_dyn_addf(&req, "Content-Length: %" CURL_FORMAT_CURL_OFF_T
                             "\r\n", postsize);
      if(result)
        return result;
    }

    if(postsize != 0) {
      result = expect100(data, conn, &req);
      if(result)
        return result;
    }

    /* end of headers */
    result = Curl_dyn_add(&req, "\r\n");
    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_buffer_send(&req, conn, &data->info.request_size, 0,
                              FIRSTSOCKET);
    if(result)
      failf(data, "Failed sending PUT request");
    else
      /* prepare for transfer */
      Curl_setup_transfer(data, FIRSTSOCKET, -1, TRUE,
                          postsize?FIRSTSOCKET:-1);
    if(result)
      return result;
    break;

  case HTTPREQ_POST_FORM:
  case HTTPREQ_POST_MIME:
    /* This is form posting using mime data. */
    if(conn->bits.authneg) {
      /* nothing to post! */
      result = Curl_dyn_add(&req, "Content-Length: 0\r\n\r\n");
      if(result)
        return result;

      result = Curl_buffer_send(&req, 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(data, FIRSTSOCKET, -1, TRUE, -1);
      break;
    }

    data->state.infilesize = postsize = http->postsize;

    /* 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 &&
       (conn->bits.authneg || !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_dyn_addf(&req,
                             "Content-Length: %" CURL_FORMAT_CURL_OFF_T
                             "\r\n", postsize);
      if(result)
        return result;
    }

#ifndef CURL_DISABLE_MIME
    /* Output mime-generated headers. */
    {
      struct curl_slist *hdr;

      for(hdr = http->sendit->curlheaders; hdr; hdr = hdr->next) {
        result = Curl_dyn_addf(&req, "%s\r\n", hdr->data);
        if(result)
          return result;
      }
    }
#endif

    /* 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 > EXPECT_100_THRESHOLD || postsize < 0) {
      result = expect100(data, conn, &req);
      if(result)
        return result;
    }
    else
      data->state.expect100header = FALSE;

    /* make the request end in a true CRLF */
    result = Curl_dyn_add(&req, "\r\n");
    if(result)
      return result;

    /* set the upload size to the progress meter */
    Curl_pgrsSetUploadSize(data, postsize);

    /* Read from mime structure. */
    data->state.fread_func = (curl_read_callback) Curl_mime_read;
    data->state.in = (void *) http->sendit;
    http->sending = HTTPSEND_BODY;

    /* this sends the buffer and frees all the buffer resources */
    result = Curl_buffer_send(&req, conn, &data->info.request_size, 0,
                              FIRSTSOCKET);
    if(result)
      failf(data, "Failed sending POST request");
    else
      /* prepare for transfer */
      Curl_setup_transfer(data, FIRSTSOCKET, -1, TRUE,
                          postsize?FIRSTSOCKET:-1);
    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
      /* the size of the post body */
      postsize = data->state.infilesize;

    /* 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 &&
       (conn->bits.authneg || !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_dyn_addf(&req, "Content-Length: %" CURL_FORMAT_CURL_OFF_T
                             "\r\n", postsize);
      if(result)
        return result;
    }

    if(!Curl_checkheaders(conn, "Content-Type")) {
      result = Curl_dyn_add(&req, "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 > EXPECT_100_THRESHOLD || postsize < 0) {
      result = expect100(data, conn, &req);
      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. */

        /* end of headers! */
        result = Curl_dyn_add(&req, "\r\n");
        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_dyn_addn(&req, data->set.postfields,
                                 (size_t)postsize);
          included_body = postsize;
        }
        else {
          if(postsize) {
            char chunk[16];
            /* Append the POST data chunky-style */
            msnprintf(chunk, sizeof(chunk), "%x\r\n", (int)postsize);
            result = Curl_dyn_add(&req, chunk);
            if(!result) {
              included_body = postsize + strlen(chunk);
              result = Curl_dyn_addn(&req, data->set.postfields,
                                     (size_t)postsize);
              if(!result)
                result = Curl_dyn_add(&req, "\r\n");
              included_body += 2;
            }
          }
          if(!result) {
            result = Curl_dyn_add(&req, "\x30\x0d\x0a\x0d\x0a");
            /* 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;

        data->state.fread_func = (curl_read_callback)readmoredata;
        data->state.in = (void *)conn;

        /* set the upload size to the progress meter */
        Curl_pgrsSetUploadSize(data, http->postsize);

        /* end of headers! */
        result = Curl_dyn_add(&req, "\r\n");
        if(result)
          return result;
      }
    }
    else {
       /* end of headers! */
      result = Curl_dyn_add(&req, "\r\n");
      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_dyn_add(&req, (char *)"\x30\x0d\x0a\x0d\x0a");
        /* 0  CR  LF  CR  LF */
        if(result)
          return result;
      }

      else if(data->state.infilesize) {
        /* 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_buffer_send(&req, conn, &data->info.request_size,
                              (size_t)included_body, FIRSTSOCKET);

    if(result)
      failf(data, "Failed sending HTTP POST request");
    else
      Curl_setup_transfer(data, FIRSTSOCKET, -1, TRUE,
                          http->postdata?FIRSTSOCKET:-1);
    break;

  default:
    result = Curl_dyn_add(&req, "\r\n");
    if(result)
      return result;

    /* issue the request */
    result = Curl_buffer_send(&req, conn, &data->info.request_size, 0,
                              FIRSTSOCKET);

    if(result)
      failf(data, "Failed sending HTTP request");
    else
      /* HTTP GET/HEAD download: */
      Curl_setup_transfer(data, FIRSTSOCKET, -1, TRUE, -1);
  }
  if(result)
    return result;

  if(!postsize && (http->sending != HTTPSEND_REQUEST))
    data->req.upload_done = TRUE;

  if(data->req.writebytecount) {
    /* if a request-body has been sent off, we make sure this progress is noted
       properly */
    Curl_pgrsSetUploadCounter(data, data->req.writebytecount);
    if(Curl_pgrsUpdate(conn))
      result = CURLE_ABORTED_BY_CALLBACK;

    if(data->req.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",
            data->req.writebytecount, postsize);
      data->req.upload_done = TRUE;
      data->req.keepon &= ~KEEP_SEND; /* we're done writing */
      data->req.exp100 = EXP100_SEND_DATA; /* already sent */
      Curl_expire_done(data, EXPIRE_100_TIMEOUT);
    }
  }

  if((conn->httpversion == 20) && data->req.upload_chunky)
    /* upload_chunky was set above to set up the request in a chunky fashion,
       but is disabled here again to avoid that the chunked encoded version is
       actually used when sending the request body over h2 */
    data->req.upload_chunky = FALSE;
  return result;
}



typedef enum {
  STATUS_UNKNOWN, /* not enough data to tell yet */
  STATUS_DONE, /* a status line was read */
  STATUS_BAD /* not a status line */
} statusline;








>
>
|
>
>
|
<
>
>
>
>
>
|
|
>
|
>
>
>
>
>
>
>
>
|
|
|
|
>
>
>
>
>
>
>
>
>
|
>
>
>
>
|
>
|
|
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
|
>
|
>
>
|
>
>
>
>
>
>
>
|
|
|
>
>
>
>
>
>
>
>
|
>
>
|
|
|
>
>
>
>
|
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
|
>
>
>
|
>
|
>
>
>
|
|
>
>
>
>
>
>
>
>
>
|
>
>
>
|
>
>
|
>
>
>
>
>
>
>
|
|
<
<
>
|
>
|
>
>
|
>
>
>
>
>
>
>
>
>
|
|
>
>
>
>


|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>









|
<
<
<
<
<
<
<
<
<
<
<
|
<
<
<
<
<
<
<
<
<
|
>
|
<
<

<
<


|










<














<











|










>
|














|
>

>







|
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<

|
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<

<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
|
<
<
<
<
<
<
|
|
<
|
<
<
<
<
<
<
<

<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
|
<
|
<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
|
<
<
<
|
<
<
<
<
<
<
|
<
<
<
<
<
<
|
<
<
<
<
<
|
<
<
<
|
|
<
<
<

|
<
<
<
<
<
<
<
>
|






|


|




|














>
>







2835
2836
2837
2838
2839
2840
2841
2842
2843
2844
2845
2846
2847

2848
2849
2850
2851
2852
2853
2854
2855
2856
2857
2858
2859
2860
2861
2862
2863
2864
2865
2866
2867
2868
2869
2870
2871
2872
2873
2874
2875
2876
2877
2878
2879
2880
2881
2882
2883
2884
2885
2886
2887
2888
2889
2890
2891
2892
2893
2894
2895
2896
2897
2898
2899
2900
2901
2902
2903
2904
2905
2906
2907
2908
2909
2910
2911
2912
2913
2914
2915
2916
2917
2918
2919
2920
2921
2922
2923
2924
2925
2926
2927
2928
2929
2930
2931
2932
2933
2934
2935
2936
2937
2938
2939
2940
2941
2942
2943
2944
2945
2946
2947
2948
2949
2950
2951
2952
2953
2954
2955
2956
2957
2958
2959
2960
2961
2962
2963
2964
2965
2966
2967
2968
2969
2970
2971
2972
2973
2974
2975
2976
2977
2978
2979
2980
2981
2982
2983
2984
2985
2986
2987
2988
2989
2990
2991
2992
2993
2994
2995
2996
2997
2998
2999
3000
3001
3002
3003
3004
3005
3006
3007
3008
3009
3010
3011
3012
3013
3014
3015
3016
3017
3018
3019


3020
3021
3022
3023
3024
3025
3026
3027
3028
3029
3030
3031
3032
3033
3034
3035
3036
3037
3038
3039
3040
3041
3042
3043
3044
3045
3046
3047
3048
3049
3050
3051
3052
3053
3054
3055
3056
3057
3058
3059
3060
3061
3062
3063
3064
3065
3066
3067
3068
3069
3070
3071
3072
3073
3074
3075
3076
3077











3078









3079
3080
3081


3082


3083
3084
3085
3086
3087
3088
3089
3090
3091
3092
3093
3094
3095

3096
3097
3098
3099
3100
3101
3102
3103
3104
3105
3106
3107
3108
3109

3110
3111
3112
3113
3114
3115
3116
3117
3118
3119
3120
3121
3122
3123
3124
3125
3126
3127
3128
3129
3130
3131
3132
3133
3134
3135
3136
3137
3138
3139
3140
3141
3142
3143
3144
3145
3146
3147
3148
3149
3150
3151
3152
3153
3154
3155
3156
3157
3158
3159


3160















































3161
3162

3163











































3164










































































3165
3166






3167
3168

3169







3170




























































































3171






















3172
3173

3174




3175




















3176
3177



3178






3179






3180





3181



3182
3183



3184
3185







3186
3187
3188
3189
3190
3191
3192
3193
3194
3195
3196
3197
3198
3199
3200
3201
3202
3203
3204
3205
3206
3207
3208
3209
3210
3211
3212
3213
3214
3215
3216
3217
3218
3219
3220
3221
3222
3223
3224
3225
          failf(data, "File already completely uploaded");
          return CURLE_PARTIAL_FILE;
        }
      }
      /* we've passed, proceed as normal */
    }
  }
  return CURLE_OK;
}

CURLcode Curl_http_firstwrite(struct Curl_easy *data,
                              struct connectdata *conn,
                              bool *done)

{
  struct SingleRequest *k = &data->req;
  DEBUGASSERT(conn->handler->protocol&(PROTO_FAMILY_HTTP|CURLPROTO_RTSP));
  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->state.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 */

  return CURLE_OK;
}

#ifndef USE_HYPER
/*
 * Curl_http() gets called from the generic multi_do() function when a HTTP
 * request is to be performed. This creates and sends a properly constructed
 * HTTP request.
 */
CURLcode Curl_http(struct Curl_easy *data, bool *done)
{
  struct connectdata *conn = data->conn;
  CURLcode result = CURLE_OK;
  struct HTTP *http;
  Curl_HttpReq httpreq;
  const char *te = ""; /* transfer-encoding */
  const char *request;
  const char *httpstring;
  struct dynbuf req;
  char *altused = NULL;
  const char *p_accept;      /* Accept: string */

  /* Always consider the DO phase done after this function call, even if there
     may be parts of the request that are not yet sent, since we can deal with
     the rest of the request in the PERFORM phase. */
  *done = TRUE;

  if(conn->transport != TRNSPRT_QUIC) {
    if(conn->httpversion < 20) { /* unless the connection is re-used and
                                    already http2 */
      switch(conn->negnpn) {
      case CURL_HTTP_VERSION_2:
        conn->httpversion = 20; /* we know we're on HTTP/2 now */

        result = Curl_http2_switched(data, NULL, 0);
        if(result)
          return result;
        break;
      case CURL_HTTP_VERSION_1_1:
        /* continue with HTTP/1.1 when explicitly requested */
        break;
      default:
        /* Check if user wants to use HTTP/2 with clear TCP*/
#ifdef USE_NGHTTP2
        if(data->set.httpversion == CURL_HTTP_VERSION_2_PRIOR_KNOWLEDGE) {
#ifndef CURL_DISABLE_PROXY
          if(conn->bits.httpproxy && !conn->bits.tunnel_proxy) {
            /* We don't support HTTP/2 proxies yet. Also it's debatable
               whether or not this setting should apply to HTTP/2 proxies. */
            infof(data, "Ignoring HTTP/2 prior knowledge due to proxy\n");
            break;
          }
#endif
          DEBUGF(infof(data, "HTTP/2 over clean TCP\n"));
          conn->httpversion = 20;

          result = Curl_http2_switched(data, NULL, 0);
          if(result)
            return result;
        }
#endif
        break;
      }
    }
    else {
      /* prepare for a http2 request */
      result = Curl_http2_setup(data, conn);
      if(result)
        return result;
    }
  }
  http = data->req.p.http;
  DEBUGASSERT(http);

  result = Curl_http_host(data, conn);
  if(result)
    return result;

  result = Curl_http_useragent(data);
  if(result)
    return result;

  Curl_http_method(data, conn, &request, &httpreq);

  /* setup the authentication headers */
  {
    char *pq = NULL;
    if(data->state.up.query) {
      pq = aprintf("%s?%s", data->state.up.path, data->state.up.query);
      if(!pq)
        return CURLE_OUT_OF_MEMORY;
    }
    result = Curl_http_output_auth(data, conn, request, httpreq,
                                   (pq ? pq : data->state.up.path), FALSE);
    free(pq);
    if(result)
      return result;
  }

  Curl_safefree(data->state.aptr.ref);
  if(data->change.referer && !Curl_checkheaders(data, "Referer")) {
    data->state.aptr.ref = aprintf("Referer: %s\r\n", data->change.referer);
    if(!data->state.aptr.ref)
      return CURLE_OUT_OF_MEMORY;
  }

  if(!Curl_checkheaders(data, "Accept-Encoding") &&
     data->set.str[STRING_ENCODING]) {
    Curl_safefree(data->state.aptr.accept_encoding);
    data->state.aptr.accept_encoding =
      aprintf("Accept-Encoding: %s\r\n", data->set.str[STRING_ENCODING]);
    if(!data->state.aptr.accept_encoding)
      return CURLE_OUT_OF_MEMORY;
  }
  else {


    Curl_safefree(data->state.aptr.accept_encoding);
    data->state.aptr.accept_encoding = NULL;
  }

#ifdef HAVE_LIBZ
  /* we only consider transfer-encoding magic if libz support is built-in */

  if(!Curl_checkheaders(data, "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/her own TE: header we don't do this magic
       but then assume that the user will handle it all! */
    char *cptr = Curl_checkheaders(data, "Connection");
#define TE_HEADER "TE: gzip\r\n"

    Curl_safefree(data->state.aptr.te);

    if(cptr) {
      cptr = Curl_copy_header_value(cptr);
      if(!cptr)
        return CURLE_OUT_OF_MEMORY;
    }

    /* Create the (updated) Connection: header */
    data->state.aptr.te = aprintf("Connection: %s%sTE\r\n" TE_HEADER,
                                cptr ? cptr : "", (cptr && *cptr) ? ", ":"");

    free(cptr);
    if(!data->state.aptr.te)
      return CURLE_OUT_OF_MEMORY;
  }
#endif

  result = Curl_http_body(data, conn, httpreq, &te);
  if(result)
    return result;

  p_accept = Curl_checkheaders(data, "Accept")?NULL:"Accept: */*\r\n";

  result = Curl_http_resume(data, conn, httpreq);
  if(result)
    return result;

  result = Curl_http_range(data, httpreq);
  if(result)
    return result;

  httpstring = get_http_string(data, conn);

  /* initialize a dynamic send-buffer */
  Curl_dyn_init(&req, DYN_HTTP_REQUEST);

  /* add the main request stuff */
  /* GET/HEAD/POST/PUT */
  result = Curl_dyn_addf(&req, "%s ", request);
  if(!result)











    result = Curl_http_target(data, conn, &req);









  if(result) {
    Curl_dyn_free(&req);
    return result;


  }



#ifndef CURL_DISABLE_ALTSVC
  if(conn->bits.altused && !Curl_checkheaders(data, "Alt-Used")) {
    altused = aprintf("Alt-Used: %s:%d\r\n",
                      conn->conn_to_host.name, conn->conn_to_port);
    if(!altused) {
      Curl_dyn_free(&req);
      return CURLE_OUT_OF_MEMORY;
    }
  }
#endif
  result =
    Curl_dyn_addf(&req,

                  " 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 */
                  "%s",/* Alt-Used */


                  httpstring,
                  (data->state.aptr.host?data->state.aptr.host:""),
                  data->state.aptr.proxyuserpwd?
                  data->state.aptr.proxyuserpwd:"",
                  data->state.aptr.userpwd?data->state.aptr.userpwd:"",
                  (data->state.use_range && data->state.aptr.rangeline)?
                  data->state.aptr.rangeline:"",
                  (data->set.str[STRING_USERAGENT] &&
                   *data->set.str[STRING_USERAGENT] &&
                   data->state.aptr.uagent)?
                  data->state.aptr.uagent:"",
                  p_accept?p_accept:"",
                  data->state.aptr.te?data->state.aptr.te:"",
                  (data->set.str[STRING_ENCODING] &&
                   *data->set.str[STRING_ENCODING] &&
                   data->state.aptr.accept_encoding)?
                  data->state.aptr.accept_encoding:"",
                  (data->change.referer && data->state.aptr.ref)?
                  data->state.aptr.ref:"" /* Referer: <data> */,
#ifndef CURL_DISABLE_PROXY
                  (conn->bits.httpproxy &&
                   !conn->bits.tunnel_proxy &&
                   !Curl_checkheaders(data, "Proxy-Connection") &&
                   !Curl_checkProxyheaders(data, conn, "Proxy-Connection"))?
                  "Proxy-Connection: Keep-Alive\r\n":"",
#else
                  "",
#endif
                  te,
                  altused ? altused : ""
      );

  /* clear userpwd and proxyuserpwd to avoid re-using old credentials
   * from re-used connections */
  Curl_safefree(data->state.aptr.userpwd);
  Curl_safefree(data->state.aptr.proxyuserpwd);
  free(altused);

  if(result) {
    Curl_dyn_free(&req);
    return result;
  }

  if(!(conn->handler->flags&PROTOPT_SSL) &&
     conn->httpversion != 20 &&
     (data->set.httpversion == CURL_HTTP_VERSION_2)) {
    /* append HTTP2 upgrade magic stuff to the HTTP request if it isn't done
       over SSL */
    result = Curl_http2_request_upgrade(&req, conn);
    if(result) {


      Curl_dyn_free(&req);















































      return result;
    }

  }






















































































































  result = Curl_http_cookies(data, conn, &req);
  if(!result)






    result = Curl_add_timecondition(data, &req);
  if(!result)

    result = Curl_add_custom_headers(data, FALSE, &req);




































































































  if(!result) {






















    http->postdata = NULL;  /* nothing to post at this point */
    if((httpreq == HTTPREQ_GET) ||

       (httpreq == HTTPREQ_HEAD))




      Curl_pgrsSetUploadSize(data, 0); /* nothing */





















    /* bodysend takes ownership of the 'req' memory on success */



    result = Curl_http_bodysend(data, conn, &req, httpreq);






  }






  if(result) {





    Curl_dyn_free(&req);



    return result;
  }




  if((http->postsize > -1) &&







     (http->postsize <= data->req.writebytecount) &&
     (http->sending != HTTPSEND_REQUEST))
    data->req.upload_done = TRUE;

  if(data->req.writebytecount) {
    /* if a request-body has been sent off, we make sure this progress is noted
       properly */
    Curl_pgrsSetUploadCounter(data, data->req.writebytecount);
    if(Curl_pgrsUpdate(data))
      result = CURLE_ABORTED_BY_CALLBACK;

    if(!http->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",
            data->req.writebytecount, http->postsize);
      data->req.upload_done = TRUE;
      data->req.keepon &= ~KEEP_SEND; /* we're done writing */
      data->req.exp100 = EXP100_SEND_DATA; /* already sent */
      Curl_expire_done(data, EXPIRE_100_TIMEOUT);
    }
  }

  if((conn->httpversion == 20) && data->req.upload_chunky)
    /* upload_chunky was set above to set up the request in a chunky fashion,
       but is disabled here again to avoid that the chunked encoded version is
       actually used when sending the request body over h2 */
    data->req.upload_chunky = FALSE;
  return result;
}

#endif /* USE_HYPER */

typedef enum {
  STATUS_UNKNOWN, /* not enough data to tell yet */
  STATUS_DONE, /* a status line was read */
  STATUS_BAD /* not a status line */
} statusline;

3100
3101
3102
3103
3104
3105
3106



3107

3108

3109





3110





3111









3112







3113


3114







3115



3116

























3117



















3118


3119







3120
3121



































3122





3123

3124



3125






3126


























3127

































3128












3129





3130








3131



































3132
3133
3134





3135
3136
3137




3138


3139


3140





3141




























































3142
3143
3144
3145
3146
3147
3148
#else
  (void)conn;
#endif /* CURL_DISABLE_RTSP */

  return checkhttpprefix(data, s, len);
}




static void print_http_error(struct Curl_easy *data)

{

  struct SingleRequest *k = &data->req;





  char *beg = Curl_dyn_ptr(&data->state.headerb);















  /* 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.
 */
CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
                                     struct connectdata *conn,







>
>
>
|
>

>

>
>
>
>
>
|
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
|
>
>
|
>
>
>
>
>
>
>
|
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
|
>
>
>
>
>
>
>
|
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
|
>
|
>
>
>
|
>
>
>
>
>
>

>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
|
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
<
|
>
>
>
>
>
|
|
|
>
>
>
>
|
>
>
|
>
>
|
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







3317
3318
3319
3320
3321
3322
3323
3324
3325
3326
3327
3328
3329
3330
3331
3332
3333
3334
3335
3336
3337
3338
3339
3340
3341
3342
3343
3344
3345
3346
3347
3348
3349
3350
3351
3352
3353
3354
3355
3356
3357
3358
3359
3360
3361
3362
3363
3364
3365
3366
3367
3368
3369
3370
3371
3372
3373
3374
3375
3376
3377
3378
3379
3380
3381
3382
3383
3384
3385
3386
3387
3388
3389
3390
3391
3392
3393
3394
3395
3396
3397
3398
3399
3400
3401
3402
3403
3404
3405
3406
3407
3408
3409
3410
3411
3412
3413
3414
3415
3416
3417
3418
3419
3420
3421
3422
3423
3424
3425
3426
3427
3428
3429
3430
3431
3432
3433
3434
3435
3436
3437
3438
3439
3440
3441
3442
3443
3444
3445
3446
3447
3448
3449
3450
3451
3452
3453
3454
3455
3456
3457
3458
3459
3460
3461
3462
3463
3464
3465
3466
3467
3468
3469
3470
3471
3472
3473
3474
3475
3476
3477
3478
3479
3480
3481
3482
3483
3484
3485
3486
3487
3488
3489
3490
3491
3492
3493
3494
3495
3496
3497
3498
3499
3500
3501
3502
3503
3504
3505
3506
3507
3508
3509
3510
3511
3512
3513
3514
3515
3516
3517
3518
3519
3520
3521
3522
3523
3524
3525
3526
3527
3528
3529
3530
3531
3532
3533
3534
3535
3536
3537
3538
3539
3540
3541
3542
3543
3544
3545
3546
3547
3548
3549
3550
3551
3552
3553
3554
3555
3556
3557
3558
3559
3560
3561
3562
3563
3564
3565
3566
3567
3568
3569
3570
3571
3572
3573
3574
3575
3576
3577
3578
3579
3580
3581
3582
3583
3584
3585
3586
3587
3588
3589
3590
3591
3592
3593
3594
3595
3596
3597
3598
3599
3600
3601
3602
3603
3604
3605
3606
3607
3608
3609
3610
3611
3612
3613
3614

3615
3616
3617
3618
3619
3620
3621
3622
3623
3624
3625
3626
3627
3628
3629
3630
3631
3632
3633
3634
3635
3636
3637
3638
3639
3640
3641
3642
3643
3644
3645
3646
3647
3648
3649
3650
3651
3652
3653
3654
3655
3656
3657
3658
3659
3660
3661
3662
3663
3664
3665
3666
3667
3668
3669
3670
3671
3672
3673
3674
3675
3676
3677
3678
3679
3680
3681
3682
3683
3684
3685
3686
3687
3688
3689
3690
3691
3692
3693
3694
3695
3696
3697
3698
3699
3700
3701
3702
3703
3704
3705
3706
3707
#else
  (void)conn;
#endif /* CURL_DISABLE_RTSP */

  return checkhttpprefix(data, s, len);
}

/*
 * Curl_http_header() parses a single response header.
 */
CURLcode Curl_http_header(struct Curl_easy *data, struct connectdata *conn,
                          char *headp)
{
  CURLcode result;
  struct SingleRequest *k = &data->req;
  /* Check for Content-Length: header lines to get size */
  if(!k->http_bodyless &&
     !data->set.ignorecl && checkprefix("Content-Length:", headp)) {
    curl_off_t contentlength;
    CURLofft offt = curlx_strtoofft(headp + 15, NULL, 10, &contentlength);

    if(offt == CURL_OFFT_OK) {
      if(data->set.max_filesize &&
         contentlength > data->set.max_filesize) {
        failf(data, "Maximum file size exceeded");
        return CURLE_FILESIZE_EXCEEDED;
      }
      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 if(offt == CURL_OFFT_FLOW) {
      /* out of range */
      if(data->set.max_filesize) {
        failf(data, "Maximum file size exceeded");
        return CURLE_FILESIZE_EXCEEDED;
      }
      streamclose(conn, "overflow content-length");
      infof(data, "Overflow Content-Length: value!\n");
    }
    else {
      /* negative or just rubbish - bad HTTP */
      failf(data, "Invalid Content-Length: value");
      return CURLE_WEIRD_SERVER_REPLY;
    }
  }
  /* check for Content-Type: header lines to get the MIME-type */
  else if(checkprefix("Content-Type:", headp)) {
    char *contenttype = Curl_copy_header_value(headp);
    if(!contenttype)
      return CURLE_OUT_OF_MEMORY;
    if(!*contenttype)
      /* ignore empty data */
      free(contenttype);
    else {
      Curl_safefree(data->info.contenttype);
      data->info.contenttype = contenttype;
    }
  }
#ifndef CURL_DISABLE_PROXY
  else if((conn->httpversion == 10) &&
          conn->bits.httpproxy &&
          Curl_compareheader(headp, "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(headp, "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");
  }
#endif
  else if((conn->httpversion == 10) &&
          Curl_compareheader(headp, "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(headp, "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.
     */
    streamclose(conn, "Connection: close used");
  }
  else if(!k->http_bodyless && checkprefix("Transfer-Encoding:", headp)) {
    /* 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. */

    result = Curl_build_unencoding_stack(data, headp + 18, TRUE);
    if(result)
      return result;
  }
  else if(!k->http_bodyless && checkprefix("Content-Encoding:", headp) &&
          data->set.str[STRING_ENCODING]) {
    /*
     * 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
     */
    result = Curl_build_unencoding_stack(data, headp + 17, FALSE);
    if(result)
      return result;
  }
  else if(checkprefix("Retry-After:", headp)) {
    /* Retry-After = HTTP-date / delay-seconds */
    curl_off_t retry_after = 0; /* zero for unknown or "now" */
    time_t date = Curl_getdate_capped(&headp[12]);
    if(-1 == date) {
      /* not a date, try it as a decimal number */
      (void)curlx_strtoofft(&headp[12], NULL, 10, &retry_after);
    }
    else
      /* convert date to number of seconds into the future */
      retry_after = date - time(NULL);
    data->info.retry_after = retry_after; /* store it */
  }
  else if(!k->http_bodyless && checkprefix("Content-Range:", headp)) {
    /* 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 = headp + 14;

    /* Move forward until first digit or asterisk */
    while(*ptr && !ISDIGIT(*ptr) && *ptr != '*')
      ptr++;

    /* if it truly stopped on a digit */
    if(ISDIGIT(*ptr)) {
      if(!curlx_strtoofft(ptr, NULL, 10, &k->offset)) {
        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 && data->state.cookie_engine &&
          checkprefix("Set-Cookie:", headp)) {
    Curl_share_lock(data, CURL_LOCK_DATA_COOKIE,
                    CURL_LOCK_ACCESS_SINGLE);
    Curl_cookie_add(data,
                    data->cookies, TRUE, FALSE, headp + 11,
                    /* If there is a custom-set Host: name, use it
                       here, or else use real peer host name. */
                    data->state.aptr.cookiehost?
                    data->state.aptr.cookiehost:conn->host.name,
                    data->state.up.path,
                    (conn->handler->protocol&CURLPROTO_HTTPS)?
                    TRUE:FALSE);
    Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE);
  }
#endif
  else if(!k->http_bodyless && checkprefix("Last-Modified:", headp) &&
          (data->set.timecondition || data->set.get_filetime) ) {
    k->timeofdoc = Curl_getdate_capped(headp + strlen("Last-Modified:"));
    if(data->set.get_filetime)
      data->info.filetime = k->timeofdoc;
  }
  else if((checkprefix("WWW-Authenticate:", headp) &&
           (401 == k->httpcode)) ||
          (checkprefix("Proxy-authenticate:", headp) &&
           (407 == k->httpcode))) {

    bool proxy = (k->httpcode == 407) ? TRUE : FALSE;
    char *auth = Curl_copy_header_value(headp);
    if(!auth)
      return CURLE_OUT_OF_MEMORY;

    result = Curl_http_input_auth(data, proxy, auth);

    free(auth);

    if(result)
      return result;
  }
#ifdef USE_SPNEGO
  else if(checkprefix("Persistent-Auth", headp)) {
    struct negotiatedata *negdata = &conn->negotiate;
    struct auth *authp = &data->state.authhost;
    if(authp->picked == CURLAUTH_NEGOTIATE) {
      char *persistentauth = Curl_copy_header_value(headp);
      if(!persistentauth)
        return CURLE_OUT_OF_MEMORY;
      negdata->noauthpersist = checkprefix("false", persistentauth)?
        TRUE:FALSE;
      negdata->havenoauthpersist = TRUE;
      infof(data, "Negotiate: noauthpersist -> %d, header part: %s",
            negdata->noauthpersist, persistentauth);
      free(persistentauth);
    }
  }
#endif
  else if((k->httpcode >= 300 && k->httpcode < 400) &&
          checkprefix("Location:", headp) &&
          !data->req.location) {
    /* this is the URL that the server advises us to use instead */
    char *location = Curl_copy_header_value(headp);
    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(data, conn);
        if(result)
          return result;
      }
    }
  }

#ifdef USE_HSTS
  /* If enabled, the header is incoming and this is over HTTPS */
  else if(data->hsts && checkprefix("Strict-Transport-Security:", headp) &&
          (conn->handler->flags & PROTOPT_SSL)) {
    CURLcode check =
      Curl_hsts_parse(data->hsts, data->state.up.hostname,
                      &headp[ sizeof("Strict-Transport-Security:") -1 ]);
    if(check)
      infof(data, "Illegal STS header skipped\n");
#ifdef DEBUGBUILD
    else
      infof(data, "Parsed STS header fine (%zu entries)\n",
            data->hsts->list.size);
#endif
  }
#endif
#ifndef CURL_DISABLE_ALTSVC
  /* If enabled, the header is incoming and this is over HTTPS */
  else if(data->asi && checkprefix("Alt-Svc:", headp) &&
          ((conn->handler->flags & PROTOPT_SSL) ||
#ifdef CURLDEBUG
           /* allow debug builds to circumvent the HTTPS restriction */
           getenv("CURL_ALTSVC_HTTP")
#else
           0
#endif
            )) {
    /* the ALPN of the current request */
    enum alpnid id = (conn->httpversion == 20) ? ALPN_h2 : ALPN_h1;
    result = Curl_altsvc_parse(data, data->asi,
                               &headp[ strlen("Alt-Svc:") ],
                               id, conn->host.name,
                               curlx_uitous(conn->remote_port));
    if(result)
      return result;
  }

#endif
  else if(conn->handler->protocol & CURLPROTO_RTSP) {
    result = Curl_rtsp_parseheader(data, headp);
    if(result)
      return result;
  }
  return CURLE_OK;
}

/*
 * Called after the first HTTP response line (the status line) has been
 * received and parsed.
 */

CURLcode Curl_http_statusline(struct Curl_easy *data,
                              struct connectdata *conn)
{
  struct SingleRequest *k = &data->req;
  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->state.resume_from && data->state.httpreq == HTTPREQ_GET &&
     k->httpcode == 416) {
    /* "Requested Range Not Satisfiable", just proceed and
       pretend this is no error */
    k->ignorebody = TRUE; /* Avoid appending error msg to good data. */
  }

  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)) {
    DEBUGF(infof(data, "HTTP/2 found, allow multiplexing\n"));
    /* HTTP/2 cannot avoid multiplexing since it is a core functionality
       of the protocol */
    conn->bundle->multiuse = BUNDLE_MULTIPLEX;
  }
  else if(conn->httpversion >= 11 &&
          !conn->bits.close) {
    /* If HTTP version is >= 1.1 and connection is persistent */
    DEBUGF(infof(data,
                 "HTTP 1.1 or later with persistent connection\n"));
  }

  k->http_bodyless = k->httpcode >= 100 && k->httpcode < 200;
  switch(k->httpcode) {
  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;
    /* FALLTHROUGH */
  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. */
    k->size = 0;
    k->maxdownload = 0;
    k->http_bodyless = TRUE;
    break;
  default:
    break;
  }
  return CURLE_OK;
}

/*
 * Read any HTTP header lines from the server and pass them to the client app.
 */
CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
                                     struct connectdata *conn,
3185
3186
3187
3188
3189
3190
3191
3192
3193
3194
3195
3196
3197
3198
3199

        if(st == STATUS_BAD) {
          /* this is not the beginning of a protocol first header line */
          k->header = FALSE;
          k->badheader = HEADER_ALLBAD;
          streamclose(conn, "bad HTTP: No end-of-message indicator");
          if(!data->set.http09_allowed) {
            failf(data, "Received HTTP/0.9 when not allowed\n");
            return CURLE_UNSUPPORTED_PROTOCOL;
          }
          break;
        }
      }

      break; /* read more and try again */







|







3744
3745
3746
3747
3748
3749
3750
3751
3752
3753
3754
3755
3756
3757
3758

        if(st == STATUS_BAD) {
          /* this is not the beginning of a protocol first header line */
          k->header = FALSE;
          k->badheader = HEADER_ALLBAD;
          streamclose(conn, "bad HTTP: No end-of-message indicator");
          if(!data->set.http09_allowed) {
            failf(data, "Received HTTP/0.9 when not allowed");
            return CURLE_UNSUPPORTED_PROTOCOL;
          }
          break;
        }
      }

      break; /* read more and try again */
3220
3221
3222
3223
3224
3225
3226
3227
3228
3229
3230
3231
3232
3233
3234
      statusline st = checkprotoprefix(data, conn,
                                       Curl_dyn_ptr(&data->state.headerb),
                                       Curl_dyn_len(&data->state.headerb));
      if(st == STATUS_BAD) {
        streamclose(conn, "bad HTTP: No end-of-message indicator");
        /* this is not the beginning of a protocol first header line */
        if(!data->set.http09_allowed) {
          failf(data, "Received HTTP/0.9 when not allowed\n");
          return CURLE_UNSUPPORTED_PROTOCOL;
        }
        k->header = FALSE;
        if(*nread)
          /* since there's more, this is a partial bad header */
          k->badheader = HEADER_PARTHEADER;
        else {







|







3779
3780
3781
3782
3783
3784
3785
3786
3787
3788
3789
3790
3791
3792
3793
      statusline st = checkprotoprefix(data, conn,
                                       Curl_dyn_ptr(&data->state.headerb),
                                       Curl_dyn_len(&data->state.headerb));
      if(st == STATUS_BAD) {
        streamclose(conn, "bad HTTP: No end-of-message indicator");
        /* this is not the beginning of a protocol first header line */
        if(!data->set.http09_allowed) {
          failf(data, "Received HTTP/0.9 when not allowed");
          return CURLE_UNSUPPORTED_PROTOCOL;
        }
        k->header = FALSE;
        if(*nread)
          /* since there's more, this is a partial bad header */
          k->badheader = HEADER_PARTHEADER;
        else {
3295
3296
3297
3298
3299
3300
3301
3302
3303
3304
3305
3306
3307
3308
3309

            /* we'll get more headers (HTTP/2 response) */
            k->header = TRUE;
            k->headerline = 0; /* restart the header line counter */

            /* 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;
          }
          else {
            /* Switching to another protocol (e.g. WebSocket) */
            k->header = FALSE; /* no more header to parse! */







|







3854
3855
3856
3857
3858
3859
3860
3861
3862
3863
3864
3865
3866
3867
3868

            /* we'll get more headers (HTTP/2 response) */
            k->header = TRUE;
            k->headerline = 0; /* restart the header line counter */

            /* switch to http2 now. The bytes after response headers
               are also processed here, otherwise they are lost. */
            result = Curl_http2_switched(data, k->str, *nread);
            if(result)
              return result;
            *nread = 0;
          }
          else {
            /* Switching to another protocol (e.g. WebSocket) */
            k->header = FALSE; /* no more header to parse! */
3361
3362
3363
3364
3365
3366
3367
3368
3369
3370
3371
3372
3373
3374
3375
3376
3377
3378
3379
3380
3381
3382
3383
3384
3385
3386
3387
3388
3389
3390
3391
3392










3393
3394
3395
3396
3397
3398
3399
3400
3401
3402
3403
3404
3405
3406
3407
        conn->http_negotiate_state = GSS_AUTHSUCC;
      }
      if((conn->proxy_negotiate_state == GSS_AUTHDONE) &&
         (data->req.httpcode != 407)) {
        conn->proxy_negotiate_state = GSS_AUTHSUCC;
      }
#endif
      /*
       * 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 = Curl_dyn_len(&data->state.headerb);
      result = Curl_client_write(conn, writetype,
                                 Curl_dyn_ptr(&data->state.headerb),
                                 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;

      /* 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) {







<
<
<
<
<
<
<
<
<








|







>
>
>
>
>
>
>
>
>
>







|







3920
3921
3922
3923
3924
3925
3926









3927
3928
3929
3930
3931
3932
3933
3934
3935
3936
3937
3938
3939
3940
3941
3942
3943
3944
3945
3946
3947
3948
3949
3950
3951
3952
3953
3954
3955
3956
3957
3958
3959
3960
3961
3962
3963
3964
3965
3966
3967
        conn->http_negotiate_state = GSS_AUTHSUCC;
      }
      if((conn->proxy_negotiate_state == GSS_AUTHDONE) &&
         (data->req.httpcode != 407)) {
        conn->proxy_negotiate_state = GSS_AUTHSUCC;
      }
#endif










      /* now, only output this if the header AND body are requested:
       */
      writetype = CLIENTWRITE_HEADER;
      if(data->set.include_header)
        writetype |= CLIENTWRITE_BODY;

      headerlen = Curl_dyn_len(&data->state.headerb);
      result = Curl_client_write(data, writetype,
                                 Curl_dyn_ptr(&data->state.headerb),
                                 headerlen);
      if(result)
        return result;

      data->info.header_size += (long)headerlen;
      data->req.headerbytecount += (long)headerlen;

      /*
       * When all the headers have been parsed, see if we should give
       * up and return an error.
       */
      if(http_should_fail(data)) {
        failf(data, "The requested URL returned error: %d",
              k->httpcode);
        return CURLE_HTTP_RETURNED_ERROR;
      }

      data->req.deductheadercount =
        (100 <= k->httpcode && 199 >= k->httpcode)?data->req.headerbytecount:0;

      /* 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(data);

      if(result)
        return result;

      if(k->httpcode >= 300) {
        if((!conn->bits.authneg) && !conn->bits.close &&
           !conn->bits.rewindaftersend) {
3431
3432
3433
3434
3435
3436
3437
3438
3439
3440
3441
3442
3443
3444
3445
3446
3447
3448
3449
3450
3451
3452
3453
3454
3455
3456
3457
3458
            if(!k->upload_done) {
              if((k->httpcode == 417) && data->state.expect100header) {
                /* 417 Expectation Failed - try again without the Expect
                   header */
                infof(data, "Got 417 while waiting for a 100\n");
                data->state.disableexpect = TRUE;
                DEBUGASSERT(!data->req.newurl);
                data->req.newurl = strdup(conn->data->change.url);
                Curl_done_sending(conn, k);
              }
              else if(data->set.http_keep_sending_on_error) {
                infof(data, "HTTP error before end of send, keep sending\n");
                if(k->exp100 > EXP100_SEND_DATA) {
                  k->exp100 = EXP100_SEND_DATA;
                  k->keepon |= KEEP_SEND;
                }
              }
              else {
                infof(data, "HTTP error before end of send, stop sending\n");
                streamclose(conn, "Stop sending data before everything sent");
                result = Curl_done_sending(conn, k);
                if(result)
                  return result;
                k->upload_done = TRUE;
                if(data->state.expect100header)
                  k->exp100 = EXP100_FAILED;
              }
            }







|
|











|







3991
3992
3993
3994
3995
3996
3997
3998
3999
4000
4001
4002
4003
4004
4005
4006
4007
4008
4009
4010
4011
4012
4013
4014
4015
4016
4017
4018
            if(!k->upload_done) {
              if((k->httpcode == 417) && data->state.expect100header) {
                /* 417 Expectation Failed - try again without the Expect
                   header */
                infof(data, "Got 417 while waiting for a 100\n");
                data->state.disableexpect = TRUE;
                DEBUGASSERT(!data->req.newurl);
                data->req.newurl = strdup(data->change.url);
                Curl_done_sending(data, k);
              }
              else if(data->set.http_keep_sending_on_error) {
                infof(data, "HTTP error before end of send, keep sending\n");
                if(k->exp100 > EXP100_SEND_DATA) {
                  k->exp100 = EXP100_SEND_DATA;
                  k->keepon |= KEEP_SEND;
                }
              }
              else {
                infof(data, "HTTP error before end of send, stop sending\n");
                streamclose(conn, "Stop sending data before everything sent");
                result = Curl_done_sending(data, k);
                if(result)
                  return result;
                k->upload_done = TRUE;
                if(data->state.expect100header)
                  k->exp100 = EXP100_FAILED;
              }
            }
3652
3653
3654
3655
3656
3657
3658
3659
3660
3661
3662
3663
3664
3665
3666
3667
3668
3669
3670
3671
3672
3673
3674
3675
3676
3677
3678
3679
3680
3681
3682
3683
3684
3685
3686
3687
3688
3689
3690
3691
3692
3693
3694
3695
3696
3697
3698
3699
3700
3701
3702
3703
3704
3705
3706
3707
3708
3709
3710
3711
3712
3713
3714
3715
3716
3717
3718
3719
3720
3721
3722
3723
3724
3725
3726
3727
3728
3729
3730
3731
3732
3733
3734
3735
3736
3737
3738
3739
3740
3741
3742
3743
3744
3745
3746
3747
3748
3749
3750
3751
3752
3753
3754
3755
3756
3757
3758
3759
3760
3761
3762
3763
3764
3765
3766
3767
3768
3769
3770
3771
3772
3773
3774
3775
3776
3777
3778
3779
3780
3781
3782
3783
3784
3785
3786
3787
3788
3789
3790
3791
3792
3793
3794
3795
3796
3797
3798
3799
3800
3801
3802
3803
3804
3805
3806
3807
3808
3809
3810
3811
3812
3813
3814
3815
3816
3817
3818
3819
3820
3821
3822
3823
3824
3825
3826
3827
3828
3829
3830
3831
3832
3833
3834
3835
3836
3837
3838
3839
3840
3841
3842
3843
3844
3845
3846
3847
3848
3849
3850
3851
3852
3853
3854
3855
3856
3857
3858
3859
3860
3861
3862
3863
3864
3865
3866
3867
3868
3869
3870
3871
3872
3873
3874
3875
3876
3877
3878
3879
3880
3881
3882
3883
3884
3885
3886
3887
3888
3889
3890
3891
3892
3893
3894
3895
3896
3897
3898
3899
3900
3901
3902
3903
3904
3905
3906
3907
3908
3909
3910
3911
3912
3913
3914
3915
3916
3917
3918
3919
3920
3921
3922
3923
3924
3925
3926
3927
3928
3929
3930
3931
3932
3933
3934
3935
3936
3937
3938
3939
3940
3941
3942
3943
3944
3945
3946
3947
3948
3949
3950
3951
3952
3953
3954
3955
3956
3957
3958
3959
3960
3961
3962
3963
3964
3965
3966
3967
3968
3969
3970
3971
3972
3973
3974
3975
3976
3977
3978
3979
3980
3981
3982
3983
3984
3985
3986
3987
3988
3989
3990
3991
3992
3993
3994
3995
3996
3997
3998
3999
4000
4001
4002
4003
4004
4005
4006
4007
4008
4009
4010
4011
4012
4013
4014
4015
4016
4017
4018
4019
4020
4021
4022
4023
4024
4025
4026
4027
4028
4029
4030
4031
4032
4033
4034
4035
4036
4037
4038
4039
4040
4041
4042
4043
4044
4045
4046
4047
4048
4049
4050
4051
4052
4053
4054
4055
4056
        }
        else {
          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->state.resume_from && data->state.httpreq == HTTPREQ_GET &&
             k->httpcode == 416) {
          /* "Requested Range Not Satisfiable", just proceed and
             pretend this is no error */
          k->ignorebody = TRUE; /* Avoid appending error msg to good data. */
        }
        else if(data->set.http_fail_on_error && (k->httpcode >= 400) &&
                ((k->httpcode != 401) || !conn->bits.user_passwd)
#ifndef CURL_DISABLE_PROXY
                && ((k->httpcode != 407) || !conn->bits.proxy_user_passwd)
#endif
          ) {
          /* 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)) {
          DEBUGF(infof(data, "HTTP/2 found, allow multiplexing\n"));
          /* HTTP/2 cannot avoid multiplexing since it is a core functionality
             of the protocol */
          conn->bundle->multiuse = BUNDLE_MULTIPLEX;
        }
        else if(conn->httpversion >= 11 &&
                !conn->bits.close) {
          /* If HTTP version is >= 1.1 and connection is persistent */
          DEBUGF(infof(data,
                       "HTTP 1.1 or later with persistent connection\n"));
        }

        k->http_bodyless = k->httpcode >= 100 && k->httpcode < 200;
        switch(k->httpcode) {
        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;
          /* FALLTHROUGH */
        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. */
          k->size = 0;
          k->maxdownload = 0;
          k->http_bodyless = TRUE;
          break;
        default:
          break;
        }
      }
      else {
        k->header = FALSE;   /* this is not a header line */
        break;
      }
    }

    result = Curl_convert_from_network(data, headp, strlen(headp));
    /* Curl_convert_from_network calls failf if unsuccessful */
    if(result)
      return result;

    /* Check for Content-Length: header lines to get size */
    if(!k->http_bodyless &&
       !data->set.ignorecl && checkprefix("Content-Length:", headp)) {
      curl_off_t contentlength;
      CURLofft offt = curlx_strtoofft(headp + 15, NULL, 10, &contentlength);

      if(offt == CURL_OFFT_OK) {
        if(data->set.max_filesize &&
           contentlength > data->set.max_filesize) {
          failf(data, "Maximum file size exceeded");
          return CURLE_FILESIZE_EXCEEDED;
        }
        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 if(offt == CURL_OFFT_FLOW) {
        /* out of range */
        if(data->set.max_filesize) {
          failf(data, "Maximum file size exceeded");
          return CURLE_FILESIZE_EXCEEDED;
        }
        streamclose(conn, "overflow content-length");
        infof(data, "Overflow Content-Length: value!\n");
      }
      else {
        /* negative or just rubbish - bad HTTP */
        failf(data, "Invalid Content-Length: value");
        return CURLE_WEIRD_SERVER_REPLY;
      }
    }
    /* check for Content-Type: header lines to get the MIME-type */
    else if(checkprefix("Content-Type:", headp)) {
      char *contenttype = Curl_copy_header_value(headp);
      if(!contenttype)
        return CURLE_OUT_OF_MEMORY;
      if(!*contenttype)
        /* ignore empty data */
        free(contenttype);
      else {
        Curl_safefree(data->info.contenttype);
        data->info.contenttype = contenttype;
      }
    }
#ifndef CURL_DISABLE_PROXY
    else if((conn->httpversion == 10) &&
            conn->bits.httpproxy &&
            Curl_compareheader(headp, "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(headp, "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");
    }
#endif
    else if((conn->httpversion == 10) &&
            Curl_compareheader(headp, "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(headp, "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.
       */
      streamclose(conn, "Connection: close used");
    }
    else if(!k->http_bodyless && checkprefix("Transfer-Encoding:", headp)) {
      /* 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. */

      result = Curl_build_unencoding_stack(conn, headp + 18, TRUE);
      if(result)
        return result;
    }
    else if(!k->http_bodyless && checkprefix("Content-Encoding:", headp) &&
            data->set.str[STRING_ENCODING]) {
      /*
       * 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
       */
      result = Curl_build_unencoding_stack(conn, headp + 17, FALSE);
      if(result)
        return result;
    }
    else if(checkprefix("Retry-After:", headp)) {
      /* Retry-After = HTTP-date / delay-seconds */
      curl_off_t retry_after = 0; /* zero for unknown or "now" */
      time_t date = Curl_getdate_capped(&headp[12]);
      if(-1 == date) {
        /* not a date, try it as a decimal number */
        (void)curlx_strtoofft(&headp[12], NULL, 10, &retry_after);
      }
      else
        /* convert date to number of seconds into the future */
        retry_after = date - time(NULL);
      data->info.retry_after = retry_after; /* store it */
    }
    else if(!k->http_bodyless && checkprefix("Content-Range:", headp)) {
      /* 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 = headp + 14;

      /* Move forward until first digit or asterisk */
      while(*ptr && !ISDIGIT(*ptr) && *ptr != '*')
        ptr++;

      /* if it truly stopped on a digit */
      if(ISDIGIT(*ptr)) {
        if(!curlx_strtoofft(ptr, NULL, 10, &k->offset)) {
          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 && data->state.cookie_engine &&
            checkprefix("Set-Cookie:", headp)) {
      Curl_share_lock(data, CURL_LOCK_DATA_COOKIE,
                      CURL_LOCK_ACCESS_SINGLE);
      Curl_cookie_add(data,
                      data->cookies, TRUE, FALSE, headp + 11,
                      /* If there is a custom-set Host: name, use it
                         here, or else use real peer host name. */
                      data->state.aptr.cookiehost?
                      data->state.aptr.cookiehost:conn->host.name,
                      data->state.up.path,
                      (conn->handler->protocol&CURLPROTO_HTTPS)?
                      TRUE:FALSE);
      Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE);
    }
#endif
    else if(!k->http_bodyless && checkprefix("Last-Modified:", headp) &&
            (data->set.timecondition || data->set.get_filetime) ) {
      k->timeofdoc = Curl_getdate_capped(headp + strlen("Last-Modified:"));
      if(data->set.get_filetime)
        data->info.filetime = k->timeofdoc;
    }
    else if((checkprefix("WWW-Authenticate:", headp) &&
             (401 == k->httpcode)) ||
            (checkprefix("Proxy-authenticate:", headp) &&
             (407 == k->httpcode))) {

      bool proxy = (k->httpcode == 407) ? TRUE : FALSE;
      char *auth = Curl_copy_header_value(headp);
      if(!auth)
        return CURLE_OUT_OF_MEMORY;

      result = Curl_http_input_auth(conn, proxy, auth);

      free(auth);

      if(result)
        return result;
    }
#ifdef USE_SPNEGO
    else if(checkprefix("Persistent-Auth", headp)) {
      struct negotiatedata *negdata = &conn->negotiate;
      struct auth *authp = &data->state.authhost;
      if(authp->picked == CURLAUTH_NEGOTIATE) {
        char *persistentauth = Curl_copy_header_value(headp);
        if(!persistentauth)
          return CURLE_OUT_OF_MEMORY;
        negdata->noauthpersist = checkprefix("false", persistentauth)?
          TRUE:FALSE;
        negdata->havenoauthpersist = TRUE;
        infof(data, "Negotiate: noauthpersist -> %d, header part: %s",
          negdata->noauthpersist, persistentauth);
        free(persistentauth);
      }
    }
#endif
    else if((k->httpcode >= 300 && k->httpcode < 400) &&
            checkprefix("Location:", headp) &&
            !data->req.location) {
      /* this is the URL that the server advises us to use instead */
      char *location = Curl_copy_header_value(headp);
      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;
        }
      }
    }

#ifdef USE_HSTS
    /* If enabled, the header is incoming and this is over HTTPS */
    else if(data->hsts && checkprefix("Strict-Transport-Security:", headp) &&
            (conn->handler->flags & PROTOPT_SSL)) {
      CURLcode check =
        Curl_hsts_parse(data->hsts, data->state.up.hostname,
                        &headp[ sizeof("Strict-Transport-Security:") -1 ]);
      if(check)
        infof(data, "Illegal STS header skipped\n");
#ifdef DEBUGBUILD
      else
        infof(data, "Parsed STS header fine (%zu entries)\n",
              data->hsts->list.size);
#endif
    }
#endif
#ifndef CURL_DISABLE_ALTSVC
    /* If enabled, the header is incoming and this is over HTTPS */
    else if(data->asi && checkprefix("Alt-Svc:", headp) &&
            ((conn->handler->flags & PROTOPT_SSL) ||
#ifdef CURLDEBUG
             /* allow debug builds to circumvent the HTTPS restriction */
             getenv("CURL_ALTSVC_HTTP")
#else
             0
#endif
              )) {
      /* the ALPN of the current request */
      enum alpnid id = (conn->httpversion == 20) ? ALPN_h2 : ALPN_h1;
      result = Curl_altsvc_parse(data, data->asi,
                                 &headp[ strlen("Alt-Svc:") ],
                                 id, conn->host.name,
                                 curlx_uitous(conn->remote_port));
      if(result)
        return result;
    }
#endif
    else if(conn->handler->protocol & CURLPROTO_RTSP) {
      result = Curl_rtsp_parseheader(conn, headp);
      if(result)
        return result;
    }

    /*
     * End of header-checks. Write them to the client.
     */

    writetype = CLIENTWRITE_HEADER;
    if(data->set.include_header)
      writetype |= CLIENTWRITE_BODY;

    Curl_debug(data, CURLINFO_HEADER_IN, headp,
               Curl_dyn_len(&data->state.headerb));

    result = Curl_client_write(conn, writetype, headp,
                               Curl_dyn_len(&data->state.headerb));
    if(result)
      return result;

    data->info.header_size += Curl_dyn_len(&data->state.headerb);
    data->req.headerbytecount += Curl_dyn_len(&data->state.headerb);








<
|
<
<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<












<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
<
<
<
|
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<












|







4212
4213
4214
4215
4216
4217
4218

4219





4220
























4221












































4222
4223
4224
4225
4226
4227
4228
4229
4230
4231
4232
4233



































































































































































































4234



4235
4236
























































































4237
4238
4239
4240
4241
4242
4243
4244
4245
4246
4247
4248
4249
4250
4251
4252
4253
4254
4255
4256
        }
        else {
          nc = 0;
        }
      }

      if(nc) {

        result = Curl_http_statusline(data, conn);





        if(result)
























          return result;












































      }
      else {
        k->header = FALSE;   /* this is not a header line */
        break;
      }
    }

    result = Curl_convert_from_network(data, headp, strlen(headp));
    /* Curl_convert_from_network calls failf if unsuccessful */
    if(result)
      return result;




































































































































































































    result = Curl_http_header(data, conn, headp);



    if(result)
      return result;

























































































    /*
     * End of header-checks. Write them to the client.
     */

    writetype = CLIENTWRITE_HEADER;
    if(data->set.include_header)
      writetype |= CLIENTWRITE_BODY;

    Curl_debug(data, CURLINFO_HEADER_IN, headp,
               Curl_dyn_len(&data->state.headerb));

    result = Curl_client_write(data, writetype, headp,
                               Curl_dyn_len(&data->state.headerb));
    if(result)
      return result;

    data->info.header_size += Curl_dyn_len(&data->state.headerb);
    data->req.headerbytecount += Curl_dyn_len(&data->state.headerb);

Changes to jni/curl/lib/http.h.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25









26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45

46

47
48
49
50
51



52
53

54




55
56

57




58
59
60
61































62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
#ifndef HEADER_CURL_HTTP_H
#define HEADER_CURL_HTTP_H
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2020, 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 https://curl.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 */
bool Curl_compareheader(const char *headerline,  /* line to check */
                        const char *header,   /* header keyword _with_ colon */
                        const char *content); /* content string to find */

char *Curl_copy_header_value(const char *header);

char *Curl_checkProxyheaders(const struct connectdata *conn,

                             const char *thisheader);

CURLcode Curl_buffer_send(struct dynbuf *in,
                          struct connectdata *conn,
                          curl_off_t *bytes_written,
                          size_t included_body_bytes,
                          int socketindex);




CURLcode Curl_add_timecondition(const struct connectdata *conn,

                                struct dynbuf *buf);




CURLcode Curl_add_custom_headers(struct connectdata *conn,
                                 bool is_connect,

                                 struct dynbuf *req_buffer);




CURLcode Curl_http_compile_trailers(struct curl_slist *trailers,
                                    struct dynbuf *buf,
                                    struct Curl_easy *handle);
































/* protocol-specific functions set up to be called by the main engine */
CURLcode Curl_http(struct connectdata *conn, bool *done);
CURLcode Curl_http_done(struct connectdata *, CURLcode, bool premature);
CURLcode Curl_http_connect(struct connectdata *conn, bool *done);

/* These functions are in http.c */
CURLcode Curl_http_input_auth(struct connectdata *conn, bool proxy,
                              const char *auth);
CURLcode Curl_http_auth_act(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 */










|















>
>
>
>
>
>
>
>
>



















|
>

>

|



>
>
>

|
>
|
>
>
>
>
|

>
|
>
>
>
>




>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

|
|
|


|

|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
#ifndef HEADER_CURL_HTTP_H
#define HEADER_CURL_HTTP_H
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2021, 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 https://curl.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"

typedef enum {
  HTTPREQ_GET,
  HTTPREQ_POST,
  HTTPREQ_POST_FORM, /* we make a difference internally */
  HTTPREQ_POST_MIME, /* we make a difference internally */
  HTTPREQ_PUT,
  HTTPREQ_HEAD
} Curl_HttpReq;

#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 */
bool Curl_compareheader(const char *headerline,  /* line to check */
                        const char *header,   /* header keyword _with_ colon */
                        const char *content); /* content string to find */

char *Curl_copy_header_value(const char *header);

char *Curl_checkProxyheaders(struct Curl_easy *data,
                             const struct connectdata *conn,
                             const char *thisheader);
#ifndef USE_HYPER
CURLcode Curl_buffer_send(struct dynbuf *in,
                          struct Curl_easy *data,
                          curl_off_t *bytes_written,
                          size_t included_body_bytes,
                          int socketindex);
#else
#define Curl_buffer_send(a,b,c,d,e) CURLE_OK
#endif

CURLcode Curl_add_timecondition(struct Curl_easy *data,
#ifndef USE_HYPER
                                struct dynbuf *req
#else
                                void *headers
#endif
  );
CURLcode Curl_add_custom_headers(struct Curl_easy *data,
                                 bool is_connect,
#ifndef USE_HYPER
                                 struct dynbuf *req
#else
                                 void *headers
#endif
  );
CURLcode Curl_http_compile_trailers(struct curl_slist *trailers,
                                    struct dynbuf *buf,
                                    struct Curl_easy *handle);

void Curl_http_method(struct Curl_easy *data, struct connectdata *conn,
                      const char **method, Curl_HttpReq *);
CURLcode Curl_http_useragent(struct Curl_easy *data);
CURLcode Curl_http_host(struct Curl_easy *data, struct connectdata *conn);
CURLcode Curl_http_target(struct Curl_easy *data, struct connectdata *conn,
                          struct dynbuf *req);
CURLcode Curl_http_statusline(struct Curl_easy *data,
                              struct connectdata *conn);
CURLcode Curl_http_header(struct Curl_easy *data, struct connectdata *conn,
                          char *headp);
CURLcode Curl_http_body(struct Curl_easy *data, struct connectdata *conn,
                        Curl_HttpReq httpreq,
                        const char **teep);
CURLcode Curl_http_bodysend(struct Curl_easy *data, struct connectdata *conn,
                            struct dynbuf *r, Curl_HttpReq httpreq);
#ifndef CURL_DISABLE_COOKIES
CURLcode Curl_http_cookies(struct Curl_easy *data,
                           struct connectdata *conn,
                           struct dynbuf *r);
#else
#define Curl_http_cookies(a,b,c) CURLE_OK
#endif
CURLcode Curl_http_resume(struct Curl_easy *data,
                          struct connectdata *conn,
                          Curl_HttpReq httpreq);
CURLcode Curl_http_range(struct Curl_easy *data,
                         Curl_HttpReq httpreq);
CURLcode Curl_http_firstwrite(struct Curl_easy *data,
                              struct connectdata *conn,
                              bool *done);

/* protocol-specific functions set up to be called by the main engine */
CURLcode Curl_http(struct Curl_easy *data, bool *done);
CURLcode Curl_http_done(struct Curl_easy *data, CURLcode, bool premature);
CURLcode Curl_http_connect(struct Curl_easy *data, bool *done);

/* These functions are in http.c */
CURLcode Curl_http_input_auth(struct Curl_easy *data, bool proxy,
                              const char *auth);
CURLcode Curl_http_auth_act(struct Curl_easy *data);

/* 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 */

111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
 ***************************************************************************/
struct HTTP {
  curl_mimepart *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 */

  /* For FORM posting */
  curl_mimepart form;

  struct back {
    curl_read_callback fread_func; /* backup storage for fread pointer */
    void *fread_in;           /* backup storage for fread_in pointer */







<







166
167
168
169
170
171
172

173
174
175
176
177
178
179
 ***************************************************************************/
struct HTTP {
  curl_mimepart *sendit;
  curl_off_t postsize; /* off_t to handle large file sizes */
  const char *postdata;

  const char *p_pragma;      /* Pragma: string */


  /* For FORM posting */
  curl_mimepart form;

  struct back {
    curl_read_callback fread_func; /* backup storage for fread pointer */
    void *fread_in;           /* backup storage for fread_in pointer */
230
231
232
233
234
235
236
237
238
239

240
241

242
243
244
245
246
247
248
249

250

251
252
253
254
255
                                     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
 */
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 */







|


>


>







|
>

>





284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
                                     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. data->state.authdone is set to TRUE when authentication is
 * done.
 *
 * @param data all information about the current transfer
 * @param conn all information about the current connection
 * @param request pointer to the request keyword
 * @param httpreq is the request type
 * @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 Curl_easy *data,
                      struct connectdata *conn,
                      const char *request,
                      Curl_HttpReq httpreq,
                      const char *path,
                      bool proxytunnel); /* TRUE if this is the request setting
                                            up the proxy tunnel */

#endif /* HEADER_CURL_HTTP_H */
Changes to jni/curl/lib/http2.c.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2020, 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 https://curl.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







|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2021, 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 https://curl.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
61
62
63
64
65
66
67
68
69
70

71
72
73
74
75
76
77
78
79
80
#ifdef DEBUG_HTTP2
#define H2BUGF(x) x
#else
#define H2BUGF(x) do { } while(0)
#endif


static ssize_t http2_recv(struct connectdata *conn, int sockindex,
                          char *mem, size_t len, CURLcode *err);
static bool http2_connisdead(struct connectdata *conn);

static int h2_session_send(struct Curl_easy *data,
                           nghttp2_session *h2);
static int h2_process_pending_input(struct connectdata *conn,
                                    struct http_conn *httpc,
                                    CURLcode *err);

/*
 * Curl_http2_init_state() is called when the easy handle is created and
 * allows for HTTP/2 specific init of state.
 */







|

|
>


|







61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
#ifdef DEBUG_HTTP2
#define H2BUGF(x) x
#else
#define H2BUGF(x) do { } while(0)
#endif


static ssize_t http2_recv(struct Curl_easy *data, int sockindex,
                          char *mem, size_t len, CURLcode *err);
static bool http2_connisdead(struct Curl_easy *data,
                             struct connectdata *conn);
static int h2_session_send(struct Curl_easy *data,
                           nghttp2_session *h2);
static int h2_process_pending_input(struct Curl_easy *data,
                                    struct http_conn *httpc,
                                    CURLcode *err);

/*
 * Curl_http2_init_state() is called when the easy handle is created and
 * allows for HTTP/2 specific init of state.
 */
88
89
90
91
92
93
94

95
96
97
98
99
100
101
102
103

104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142

143
144
145
146



147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
 * allows for HTTP/2 specific user-set fields.
 */
void Curl_http2_init_userset(struct UserDefined *set)
{
  set->stream_weight = NGHTTP2_DEFAULT_WEIGHT;
}


static int http2_perform_getsock(const struct connectdata *conn,
                                 curl_socket_t *sock)
{
  const struct http_conn *c = &conn->proto.httpc;
  struct SingleRequest *k = &conn->data->req;
  int bitmap = GETSOCK_BLANK;

  sock[0] = conn->sock[FIRSTSOCKET];


  /* in a HTTP/2 connection we can basically always get a frame so we should
     always be ready for one */
  bitmap |= GETSOCK_READSOCK(FIRSTSOCKET);

  /* we're still uploading or the HTTP/2 layer wants to send data */
  if(((k->keepon & (KEEP_SEND|KEEP_SEND_PAUSE)) == KEEP_SEND) ||
     nghttp2_session_want_write(c->h2))
    bitmap |= GETSOCK_WRITESOCK(FIRSTSOCKET);

  return bitmap;
}

static int http2_getsock(struct connectdata *conn,
                         curl_socket_t *socks)
{
  return http2_perform_getsock(conn, socks);
}

/*
 * http2_stream_free() free HTTP2 stream related data
 */
static void http2_stream_free(struct HTTP *http)
{
  if(http) {
    Curl_dyn_free(&http->header_recvbuf);
    for(; http->push_headers_used > 0; --http->push_headers_used) {
      free(http->push_headers[http->push_headers_used - 1]);
    }
    free(http->push_headers);
    http->push_headers = NULL;
  }
}

/*
 * Disconnects *a* connection used for HTTP/2. It might be an old one from the
 * connection cache and not the "main" one. Don't touch the easy handle!
 */

static CURLcode http2_disconnect(struct connectdata *conn,

                                 bool dead_connection)
{
  struct http_conn *c = &conn->proto.httpc;
  (void)dead_connection;




  H2BUGF(infof(conn->data, "HTTP/2 DISCONNECT starts now\n"));

  nghttp2_session_del(c->h2);
  Curl_safefree(c->inbuf);

  H2BUGF(infof(conn->data, "HTTP/2 DISCONNECT done\n"));

  return CURLE_OK;
}

/*
 * The server may send us data at any point (e.g. PING frames). Therefore,
 * we cannot assume that an HTTP/2 socket is dead just because it is readable.
 *
 * Instead, if it is readable, run Curl_connalive() to peek at the socket
 * and distinguish between closed and data.
 */
static bool http2_connisdead(struct connectdata *conn)
{
  int sval;
  bool dead = TRUE;

  if(conn->bits.close)
    return TRUE;








>
|
|


|




>
|
|
|









<
<
<
<
<
<




















|
>




>
>
>

|




|











|







89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118






119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
 * allows for HTTP/2 specific user-set fields.
 */
void Curl_http2_init_userset(struct UserDefined *set)
{
  set->stream_weight = NGHTTP2_DEFAULT_WEIGHT;
}

static int http2_getsock(struct Curl_easy *data,
                         struct connectdata *conn,
                         curl_socket_t *sock)
{
  const struct http_conn *c = &conn->proto.httpc;
  struct SingleRequest *k = &data->req;
  int bitmap = GETSOCK_BLANK;

  sock[0] = conn->sock[FIRSTSOCKET];

  if(!(k->keepon & KEEP_RECV_PAUSE))
    /* Unless paused - in a HTTP/2 connection we can basically always get a
       frame so we should always be ready for one */
    bitmap |= GETSOCK_READSOCK(FIRSTSOCKET);

  /* we're still uploading or the HTTP/2 layer wants to send data */
  if(((k->keepon & (KEEP_SEND|KEEP_SEND_PAUSE)) == KEEP_SEND) ||
     nghttp2_session_want_write(c->h2))
    bitmap |= GETSOCK_WRITESOCK(FIRSTSOCKET);

  return bitmap;
}







/*
 * http2_stream_free() free HTTP2 stream related data
 */
static void http2_stream_free(struct HTTP *http)
{
  if(http) {
    Curl_dyn_free(&http->header_recvbuf);
    for(; http->push_headers_used > 0; --http->push_headers_used) {
      free(http->push_headers[http->push_headers_used - 1]);
    }
    free(http->push_headers);
    http->push_headers = NULL;
  }
}

/*
 * Disconnects *a* connection used for HTTP/2. It might be an old one from the
 * connection cache and not the "main" one. Don't touch the easy handle!
 */

static CURLcode http2_disconnect(struct Curl_easy *data,
                                 struct connectdata *conn,
                                 bool dead_connection)
{
  struct http_conn *c = &conn->proto.httpc;
  (void)dead_connection;
#ifndef DEBUG_HTTP2
  (void)data;
#endif

  H2BUGF(infof(data, "HTTP/2 DISCONNECT starts now\n"));

  nghttp2_session_del(c->h2);
  Curl_safefree(c->inbuf);

  H2BUGF(infof(data, "HTTP/2 DISCONNECT done\n"));

  return CURLE_OK;
}

/*
 * The server may send us data at any point (e.g. PING frames). Therefore,
 * we cannot assume that an HTTP/2 socket is dead just because it is readable.
 *
 * Instead, if it is readable, run Curl_connalive() to peek at the socket
 * and distinguish between closed and data.
 */
static bool http2_connisdead(struct Curl_easy *data, struct connectdata *conn)
{
  int sval;
  bool dead = TRUE;

  if(conn->bits.close)
    return TRUE;

188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213

214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
         only "protocol frames" */
      CURLcode result;
      struct http_conn *httpc = &conn->proto.httpc;
      ssize_t nread = -1;
      if(httpc->recv_underlying)
        /* if called "too early", this pointer isn't setup yet! */
        nread = ((Curl_recv *)httpc->recv_underlying)(
          conn, FIRSTSOCKET, httpc->inbuf, H2_BUFSIZE, &result);
      if(nread != -1) {
        infof(conn->data,
              "%d bytes stray data read before trying h2 connection\n",
              (int)nread);
        httpc->nread_inbuf = 0;
        httpc->inbuflen = nread;
        (void)h2_process_pending_input(conn, httpc, &result);
      }
      else
        /* the read failed so let's say this is dead anyway */
        dead = TRUE;
    }
  }

  return dead;
}

static unsigned int http2_conncheck(struct connectdata *check,

                                    unsigned int checks_to_perform)
{
  unsigned int ret_val = CONNRESULT_NONE;
  struct http_conn *c = &check->proto.httpc;
  int rc;
  bool send_frames = false;

  if(checks_to_perform & CONNCHECK_ISDEAD) {
    if(http2_connisdead(check))
      ret_val |= CONNRESULT_DEAD;
  }

  if(checks_to_perform & CONNCHECK_KEEPALIVE) {
    struct curltime now = Curl_now();
    timediff_t elapsed = Curl_timediff(now, check->keepalive);

    if(elapsed > check->upkeep_interval_ms) {
      /* Perform an HTTP/2 PING */
      rc = nghttp2_submit_ping(c->h2, 0, ZERO_NULL);
      if(!rc) {
        /* Successfully added a PING frame to the session. Need to flag this
           so the frame is sent. */
        send_frames = true;
      }
      else {
       failf(check->data, "nghttp2_submit_ping() failed: %s(%d)",
             nghttp2_strerror(rc), rc);
      }

      check->keepalive = now;
    }
  }

  if(send_frames) {
    rc = nghttp2_session_send(c->h2);
    if(rc)
      failf(check->data, "nghttp2_session_send() failed: %s(%d)",
            nghttp2_strerror(rc), rc);
  }

  return ret_val;
}

/* called from http_setup_conn */







|

|




|










|
>



|




|





|

|








|



|






|







189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
         only "protocol frames" */
      CURLcode result;
      struct http_conn *httpc = &conn->proto.httpc;
      ssize_t nread = -1;
      if(httpc->recv_underlying)
        /* if called "too early", this pointer isn't setup yet! */
        nread = ((Curl_recv *)httpc->recv_underlying)(
          data, FIRSTSOCKET, httpc->inbuf, H2_BUFSIZE, &result);
      if(nread != -1) {
        infof(data,
              "%d bytes stray data read before trying h2 connection\n",
              (int)nread);
        httpc->nread_inbuf = 0;
        httpc->inbuflen = nread;
        (void)h2_process_pending_input(data, httpc, &result);
      }
      else
        /* the read failed so let's say this is dead anyway */
        dead = TRUE;
    }
  }

  return dead;
}

static unsigned int http2_conncheck(struct Curl_easy *data,
                                    struct connectdata *conn,
                                    unsigned int checks_to_perform)
{
  unsigned int ret_val = CONNRESULT_NONE;
  struct http_conn *c = &conn->proto.httpc;
  int rc;
  bool send_frames = false;

  if(checks_to_perform & CONNCHECK_ISDEAD) {
    if(http2_connisdead(data, conn))
      ret_val |= CONNRESULT_DEAD;
  }

  if(checks_to_perform & CONNCHECK_KEEPALIVE) {
    struct curltime now = Curl_now();
    timediff_t elapsed = Curl_timediff(now, conn->keepalive);

    if(elapsed > data->set.upkeep_interval_ms) {
      /* Perform an HTTP/2 PING */
      rc = nghttp2_submit_ping(c->h2, 0, ZERO_NULL);
      if(!rc) {
        /* Successfully added a PING frame to the session. Need to flag this
           so the frame is sent. */
        send_frames = true;
      }
      else {
       failf(data, "nghttp2_submit_ping() failed: %s(%d)",
             nghttp2_strerror(rc), rc);
      }

      conn->keepalive = now;
    }
  }

  if(send_frames) {
    rc = nghttp2_session_send(c->h2);
    if(rc)
      failf(data, "nghttp2_session_send() failed: %s(%d)",
            nghttp2_strerror(rc), rc);
  }

  return ret_val;
}

/* called from http_setup_conn */
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
  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 */
  http2_conncheck,                      /* connection_check */
  PORT_HTTP,                            /* defport */
  CURLPROTO_HTTP,                       /* protocol */
  CURLPROTO_HTTP,                       /* family */
  PROTOPT_STREAM                        /* flags */







|







292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
  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_getsock,                        /* perform_getsock */
  http2_disconnect,                     /* disconnect */
  ZERO_NULL,                            /* readwrite */
  http2_conncheck,                      /* connection_check */
  PORT_HTTP,                            /* defport */
  CURLPROTO_HTTP,                       /* protocol */
  CURLPROTO_HTTP,                       /* family */
  PROTOPT_STREAM                        /* flags */
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
  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 */
  http2_conncheck,                      /* connection_check */
  PORT_HTTP,                            /* defport */
  CURLPROTO_HTTPS,                      /* protocol */
  CURLPROTO_HTTP,                       /* family */
  PROTOPT_SSL | PROTOPT_STREAM          /* flags */







|







314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
  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_getsock,                        /* perform_getsock */
  http2_disconnect,                     /* disconnect */
  ZERO_NULL,                            /* readwrite */
  http2_conncheck,                      /* connection_check */
  PORT_HTTP,                            /* defport */
  CURLPROTO_HTTPS,                      /* protocol */
  CURLPROTO_HTTP,                       /* family */
  PROTOPT_SSL | PROTOPT_STREAM          /* flags */
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368

/*
 * 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 *c = &conn->proto.httpc;
  ssize_t written;
  CURLcode result = CURLE_OK;

  (void)h2;
  (void)flags;

  if(!c->send_underlying)
    /* called before setup properly! */
    return NGHTTP2_ERR_CALLBACK_FAILURE;

  written = ((Curl_send*)c->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");







|














|
|







340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370

/*
 * 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 *mem, size_t length, int flags,
                             void *userp)
{
  struct connectdata *conn = (struct connectdata *)userp;
  struct http_conn *c = &conn->proto.httpc;
  ssize_t written;
  CURLcode result = CURLE_OK;

  (void)h2;
  (void)flags;

  if(!c->send_underlying)
    /* called before setup properly! */
    return NGHTTP2_ERR_CALLBACK_FAILURE;

  written = ((Curl_send*)c->send_underlying)(conn->data, FIRSTSOCKET,
                                             mem, length, &result);

  if(result == CURLE_AGAIN) {
    return NGHTTP2_ERR_WOULDBLOCK;
  }

  if(written == -1) {
    failf(conn->data, "Failed sending HTTP2 data");
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
    heads.data = data;
    heads.frame = frame;
    /* ask the application */
    H2BUGF(infof(data, "Got PUSH_PROMISE, ask application!\n"));

    stream = data->req.p.http;
    if(!stream) {
      failf(data, "Internal NULL stream!\n");
      (void)Curl_close(&newhandle);
      rv = CURL_PUSH_DENY;
      goto fail;
    }

    rv = set_transfer_url(newhandle, &heads);
    if(rv) {







|







539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
    heads.data = data;
    heads.frame = frame;
    /* ask the application */
    H2BUGF(infof(data, "Got PUSH_PROMISE, ask application!\n"));

    stream = data->req.p.http;
    if(!stream) {
      failf(data, "Internal NULL stream!");
      (void)Curl_close(&newhandle);
      rv = CURL_PUSH_DENY;
      goto fail;
    }

    rv = set_transfer_url(newhandle, &heads);
    if(rv) {
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
  if(!data_s)
    /* Receiving a Stream ID not in the hash should not happen, this is an
       internal error more than anything else! */
    return NGHTTP2_ERR_CALLBACK_FAILURE;

  stream = data_s->req.p.http;
  if(!stream) {
    failf(data_s, "Internal NULL stream! 5\n");
    return NGHTTP2_ERR_CALLBACK_FAILURE;
  }

  /* Store received PUSH_PROMISE headers to be used when the subsequent
     PUSH_PROMISE callback comes */
  if(frame->hd.type == NGHTTP2_PUSH_PROMISE) {
    char *h;







|







954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
  if(!data_s)
    /* Receiving a Stream ID not in the hash should not happen, this is an
       internal error more than anything else! */
    return NGHTTP2_ERR_CALLBACK_FAILURE;

  stream = data_s->req.p.http;
  if(!stream) {
    failf(data_s, "Internal NULL stream!");
    return NGHTTP2_ERR_CALLBACK_FAILURE;
  }

  /* Store received PUSH_PROMISE headers to be used when the subsequent
     PUSH_PROMISE callback comes */
  if(frame->hd.type == NGHTTP2_PUSH_PROMISE) {
    char *h;
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
    http->stream_id = 0;
  }
}

/*
 * Initialize nghttp2 for a Curl connection
 */
static CURLcode 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







|












|







1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
    http->stream_id = 0;
  }
}

/*
 * Initialize nghttp2 for a Curl connection
 */
static CURLcode http2_init(struct Curl_easy *data, 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(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
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275

1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300

    /* 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;
}

/*
 * Append headers to ask for a HTTP1.1 to HTTP2 upgrade.
 */
CURLcode Curl_http2_request_upgrade(struct dynbuf *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;
  struct http_conn *httpc = &conn->proto.httpc;

  populate_settings(conn, httpc);

  /* this returns number of bytes it wrote */
  binlen = nghttp2_pack_settings_payload(binsettings, H2_BINSETTINGS_LEN,
                                         httpc->local_settings,
                                         httpc->local_settings_num);
  if(binlen <= 0) {
    failf(conn->data, "nghttp2 unexpectedly failed on pack_settings_payload");
    Curl_dyn_free(req);
    return CURLE_FAILED_INIT;
  }
  conn->proto.httpc.binlen = binlen;

  result = Curl_base64url_encode(conn->data, (const char *)binsettings, binlen,
                                 &base64, &blen);
  if(result) {
    Curl_dyn_free(req);
    return result;
  }

  result = Curl_dyn_addf(req,







|
















>
|










|





|







1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303

    /* 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(data, "Couldn't initialize nghttp2!");
      return CURLE_OUT_OF_MEMORY; /* most likely at least */
    }
  }
  return CURLE_OK;
}

/*
 * Append headers to ask for a HTTP1.1 to HTTP2 upgrade.
 */
CURLcode Curl_http2_request_upgrade(struct dynbuf *req,
                                    struct connectdata *conn)
{
  CURLcode result;
  ssize_t binlen;
  char *base64;
  size_t blen;
  struct Curl_easy *data = conn->data;
  struct SingleRequest *k = &data->req;
  uint8_t *binsettings = conn->proto.httpc.binsettings;
  struct http_conn *httpc = &conn->proto.httpc;

  populate_settings(conn, httpc);

  /* this returns number of bytes it wrote */
  binlen = nghttp2_pack_settings_payload(binsettings, H2_BINSETTINGS_LEN,
                                         httpc->local_settings,
                                         httpc->local_settings_num);
  if(binlen <= 0) {
    failf(data, "nghttp2 unexpectedly failed on pack_settings_payload");
    Curl_dyn_free(req);
    return CURLE_FAILED_INIT;
  }
  conn->proto.httpc.binlen = binlen;

  result = Curl_base64url_encode(data, (const char *)binsettings, binlen,
                                 &base64, &blen);
  if(result) {
    Curl_dyn_free(req);
    return result;
  }

  result = Curl_dyn_addf(req,
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350

/*
 * h2_process_pending_input() processes pending input left in
 * httpc->inbuf.  Then, call h2_session_send() to send pending data.
 * This function returns 0 if it succeeds, or -1 and error code will
 * be assigned to *err.
 */
static int h2_process_pending_input(struct connectdata *conn,
                                    struct http_conn *httpc,
                                    CURLcode *err)
{
  ssize_t nread;
  char *inbuf;
  ssize_t rv;
  struct Curl_easy *data = conn->data;

  nread = httpc->inbuflen - httpc->nread_inbuf;
  inbuf = httpc->inbuf + httpc->nread_inbuf;

  rv = nghttp2_session_mem_recv(httpc->h2, (const uint8_t *)inbuf, nread);
  if(rv < 0) {
    failf(data,
          "h2_process_pending_input: nghttp2_session_mem_recv() returned "
          "%zd:%s\n", rv, nghttp2_strerror((int)rv));
    *err = CURLE_RECV_ERROR;
    return -1;
  }

  if(nread == rv) {
    H2BUGF(infof(data,
                 "h2_process_pending_input: All data in connection buffer "







|






<








|







1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336

1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352

/*
 * h2_process_pending_input() processes pending input left in
 * httpc->inbuf.  Then, call h2_session_send() to send pending data.
 * This function returns 0 if it succeeds, or -1 and error code will
 * be assigned to *err.
 */
static int h2_process_pending_input(struct Curl_easy *data,
                                    struct http_conn *httpc,
                                    CURLcode *err)
{
  ssize_t nread;
  char *inbuf;
  ssize_t rv;


  nread = httpc->inbuflen - httpc->nread_inbuf;
  inbuf = httpc->inbuf + httpc->nread_inbuf;

  rv = nghttp2_session_mem_recv(httpc->h2, (const uint8_t *)inbuf, nread);
  if(rv < 0) {
    failf(data,
          "h2_process_pending_input: nghttp2_session_mem_recv() returned "
          "%zd:%s", rv, nghttp2_strerror((int)rv));
    *err = CURLE_RECV_ERROR;
    return -1;
  }

  if(nread == rv) {
    H2BUGF(infof(data,
                 "h2_process_pending_input: All data in connection buffer "
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395

1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
  }

  if(nghttp2_session_check_request_allowed(httpc->h2) == 0) {
    /* No more requests are allowed in the current session, so
       the connection may not be reused. This is set when a
       GOAWAY frame has been received or when the limit of stream
       identifiers has been reached. */
    connclose(conn, "http/2: No new requests allowed");
  }

  if(should_close_session(httpc)) {
    H2BUGF(infof(data,
                 "h2_process_pending_input: nothing to do in this session\n"));
    if(httpc->error_code)
      *err = CURLE_HTTP2;
    else {
      /* not an error per se, but should still close the connection */
      connclose(conn, "GOAWAY received");
      *err = CURLE_OK;
    }
    return -1;
  }
  return 0;
}

/*
 * Called from transfer.c:done_sending when we stop uploading.
 */
CURLcode Curl_http2_done_sending(struct connectdata *conn)

{
  CURLcode result = CURLE_OK;

  if((conn->handler == &Curl_handler_http2_ssl) ||
     (conn->handler == &Curl_handler_http2)) {
    /* make sure this is only attempted for HTTP/2 transfers */

    struct HTTP *stream = conn->data->req.p.http;

    struct http_conn *httpc = &conn->proto.httpc;
    nghttp2_session *h2 = httpc->h2;

    if(stream->upload_left) {
      /* If the stream still thinks there's data left to upload. */

      stream->upload_left = 0; /* DONE! */

      /* resume sending here to trigger the callback to get called again so
         that it can signal EOF to nghttp2 */
      (void)nghttp2_session_resume_data(h2, stream->stream_id);

      (void)h2_process_pending_input(conn, httpc, &result);
    }

    /* If nghttp2 still has pending frames unsent */
    if(nghttp2_session_want_write(h2)) {
      struct Curl_easy *data = conn->data;
      struct SingleRequest *k = &data->req;
      int rv;

      H2BUGF(infof(data, "HTTP/2 still wants to send data (easy %p)\n", data));

      /* re-set KEEP_SEND to make sure we are called again */
      k->keepon |= KEEP_SEND;







|









|










|
>







|












<
|




<







1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418

1419
1420
1421
1422
1423

1424
1425
1426
1427
1428
1429
1430
  }

  if(nghttp2_session_check_request_allowed(httpc->h2) == 0) {
    /* No more requests are allowed in the current session, so
       the connection may not be reused. This is set when a
       GOAWAY frame has been received or when the limit of stream
       identifiers has been reached. */
    connclose(data->conn, "http/2: No new requests allowed");
  }

  if(should_close_session(httpc)) {
    H2BUGF(infof(data,
                 "h2_process_pending_input: nothing to do in this session\n"));
    if(httpc->error_code)
      *err = CURLE_HTTP2;
    else {
      /* not an error per se, but should still close the connection */
      connclose(data->conn, "GOAWAY received");
      *err = CURLE_OK;
    }
    return -1;
  }
  return 0;
}

/*
 * Called from transfer.c:done_sending when we stop uploading.
 */
CURLcode Curl_http2_done_sending(struct Curl_easy *data,
                                 struct connectdata *conn)
{
  CURLcode result = CURLE_OK;

  if((conn->handler == &Curl_handler_http2_ssl) ||
     (conn->handler == &Curl_handler_http2)) {
    /* make sure this is only attempted for HTTP/2 transfers */

    struct HTTP *stream = data->req.p.http;

    struct http_conn *httpc = &conn->proto.httpc;
    nghttp2_session *h2 = httpc->h2;

    if(stream->upload_left) {
      /* If the stream still thinks there's data left to upload. */

      stream->upload_left = 0; /* DONE! */

      /* resume sending here to trigger the callback to get called again so
         that it can signal EOF to nghttp2 */
      (void)nghttp2_session_resume_data(h2, stream->stream_id);

      (void)h2_process_pending_input(data, httpc, &result);
    }

    /* If nghttp2 still has pending frames unsent */
    if(nghttp2_session_want_write(h2)) {

      struct SingleRequest *k = &data->req;
      int rv;

      H2BUGF(infof(data, "HTTP/2 still wants to send data (easy %p)\n", data));

      /* re-set KEEP_SEND to make sure we are called again */
      k->keepon |= KEEP_SEND;
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
  if(httpc->pause_stream_id == stream->stream_id) {
    httpc->pause_stream_id = 0;
  }

  drained_transfer(data, httpc);

  if(httpc->pause_stream_id == 0) {
    if(h2_process_pending_input(conn, httpc, err) != 0) {
      return -1;
    }
  }

  DEBUGASSERT(data->state.drain == 0);

  /* Reset to FALSE to prevent infinite loop in readwrite_data function. */







|







1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
  if(httpc->pause_stream_id == stream->stream_id) {
    httpc->pause_stream_id = 0;
  }

  drained_transfer(data, httpc);

  if(httpc->pause_stream_id == 0) {
    if(h2_process_pending_input(data, httpc, err) != 0) {
      return -1;
    }
  }

  DEBUGASSERT(data->state.drain == 0);

  /* Reset to FALSE to prevent infinite loop in readwrite_data function. */
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
      lf = strchr(trailp, '\n');
      if(!lf)
        break;
      len = lf + 1 - trailp;

      Curl_debug(data, CURLINFO_HEADER_IN, trailp, len);
      /* pass the trailers one by one to the callback */
      result = Curl_client_write(conn, CLIENTWRITE_HEADER, trailp, len);
      if(result) {
        *err = result;
        return -1;
      }
      trailp = ++lf;
    } while(lf);
  }







|







1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
      lf = strchr(trailp, '\n');
      if(!lf)
        break;
      len = lf + 1 - trailp;

      Curl_debug(data, CURLINFO_HEADER_IN, trailp, len);
      /* pass the trailers one by one to the callback */
      result = Curl_client_write(data, CLIENTWRITE_HEADER, trailp, len);
      if(result) {
        *err = result;
        return -1;
      }
      trailp = ++lf;
    } while(lf);
  }
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568

1569
1570
1571
1572
1573
1574
1575
1576
1577
    if(rv)
      return rv;
  }

  return nghttp2_session_send(h2);
}

static ssize_t http2_recv(struct connectdata *conn, int sockindex,
                          char *mem, size_t len, CURLcode *err)
{
  ssize_t nread;

  struct http_conn *httpc = &conn->proto.httpc;
  struct Curl_easy *data = conn->data;
  struct HTTP *stream = data->req.p.http;

  (void)sockindex; /* we always do HTTP2 on sockindex 0 */

  if(should_close_session(httpc)) {
    H2BUGF(infof(data,
                 "http2_recv: nothing to do in this session\n"));







|



>

<







1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571

1572
1573
1574
1575
1576
1577
1578
    if(rv)
      return rv;
  }

  return nghttp2_session_send(h2);
}

static ssize_t http2_recv(struct Curl_easy *data, int sockindex,
                          char *mem, size_t len, CURLcode *err)
{
  ssize_t nread;
  struct connectdata *conn = data->conn;
  struct http_conn *httpc = &conn->proto.httpc;

  struct HTTP *stream = data->req.p.http;

  (void)sockindex; /* we always do HTTP2 on sockindex 0 */

  if(should_close_session(httpc)) {
    H2BUGF(infof(data,
                 "http2_recv: nothing to do in this session\n"));
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
      stream->len = len - stream->memlen;
      stream->mem = mem;
    }
    if(httpc->pause_stream_id == stream->stream_id && !stream->pausedata) {
      /* We have paused nghttp2, but we have no pause data (see
         on_data_chunk_recv). */
      httpc->pause_stream_id = 0;
      if(h2_process_pending_input(conn, httpc, err) != 0) {
        return -1;
      }
    }
  }
  else if(stream->pausedata) {
    DEBUGASSERT(httpc->pause_stream_id == stream->stream_id);
    nread = CURLMIN(len, stream->pauselen);







|







1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
      stream->len = len - stream->memlen;
      stream->mem = mem;
    }
    if(httpc->pause_stream_id == stream->stream_id && !stream->pausedata) {
      /* We have paused nghttp2, but we have no pause data (see
         on_data_chunk_recv). */
      httpc->pause_stream_id = 0;
      if(h2_process_pending_input(data, httpc, err) != 0) {
        return -1;
      }
    }
  }
  else if(stream->pausedata) {
    DEBUGASSERT(httpc->pause_stream_id == stream->stream_id);
    nread = CURLMIN(len, stream->pauselen);
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
      /* When NGHTTP2_ERR_PAUSE is returned from
         data_source_read_callback, we might not process DATA frame
         fully.  Calling nghttp2_session_mem_recv() again will
         continue to process DATA frame, but if there is no incoming
         frames, then we have to call it again with 0-length data.
         Without this, on_stream_close callback will not be called,
         and stream could be hanged. */
      if(h2_process_pending_input(conn, httpc, err) != 0) {
        return -1;
      }
    }
    H2BUGF(infof(data, "http2_recv: returns unpaused %zd bytes on stream %u\n",
                 nread, stream->stream_id));
    return nread;
  }







|







1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
      /* When NGHTTP2_ERR_PAUSE is returned from
         data_source_read_callback, we might not process DATA frame
         fully.  Calling nghttp2_session_mem_recv() again will
         continue to process DATA frame, but if there is no incoming
         frames, then we have to call it again with 0-length data.
         Without this, on_stream_close callback will not be called,
         and stream could be hanged. */
      if(h2_process_pending_input(data, httpc, err) != 0) {
        return -1;
      }
    }
    H2BUGF(infof(data, "http2_recv: returns unpaused %zd bytes on stream %u\n",
                 nread, stream->stream_id));
    return nread;
  }
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
       buffer is */
    stream->mem = mem;
    stream->len = len;
    stream->memlen = 0;

    if(httpc->inbuflen == 0) {
      nread = ((Curl_recv *)httpc->recv_underlying)(
          conn, FIRSTSOCKET, httpc->inbuf, H2_BUFSIZE, err);

      if(nread == -1) {
        if(*err != CURLE_AGAIN)
          failf(data, "Failed receiving HTTP2 data");
        else if(stream->closed)
          /* received when the stream was already closed! */
          return http2_handle_stream_close(conn, data, stream, err);







|







1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
       buffer is */
    stream->mem = mem;
    stream->len = len;
    stream->memlen = 0;

    if(httpc->inbuflen == 0) {
      nread = ((Curl_recv *)httpc->recv_underlying)(
        data, FIRSTSOCKET, httpc->inbuf, H2_BUFSIZE, err);

      if(nread == -1) {
        if(*err != CURLE_AGAIN)
          failf(data, "Failed receiving HTTP2 data");
        else if(stream->closed)
          /* received when the stream was already closed! */
          return http2_handle_stream_close(conn, data, stream, err);
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
    else {
      nread = httpc->inbuflen - httpc->nread_inbuf;
      (void)nread;  /* silence warning, used in debug */
      H2BUGF(infof(data, "Use data left in connection buffer, nread=%zd\n",
                   nread));
    }

    if(h2_process_pending_input(conn, httpc, err) != 0)
      return -1;
  }
  if(stream->memlen) {
    ssize_t retlen = stream->memlen;
    H2BUGF(infof(data, "http2_recv: returns %zd for stream %u\n",
                 retlen, stream->stream_id));
    stream->memlen = 0;







|







1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
    else {
      nread = httpc->inbuflen - httpc->nread_inbuf;
      (void)nread;  /* silence warning, used in debug */
      H2BUGF(infof(data, "Use data left in connection buffer, nread=%zd\n",
                   nread));
    }

    if(h2_process_pending_input(data, httpc, err) != 0)
      return -1;
  }
  if(stream->memlen) {
    ssize_t retlen = stream->memlen;
    H2BUGF(infof(data, "http2_recv: returns %zd for stream %u\n",
                 retlen, stream->stream_id));
    stream->memlen = 0;
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841

1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
    return strncasecompare("transfer-encoding", name, namelen) ?
           HEADERINST_IGNORE : HEADERINST_FORWARD;
  default:
    return HEADERINST_FORWARD;
  }
}

static ssize_t http2_send(struct connectdata *conn, int sockindex,
                          const void *mem, size_t len, CURLcode *err)
{
  /*
   * 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;
  struct HTTP *stream = conn->data->req.p.http;
  nghttp2_nv *nva = NULL;
  size_t nheader;
  size_t i;
  size_t authority_idx;
  char *hdbuf = (char *)mem;
  char *end, *line_end;
  nghttp2_data_provider data_prd;
  int32_t stream_id;
  nghttp2_session *h2 = httpc->h2;
  nghttp2_priority_spec pri_spec;

  (void)sockindex;

  H2BUGF(infof(conn->data, "http2_send len=%zu\n", len));

  if(stream->stream_id != -1) {
    if(stream->close_handled) {
      infof(conn->data, "stream %d closed\n", stream->stream_id);
      *err = CURLE_HTTP2_STREAM;
      return -1;
    }
    else if(stream->closed) {
      return http2_handle_stream_close(conn, conn->data, stream, err);
    }
    /* If stream_id != -1, we have dispatched request HEADERS, and now
       are going to send or sending request body in DATA frame */
    stream->upload_mem = mem;
    stream->upload_len = len;
    rv = nghttp2_session_resume_data(h2, stream->stream_id);
    if(nghttp2_is_fatal(rv)) {
      *err = CURLE_SEND_ERROR;
      return -1;
    }
    rv = h2_session_send(conn->data, h2);
    if(nghttp2_is_fatal(rv)) {
      *err = CURLE_SEND_ERROR;
      return -1;
    }
    len -= stream->upload_len;

    /* Nullify here because we call nghttp2_session_send() and they
       might refer to the old buffer. */
    stream->upload_mem = NULL;
    stream->upload_len = 0;

    if(should_close_session(httpc)) {
      H2BUGF(infof(conn->data, "http2_send: nothing to do in this session\n"));
      *err = CURLE_HTTP2;
      return -1;
    }

    if(stream->upload_left) {
      /* we are sure that we have more data to send here.  Calling the
         following API will make nghttp2_session_want_write() return
         nonzero if remote window allows it, which then libcurl checks
         socket is writable or not.  See http2_perform_getsock(). */
      nghttp2_session_resume_data(h2, stream->stream_id);
    }

    H2BUGF(infof(conn->data, "http2_send returns %zu for stream %u\n", len,
                 stream->stream_id));
    return len;
  }

  /* Calculate number of headers contained in [mem, mem + len) */
  /* Here, we assume the curl http code generate *correct* HTTP header
     field block */







|








>

|













|



|




|










|












|












|







1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
    return strncasecompare("transfer-encoding", name, namelen) ?
           HEADERINST_IGNORE : HEADERINST_FORWARD;
  default:
    return HEADERINST_FORWARD;
  }
}

static ssize_t http2_send(struct Curl_easy *data, int sockindex,
                          const void *mem, size_t len, CURLcode *err)
{
  /*
   * 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 connectdata *conn = data->conn;
  struct http_conn *httpc = &conn->proto.httpc;
  struct HTTP *stream = data->req.p.http;
  nghttp2_nv *nva = NULL;
  size_t nheader;
  size_t i;
  size_t authority_idx;
  char *hdbuf = (char *)mem;
  char *end, *line_end;
  nghttp2_data_provider data_prd;
  int32_t stream_id;
  nghttp2_session *h2 = httpc->h2;
  nghttp2_priority_spec pri_spec;

  (void)sockindex;

  H2BUGF(infof(data, "http2_send len=%zu\n", len));

  if(stream->stream_id != -1) {
    if(stream->close_handled) {
      infof(data, "stream %d closed\n", stream->stream_id);
      *err = CURLE_HTTP2_STREAM;
      return -1;
    }
    else if(stream->closed) {
      return http2_handle_stream_close(conn, data, stream, err);
    }
    /* If stream_id != -1, we have dispatched request HEADERS, and now
       are going to send or sending request body in DATA frame */
    stream->upload_mem = mem;
    stream->upload_len = len;
    rv = nghttp2_session_resume_data(h2, stream->stream_id);
    if(nghttp2_is_fatal(rv)) {
      *err = CURLE_SEND_ERROR;
      return -1;
    }
    rv = h2_session_send(data, h2);
    if(nghttp2_is_fatal(rv)) {
      *err = CURLE_SEND_ERROR;
      return -1;
    }
    len -= stream->upload_len;

    /* Nullify here because we call nghttp2_session_send() and they
       might refer to the old buffer. */
    stream->upload_mem = NULL;
    stream->upload_len = 0;

    if(should_close_session(httpc)) {
      H2BUGF(infof(data, "http2_send: nothing to do in this session\n"));
      *err = CURLE_HTTP2;
      return -1;
    }

    if(stream->upload_left) {
      /* we are sure that we have more data to send here.  Calling the
         following API will make nghttp2_session_want_write() return
         nonzero if remote window allows it, which then libcurl checks
         socket is writable or not.  See http2_perform_getsock(). */
      nghttp2_session_resume_data(h2, stream->stream_id);
    }

    H2BUGF(infof(data, "http2_send returns %zu for stream %u\n", len,
                 stream->stream_id));
    return len;
  }

  /* Calculate number of headers contained in [mem, mem + len) */
  /* Here, we assume the curl http code generate *correct* HTTP header
     field block */
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
    goto fail;
  nva[0].name = (unsigned char *)":method";
  nva[0].namelen = strlen((char *)nva[0].name);
  nva[0].value = (unsigned char *)hdbuf;
  nva[0].valuelen = (size_t)(end - hdbuf);
  nva[0].flags = NGHTTP2_NV_FLAG_NONE;
  if(HEADER_OVERFLOW(nva[0])) {
    failf(conn->data, "Failed sending HTTP request: Header overflow");
    goto fail;
  }

  hdbuf = end + 1;

  /* Path may contain spaces so scan backwards */
  end = NULL;







|







1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
    goto fail;
  nva[0].name = (unsigned char *)":method";
  nva[0].namelen = strlen((char *)nva[0].name);
  nva[0].value = (unsigned char *)hdbuf;
  nva[0].valuelen = (size_t)(end - hdbuf);
  nva[0].flags = NGHTTP2_NV_FLAG_NONE;
  if(HEADER_OVERFLOW(nva[0])) {
    failf(data, "Failed sending HTTP request: Header overflow");
    goto fail;
  }

  hdbuf = end + 1;

  /* Path may contain spaces so scan backwards */
  end = NULL;
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
    goto fail;
  nva[1].name = (unsigned char *)":path";
  nva[1].namelen = strlen((char *)nva[1].name);
  nva[1].value = (unsigned char *)hdbuf;
  nva[1].valuelen = (size_t)(end - hdbuf);
  nva[1].flags = NGHTTP2_NV_FLAG_NONE;
  if(HEADER_OVERFLOW(nva[1])) {
    failf(conn->data, "Failed sending HTTP request: Header overflow");
    goto fail;
  }

  nva[2].name = (unsigned char *)":scheme";
  nva[2].namelen = 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 = strlen((char *)nva[2].value);
  nva[2].flags = NGHTTP2_NV_FLAG_NONE;
  if(HEADER_OVERFLOW(nva[2])) {
    failf(conn->data, "Failed sending HTTP request: Header overflow");
    goto fail;
  }

  authority_idx = 0;
  i = 3;
  while(i < nheader) {
    size_t hlen;







|












|







1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
    goto fail;
  nva[1].name = (unsigned char *)":path";
  nva[1].namelen = strlen((char *)nva[1].name);
  nva[1].value = (unsigned char *)hdbuf;
  nva[1].valuelen = (size_t)(end - hdbuf);
  nva[1].flags = NGHTTP2_NV_FLAG_NONE;
  if(HEADER_OVERFLOW(nva[1])) {
    failf(data, "Failed sending HTTP request: Header overflow");
    goto fail;
  }

  nva[2].name = (unsigned char *)":scheme";
  nva[2].namelen = 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 = strlen((char *)nva[2].value);
  nva[2].flags = NGHTTP2_NV_FLAG_NONE;
  if(HEADER_OVERFLOW(nva[2])) {
    failf(data, "Failed sending HTTP request: Header overflow");
    goto fail;
  }

  authority_idx = 0;
  i = 3;
  while(i < nheader) {
    size_t hlen;
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
    default:
      nva[i].value = (unsigned char *)hdbuf;
      nva[i].valuelen = (size_t)(end - hdbuf);
    }

    nva[i].flags = NGHTTP2_NV_FLAG_NONE;
    if(HEADER_OVERFLOW(nva[i])) {
      failf(conn->data, "Failed sending HTTP request: Header overflow");
      goto fail;
    }
    ++i;
  }

  /* :authority must come before non-pseudo header fields */
  if(authority_idx != 0 && authority_idx != AUTHORITY_DST_IDX) {







|







2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
    default:
      nva[i].value = (unsigned char *)hdbuf;
      nva[i].valuelen = (size_t)(end - hdbuf);
    }

    nva[i].flags = NGHTTP2_NV_FLAG_NONE;
    if(HEADER_OVERFLOW(nva[i])) {
      failf(data, "Failed sending HTTP request: Header overflow");
      goto fail;
    }
    ++i;
  }

  /* :authority must come before non-pseudo header fields */
  if(authority_idx != 0 && authority_idx != AUTHORITY_DST_IDX) {
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
#define MAX_ACC 60000  /* <64KB to account for some overhead */
  {
    size_t acc = 0;

    for(i = 0; i < nheader; ++i) {
      acc += nva[i].namelen + nva[i].valuelen;

      H2BUGF(infof(conn->data, "h2 header: %.*s:%.*s\n",
                   nva[i].namelen, nva[i].name,
                   nva[i].valuelen, nva[i].value));
    }

    if(acc > MAX_ACC) {
      infof(conn->data, "http2_send: Warning: The cumulative length of all "
            "headers exceeds %d bytes and that could cause the "
            "stream to be rejected.\n", MAX_ACC);
    }
  }

  h2_pri_spec(conn->data, &pri_spec);

  H2BUGF(infof(conn->data, "http2_send request allowed %d (easy handle %p)\n",
         nghttp2_session_check_request_allowed(h2), (void *)conn->data));

  switch(conn->data->state.httpreq) {
  case HTTPREQ_POST:
  case HTTPREQ_POST_FORM:
  case HTTPREQ_POST_MIME:
  case HTTPREQ_PUT:
    if(conn->data->state.infilesize != -1)
      stream->upload_left = conn->data->state.infilesize;
    else
      /* data sending without specifying the data amount up front */
      stream->upload_left = -1; /* unknown, but not zero */

    data_prd.read_callback = data_source_read_callback;
    data_prd.source.ptr = NULL;
    stream_id = nghttp2_submit_request(h2, &pri_spec, nva, nheader,
                                       &data_prd, conn->data);
    break;
  default:
    stream_id = nghttp2_submit_request(h2, &pri_spec, nva, nheader,
                                       NULL, conn->data);
  }

  Curl_safefree(nva);

  if(stream_id < 0) {
    H2BUGF(infof(conn->data,
                 "http2_send() nghttp2_submit_request error (%s)%d\n",
                 nghttp2_strerror(stream_id), stream_id));
    *err = CURLE_SEND_ERROR;
    return -1;
  }

  infof(conn->data, "Using Stream ID: %x (easy handle %p)\n",
        stream_id, (void *)conn->data);
  stream->stream_id = stream_id;

  /* this does not call h2_session_send() since there can not have been any
   * priority update since the nghttp2_submit_request() call above */
  rv = nghttp2_session_send(h2);
  if(rv != 0) {
    H2BUGF(infof(conn->data,
                 "http2_send() nghttp2_session_send error (%s)%d\n",
                 nghttp2_strerror(rv), rv));

    *err = CURLE_SEND_ERROR;
    return -1;
  }

  if(should_close_session(httpc)) {
    H2BUGF(infof(conn->data, "http2_send: nothing to do in this session\n"));
    *err = CURLE_HTTP2;
    return -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







|





|





|

|
|

|




|
|







|



|





|






|
|






|








|







2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
#define MAX_ACC 60000  /* <64KB to account for some overhead */
  {
    size_t acc = 0;

    for(i = 0; i < nheader; ++i) {
      acc += nva[i].namelen + nva[i].valuelen;

      H2BUGF(infof(data, "h2 header: %.*s:%.*s\n",
                   nva[i].namelen, nva[i].name,
                   nva[i].valuelen, nva[i].value));
    }

    if(acc > MAX_ACC) {
      infof(data, "http2_send: Warning: The cumulative length of all "
            "headers exceeds %d bytes and that could cause the "
            "stream to be rejected.\n", MAX_ACC);
    }
  }

  h2_pri_spec(data, &pri_spec);

  H2BUGF(infof(data, "http2_send request allowed %d (easy handle %p)\n",
               nghttp2_session_check_request_allowed(h2), (void *)data));

  switch(data->state.httpreq) {
  case HTTPREQ_POST:
  case HTTPREQ_POST_FORM:
  case HTTPREQ_POST_MIME:
  case HTTPREQ_PUT:
    if(data->state.infilesize != -1)
      stream->upload_left = data->state.infilesize;
    else
      /* data sending without specifying the data amount up front */
      stream->upload_left = -1; /* unknown, but not zero */

    data_prd.read_callback = data_source_read_callback;
    data_prd.source.ptr = NULL;
    stream_id = nghttp2_submit_request(h2, &pri_spec, nva, nheader,
                                       &data_prd, data);
    break;
  default:
    stream_id = nghttp2_submit_request(h2, &pri_spec, nva, nheader,
                                       NULL, data);
  }

  Curl_safefree(nva);

  if(stream_id < 0) {
    H2BUGF(infof(data,
                 "http2_send() nghttp2_submit_request error (%s)%d\n",
                 nghttp2_strerror(stream_id), stream_id));
    *err = CURLE_SEND_ERROR;
    return -1;
  }

  infof(data, "Using Stream ID: %x (easy handle %p)\n",
        stream_id, (void *)data);
  stream->stream_id = stream_id;

  /* this does not call h2_session_send() since there can not have been any
   * priority update since the nghttp2_submit_request() call above */
  rv = nghttp2_session_send(h2);
  if(rv != 0) {
    H2BUGF(infof(data,
                 "http2_send() nghttp2_session_send error (%s)%d\n",
                 nghttp2_strerror(rv), rv));

    *err = CURLE_SEND_ERROR;
    return -1;
  }

  if(should_close_session(httpc)) {
    H2BUGF(infof(data, "http2_send: nothing to do in this session\n"));
    *err = CURLE_HTTP2;
    return -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
2146
2147
2148
2149
2150
2151
2152
2153

2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207

2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229

fail:
  free(nva);
  *err = CURLE_SEND_ERROR;
  return -1;
}

CURLcode Curl_http2_setup(struct connectdata *conn)

{
  CURLcode result;
  struct http_conn *httpc = &conn->proto.httpc;
  struct HTTP *stream = conn->data->req.p.http;

  DEBUGASSERT(conn->data->state.buffer);

  stream->stream_id = -1;

  Curl_dyn_init(&stream->header_recvbuf, DYN_H2_HEADERS);
  Curl_dyn_init(&stream->trailer_recvbuf, DYN_H2_TRAILERS);

  if((conn->handler == &Curl_handler_http2_ssl) ||
     (conn->handler == &Curl_handler_http2))
    return CURLE_OK; /* already done */

  if(conn->handler->flags & PROTOPT_SSL)
    conn->handler = &Curl_handler_http2_ssl;
  else
    conn->handler = &Curl_handler_http2;

  result = http2_init(conn);
  if(result) {
    Curl_dyn_free(&stream->header_recvbuf);
    return result;
  }

  infof(conn->data, "Using HTTP2, server supports multi-use\n");
  stream->upload_left = 0;
  stream->upload_mem = NULL;
  stream->upload_len = 0;
  stream->mem = conn->data->state.buffer;
  stream->len = conn->data->set.buffer_size;

  httpc->inbuflen = 0;
  httpc->nread_inbuf = 0;

  httpc->pause_stream_id = 0;
  httpc->drain_total = 0;

  conn->bits.multiplex = TRUE; /* at least potentially multiplexed */
  conn->httpversion = 20;
  conn->bundle->multiuse = BUNDLE_MULTIPLEX;

  infof(conn->data, "Connection state changed (HTTP/2 confirmed)\n");
  multi_connchanged(conn->data->multi);

  return CURLE_OK;
}

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 Curl_easy *data = conn->data;
  struct HTTP *stream = conn->data->req.p.http;

  result = Curl_http2_setup(conn);
  if(result)
    return result;

  httpc->recv_underlying = conn->recv[FIRSTSOCKET];
  httpc->send_underlying = conn->send[FIRSTSOCKET];
  conn->recv[FIRSTSOCKET] = http2_recv;
  conn->send[FIRSTSOCKET] = http2_send;

  if(conn->data->req.upgr101 == UPGR101_RECEIVED) {
    /* stream 1 is opened implicitly on upgrade */
    stream->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)",







|
>



|

|















|





|



|
|











|
|




|



>


<
|

|








|







2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213

2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232

fail:
  free(nva);
  *err = CURLE_SEND_ERROR;
  return -1;
}

CURLcode Curl_http2_setup(struct Curl_easy *data,
                          struct connectdata *conn)
{
  CURLcode result;
  struct http_conn *httpc = &conn->proto.httpc;
  struct HTTP *stream = data->req.p.http;

  DEBUGASSERT(data->state.buffer);

  stream->stream_id = -1;

  Curl_dyn_init(&stream->header_recvbuf, DYN_H2_HEADERS);
  Curl_dyn_init(&stream->trailer_recvbuf, DYN_H2_TRAILERS);

  if((conn->handler == &Curl_handler_http2_ssl) ||
     (conn->handler == &Curl_handler_http2))
    return CURLE_OK; /* already done */

  if(conn->handler->flags & PROTOPT_SSL)
    conn->handler = &Curl_handler_http2_ssl;
  else
    conn->handler = &Curl_handler_http2;

  result = http2_init(data, conn);
  if(result) {
    Curl_dyn_free(&stream->header_recvbuf);
    return result;
  }

  infof(data, "Using HTTP2, server supports multi-use\n");
  stream->upload_left = 0;
  stream->upload_mem = NULL;
  stream->upload_len = 0;
  stream->mem = data->state.buffer;
  stream->len = data->set.buffer_size;

  httpc->inbuflen = 0;
  httpc->nread_inbuf = 0;

  httpc->pause_stream_id = 0;
  httpc->drain_total = 0;

  conn->bits.multiplex = TRUE; /* at least potentially multiplexed */
  conn->httpversion = 20;
  conn->bundle->multiuse = BUNDLE_MULTIPLEX;

  infof(data, "Connection state changed (HTTP/2 confirmed)\n");
  multi_connchanged(data->multi);

  return CURLE_OK;
}

CURLcode Curl_http2_switched(struct Curl_easy *data,
                             const char *mem, size_t nread)
{
  CURLcode result;
  struct connectdata *conn = data->conn;
  struct http_conn *httpc = &conn->proto.httpc;
  int rv;

  struct HTTP *stream = data->req.p.http;

  result = Curl_http2_setup(data, conn);
  if(result)
    return result;

  httpc->recv_underlying = conn->recv[FIRSTSOCKET];
  httpc->send_underlying = conn->send[FIRSTSOCKET];
  conn->recv[FIRSTSOCKET] = http2_recv;
  conn->send[FIRSTSOCKET] = http2_send;

  if(data->req.upgr101 == UPGR101_RECEIVED) {
    /* stream 1 is opened implicitly on upgrade */
    stream->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)",
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295

  /* we are going to copy mem to httpc->inbuf.  This is required since
     mem is part of buffer pointed by stream->mem, and callbacks
     called by nghttp2_session_mem_recv() will write stream specific
     data into stream->mem, overwriting data already there. */
  if(H2_BUFSIZE < nread) {
    failf(data, "connection buffer size is too small to store data following "
                "HTTP Upgrade response header: buflen=%d, datalen=%zu",
          H2_BUFSIZE, nread);
    return CURLE_HTTP2;
  }

  infof(conn->data, "Copying HTTP/2 data in stream buffer to connection buffer"
                    " after upgrade: len=%zu\n",
        nread);

  if(nread)
    memcpy(httpc->inbuf, mem, nread);

  httpc->inbuflen = nread;

  DEBUGASSERT(httpc->nread_inbuf == 0);

  if(-1 == h2_process_pending_input(conn, httpc, &result))
    return CURLE_HTTP2;

  return CURLE_OK;
}

CURLcode Curl_http2_stream_pause(struct Curl_easy *data, bool pause)
{







|




|
|









|







2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298

  /* we are going to copy mem to httpc->inbuf.  This is required since
     mem is part of buffer pointed by stream->mem, and callbacks
     called by nghttp2_session_mem_recv() will write stream specific
     data into stream->mem, overwriting data already there. */
  if(H2_BUFSIZE < nread) {
    failf(data, "connection buffer size is too small to store data following "
          "HTTP Upgrade response header: buflen=%d, datalen=%zu",
          H2_BUFSIZE, nread);
    return CURLE_HTTP2;
  }

  infof(data, "Copying HTTP/2 data in stream buffer to connection buffer"
        " after upgrade: len=%zu\n",
        nread);

  if(nread)
    memcpy(httpc->inbuf, mem, nread);

  httpc->inbuflen = nread;

  DEBUGASSERT(httpc->nread_inbuf == 0);

  if(-1 == h2_process_pending_input(data, httpc, &result))
    return CURLE_HTTP2;

  return CURLE_OK;
}

CURLcode Curl_http2_stream_pause(struct Curl_easy *data, bool pause)
{
Changes to jni/curl/lib/http2.h.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#ifndef HEADER_CURL_HTTP2_H
#define HEADER_CURL_HTTP2_H
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2020, 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 https://curl.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









|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#ifndef HEADER_CURL_HTTP2_H
#define HEADER_CURL_HTTP2_H
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2021, 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 https://curl.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
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54

55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
const char *Curl_http2_strerror(uint32_t err);

CURLcode Curl_http2_init(struct connectdata *conn);
void Curl_http2_init_state(struct UrlState *state);
void Curl_http2_init_userset(struct UserDefined *set);
CURLcode Curl_http2_request_upgrade(struct dynbuf *req,
                                    struct connectdata *conn);
CURLcode Curl_http2_setup(struct connectdata *conn);
CURLcode Curl_http2_switched(struct connectdata *conn,
                             const char *data, size_t nread);
/* called from http_setup_conn */
void Curl_http2_setup_conn(struct connectdata *conn);
void Curl_http2_setup_req(struct Curl_easy *data);
void Curl_http2_done(struct Curl_easy *data, bool premature);
CURLcode Curl_http2_done_sending(struct connectdata *conn);

CURLcode Curl_http2_add_child(struct Curl_easy *parent,
                              struct Curl_easy *child,
                              bool exclusive);
void Curl_http2_remove_child(struct Curl_easy *parent,
                             struct Curl_easy *child);
void Curl_http2_cleanup_dependencies(struct Curl_easy *data);
CURLcode Curl_http2_stream_pause(struct Curl_easy *data, bool pause);

/* returns true if the HTTP/2 stream error was HTTP_1_1_REQUIRED */
bool Curl_h2_http_1_1_error(struct connectdata *conn);
#else /* USE_NGHTTP2 */
#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
#define Curl_http2_setup_conn(x) Curl_nop_stmt
#define Curl_http2_setup_req(x)
#define Curl_http2_init_state(x)
#define Curl_http2_init_userset(x)
#define Curl_http2_done(x,y)
#define Curl_http2_done_sending(x)
#define Curl_http2_add_child(x, y, z)
#define Curl_http2_remove_child(x, y)
#define Curl_http2_cleanup_dependencies(x)
#define Curl_http2_stream_pause(x, y)
#define Curl_h2_http_1_1_error(x) 0
#endif

#endif /* HEADER_CURL_HTTP2_H */







|
|
|




|
>












|






|








40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
const char *Curl_http2_strerror(uint32_t err);

CURLcode Curl_http2_init(struct connectdata *conn);
void Curl_http2_init_state(struct UrlState *state);
void Curl_http2_init_userset(struct UserDefined *set);
CURLcode Curl_http2_request_upgrade(struct dynbuf *req,
                                    struct connectdata *conn);
CURLcode Curl_http2_setup(struct Curl_easy *data, struct connectdata *conn);
CURLcode Curl_http2_switched(struct Curl_easy *data,
                             const char *ptr, size_t nread);
/* called from http_setup_conn */
void Curl_http2_setup_conn(struct connectdata *conn);
void Curl_http2_setup_req(struct Curl_easy *data);
void Curl_http2_done(struct Curl_easy *data, bool premature);
CURLcode Curl_http2_done_sending(struct Curl_easy *data,
                                 struct connectdata *conn);
CURLcode Curl_http2_add_child(struct Curl_easy *parent,
                              struct Curl_easy *child,
                              bool exclusive);
void Curl_http2_remove_child(struct Curl_easy *parent,
                             struct Curl_easy *child);
void Curl_http2_cleanup_dependencies(struct Curl_easy *data);
CURLcode Curl_http2_stream_pause(struct Curl_easy *data, bool pause);

/* returns true if the HTTP/2 stream error was HTTP_1_1_REQUIRED */
bool Curl_h2_http_1_1_error(struct connectdata *conn);
#else /* USE_NGHTTP2 */
#define Curl_http2_request_upgrade(x,y) CURLE_UNSUPPORTED_PROTOCOL
#define Curl_http2_setup(x,y) CURLE_UNSUPPORTED_PROTOCOL
#define Curl_http2_switched(x,y,z) CURLE_UNSUPPORTED_PROTOCOL
#define Curl_http2_setup_conn(x) Curl_nop_stmt
#define Curl_http2_setup_req(x)
#define Curl_http2_init_state(x)
#define Curl_http2_init_userset(x)
#define Curl_http2_done(x,y)
#define Curl_http2_done_sending(x,y)
#define Curl_http2_add_child(x, y, z)
#define Curl_http2_remove_child(x, y)
#define Curl_http2_cleanup_dependencies(x)
#define Curl_http2_stream_pause(x, y)
#define Curl_h2_http_1_1_error(x) 0
#endif

#endif /* HEADER_CURL_HTTP2_H */
Added jni/curl/lib/http_aws_sigv4.c.




















































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2021, 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 https://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 "strcase.h"
#include "strdup.h"
#include "vauth/vauth.h"
#include "vauth/digest.h"
#include "http_aws_sigv4.h"
#include "curl_sha256.h"
#include "transfer.h"

#include "strcase.h"
#include "parsedate.h"
#include "sendf.h"

#include <time.h>

/* The last 3 #include files should be in this order */
#include "curl_printf.h"
#include "curl_memory.h"
#include "memdebug.h"

#define HMAC_SHA256(k, kl, d, dl, o)        \
  do {                                      \
    ret = Curl_hmacit(Curl_HMAC_SHA256,     \
                      (unsigned char *)k,   \
                      (unsigned int)kl,     \
                      (unsigned char *)d,   \
                      (unsigned int)dl, o); \
    if(ret != CURLE_OK) {                   \
      goto fail;                            \
    }                                       \
  } while(0)

static void sha256_to_hex(char *dst, unsigned char *sha, size_t dst_l)
{
  int i;

  DEBUGASSERT(dst_l >= 65);
  for(i = 0; i < 32; ++i) {
    curl_msnprintf(dst + (i * 2), dst_l - (i * 2), "%02x", sha[i]);
  }
}

CURLcode Curl_output_aws_sigv4(struct Curl_easy *data, bool proxy)
{
  CURLcode ret = CURLE_OUT_OF_MEMORY;
  struct connectdata *conn = data->conn;
  size_t len;
  const char *tmp0;
  const char *tmp1;
  char *provider0_low = NULL;
  char *provider0_up = NULL;
  char *provider1_low = NULL;
  char *provider1_mid = NULL;
  char *region = NULL;
  char *service = NULL;
  const char *hostname = conn->host.name;
#ifdef DEBUGBUILD
  char *force_timestamp;
#endif
  time_t clock;
  struct tm tm;
  char timestamp[17];
  char date[9];
  const char *content_type = Curl_checkheaders(data, "Content-Type");
  char *canonical_headers = NULL;
  char *signed_headers = NULL;
  Curl_HttpReq httpreq;
  const char *method;
  const char *post_data = data->set.postfields ? data->set.postfields : "";
  unsigned char sha_hash[32];
  char sha_hex[65];
  char *canonical_request = NULL;
  char *request_type = NULL;
  char *credential_scope = NULL;
  char *str_to_sign = NULL;
  const char *user = conn->user ? conn->user : "";
  const char *passwd = conn->passwd ? conn->passwd : "";
  char *secret = NULL;
  unsigned char tmp_sign0[32] = {0};
  unsigned char tmp_sign1[32] = {0};
  char *auth_headers = NULL;

  DEBUGASSERT(!proxy);
  (void)proxy;

  if(Curl_checkheaders(data, "Authorization")) {
    /* Authorization already present, Bailing out */
    return CURLE_OK;
  }

  /*
   * Parameters parsing
   * Google and Outscale use the same OSC or GOOG,
   * but Amazon uses AWS and AMZ for header arguments.
   * AWS is the default because most of non-amazon providers
   * are still using aws:amz as a prefix.
   */
  tmp0 = data->set.str[STRING_AWS_SIGV4] ?
    data->set.str[STRING_AWS_SIGV4] : "aws:amz";
  tmp1 = strchr(tmp0, ':');
  len = tmp1 ? (size_t)(tmp1 - tmp0) : strlen(tmp0);
  if(len < 1) {
    infof(data, "first provider can't be empty\n");
    ret = CURLE_BAD_FUNCTION_ARGUMENT;
    goto fail;
  }
  provider0_low = malloc(len + 1);
  provider0_up = malloc(len + 1);
  if(!provider0_low || !provider0_up) {
    goto fail;
  }
  Curl_strntolower(provider0_low, tmp0, len);
  provider0_low[len] = '\0';
  Curl_strntoupper(provider0_up, tmp0, len);
  provider0_up[len] = '\0';

  if(tmp1) {
    tmp0 = tmp1 + 1;
    tmp1 = strchr(tmp0, ':');
    len = tmp1 ? (size_t)(tmp1 - tmp0) : strlen(tmp0);
    if(len < 1) {
      infof(data, "second provider can't be empty\n");
      ret = CURLE_BAD_FUNCTION_ARGUMENT;
      goto fail;
    }
    provider1_low = malloc(len + 1);
    provider1_mid = malloc(len + 1);
    if(!provider1_low || !provider1_mid) {
      goto fail;
    }
    Curl_strntolower(provider1_low, tmp0, len);
    provider1_low[len] = '\0';
    Curl_strntolower(provider1_mid, tmp0, len);
    provider1_mid[0] = Curl_raw_toupper(provider1_mid[0]);
    provider1_mid[len] = '\0';

    if(tmp1) {
      tmp0 = tmp1 + 1;
      tmp1 = strchr(tmp0, ':');
      len = tmp1 ? (size_t)(tmp1 - tmp0) : strlen(tmp0);
      if(len < 1) {
        infof(data, "region can't be empty\n");
        ret = CURLE_BAD_FUNCTION_ARGUMENT;
        goto fail;
      }
      region = Curl_memdup(tmp0, len + 1);
      if(!region) {
        goto fail;
      }
      region[len] = '\0';

      if(tmp1) {
        tmp0 = tmp1 + 1;
        service = strdup(tmp0);
        if(!service) {
          goto fail;
        }
        if(strlen(service) < 1) {
          infof(data, "service can't be empty\n");
          ret = CURLE_BAD_FUNCTION_ARGUMENT;
          goto fail;
        }
      }
    }
  }
  else {
    provider1_low = Curl_memdup(provider0_low, len + 1);
    provider1_mid = Curl_memdup(provider0_low, len + 1);
    if(!provider1_low || !provider1_mid) {
      goto fail;
    }
    provider1_mid[0] = Curl_raw_toupper(provider1_mid[0]);
  }

  if(!service) {
    tmp0 = hostname;
    tmp1 = strchr(tmp0, '.');
    len = tmp1 - tmp0;
    if(!tmp1 || len < 1) {
      infof(data, "service missing in parameters or hostname\n");
      ret = CURLE_URL_MALFORMAT;
      goto fail;
    }
    service = Curl_memdup(tmp0, len + 1);
    if(!service) {
      goto fail;
    }
    service[len] = '\0';

    if(!region) {
      tmp0 = tmp1 + 1;
      tmp1 = strchr(tmp0, '.');
      len = tmp1 - tmp0;
      if(!tmp1 || len < 1) {
        infof(data, "region missing in parameters or hostname\n");
        ret = CURLE_URL_MALFORMAT;
        goto fail;
      }
      region = Curl_memdup(tmp0, len + 1);
      if(!region) {
        goto fail;
      }
      region[len] = '\0';
    }
  }

#ifdef DEBUGBUILD
  force_timestamp = getenv("CURL_FORCETIME");
  if(force_timestamp)
    clock = 0;
  else
    time(&clock);
#else
  time(&clock);
#endif
  ret = Curl_gmtime(clock, &tm);
  if(ret != CURLE_OK) {
    goto fail;
  }
  if(!strftime(timestamp, sizeof(timestamp), "%Y%m%dT%H%M%SZ", &tm)) {
    goto fail;
  }
  memcpy(date, timestamp, sizeof(date));
  date[sizeof(date) - 1] = 0;

  if(content_type) {
    content_type = strchr(content_type, ':');
    if(!content_type) {
      ret = CURLE_FAILED_INIT;
      goto fail;
    }
    content_type++;
    /* Skip whitespace now */
    while(*content_type == ' ' || *content_type == '\t')
      ++content_type;

    canonical_headers = curl_maprintf("content-type:%s\n"
                                      "host:%s\n"
                                      "x-%s-date:%s\n",
                                      content_type,
                                      hostname,
                                      provider1_low, timestamp);
    signed_headers = curl_maprintf("content-type;host;x-%s-date",
                                   provider1_low);
  }
  else {
    canonical_headers = curl_maprintf("host:%s\n"
                                      "x-%s-date:%s\n",
                                      hostname,
                                      provider1_low, timestamp);
    signed_headers = curl_maprintf("host;x-%s-date", provider1_low);
  }

  if(!canonical_headers || !signed_headers) {
    goto fail;
  }

  Curl_sha256it(sha_hash,
                (const unsigned char *) post_data, strlen(post_data));
  sha256_to_hex(sha_hex, sha_hash, sizeof(sha_hex));

  Curl_http_method(data, conn, &method, &httpreq);

  canonical_request =
    curl_maprintf("%s\n" /* HTTPRequestMethod */
                  "%s\n" /* CanonicalURI */
                  "%s\n" /* CanonicalQueryString */
                  "%s\n" /* CanonicalHeaders */
                  "%s\n" /* SignedHeaders */
                  "%s",  /* HashedRequestPayload in hex */
                  method,
                  data->state.up.path,
                  data->state.up.query ? data->state.up.query : "",
                  canonical_headers,
                  signed_headers,
                  sha_hex);
  if(!canonical_request) {
    goto fail;
  }

  request_type = curl_maprintf("%s4_request", provider0_low);
  if(!request_type) {
    goto fail;
  }

  credential_scope = curl_maprintf("%s/%s/%s/%s",
                                   date, region, service, request_type);
  if(!credential_scope) {
    goto fail;
  }

  Curl_sha256it(sha_hash, (unsigned char *) canonical_request,
                strlen(canonical_request));
  sha256_to_hex(sha_hex, sha_hash, sizeof(sha_hex));

  /*
   * Google allow to use rsa key instead of HMAC, so this code might change
   * In the furure, but for now we support only HMAC version
   */
  str_to_sign = curl_maprintf("%s4-HMAC-SHA256\n" /* Algorithm */
                              "%s\n" /* RequestDateTime */
                              "%s\n" /* CredentialScope */
                              "%s",  /* HashedCanonicalRequest in hex */
                              provider0_up,
                              timestamp,
                              credential_scope,
                              sha_hex);
  if(!str_to_sign) {
    goto fail;
  }

  secret = curl_maprintf("%s4%s", provider0_up, passwd);
  if(!secret) {
    goto fail;
  }

  HMAC_SHA256(secret, strlen(secret),
              date, strlen(date), tmp_sign0);
  HMAC_SHA256(tmp_sign0, sizeof(tmp_sign0),
              region, strlen(region), tmp_sign1);
  HMAC_SHA256(tmp_sign1, sizeof(tmp_sign1),
              service, strlen(service), tmp_sign0);
  HMAC_SHA256(tmp_sign0, sizeof(tmp_sign0),
              request_type, strlen(request_type), tmp_sign1);
  HMAC_SHA256(tmp_sign1, sizeof(tmp_sign1),
              str_to_sign, strlen(str_to_sign), tmp_sign0);

  sha256_to_hex(sha_hex, tmp_sign0, sizeof(sha_hex));

  auth_headers = curl_maprintf("Authorization: %s4-HMAC-SHA256 "
                               "Credential=%s/%s, "
                               "SignedHeaders=%s, "
                               "Signature=%s\r\n"
                               "X-%s-Date: %s\r\n",
                               provider0_up,
                               user,
                               credential_scope,
                               signed_headers,
                               sha_hex,
                               provider1_mid,
                               timestamp);
  if(!auth_headers) {
    goto fail;
  }

  Curl_safefree(data->state.aptr.userpwd);
  data->state.aptr.userpwd = auth_headers;
  data->state.authhost.done = TRUE;
  ret = CURLE_OK;

fail:
  free(provider0_low);
  free(provider0_up);
  free(provider1_low);
  free(provider1_mid);
  free(region);
  free(service);
  free(canonical_headers);
  free(signed_headers);
  free(canonical_request);
  free(request_type);
  free(credential_scope);
  free(str_to_sign);
  free(secret);
  return ret;
}

#endif /* !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_CRYPTO_AUTH) */
Added jni/curl/lib/http_aws_sigv4.h.


























































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#ifndef HEADER_CURL_HTTP_AWS_SIGV4_H
#define HEADER_CURL_HTTP_AWS_SIGV4_H
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2021, 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 https://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 creating aws_sigv4 header output */
CURLcode Curl_output_aws_sigv4(struct Curl_easy *data, bool proxy);

#endif /* HEADER_CURL_HTTP_AWS_SIGV4_H */
Changes to jni/curl/lib/http_chunks.c.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2020, 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 https://curl.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







|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2021, 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 https://curl.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
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91

92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
   zero, followed by the trailer, which is terminated by an empty line.

 */

#ifdef CURL_DOES_CONVERSIONS
/* Check for an ASCII hex digit.
   We avoid the use of ISXDIGIT to accommodate non-ASCII hosts. */
static bool Curl_isxdigit_ascii(char digit)
{
  return (digit >= 0x30 && digit <= 0x39) /* 0-9 */
        || (digit >= 0x41 && digit <= 0x46) /* A-F */
        || (digit >= 0x61 && digit <= 0x66); /* a-f */
}
#else
#define Curl_isxdigit_ascii(x) Curl_isxdigit(x)
#endif

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! */
  Curl_dyn_init(&conn->trailer, DYN_H1_TRAILER);
}

/*
 * 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'.
 */
CHUNKcode Curl_httpchunk_read(struct connectdata *conn,
                              char *datap,
                              ssize_t datalen,
                              ssize_t *wrotep,
                              CURLcode *extrap)
{
  CURLcode result = CURLE_OK;
  struct Curl_easy *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) {
      *extrap = result;
      return CHUNKE_PASSTHRU_ERROR;
    }
  }

  while(length) {
    switch(ch->state) {
    case CHUNK_HEX:
      if(Curl_isxdigit_ascii(*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;
        }

        if(curlx_strtoofft(ch->hexbuffer, &endptr, 16, &ch->datasize))







|


|
|


|


|

>


<















|






|











|









|
|




















|
<







73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94

95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161

162
163
164
165
166
167
168
   zero, followed by the trailer, which is terminated by an empty line.

 */

#ifdef CURL_DOES_CONVERSIONS
/* Check for an ASCII hex digit.
   We avoid the use of ISXDIGIT to accommodate non-ASCII hosts. */
static bool isxdigit_ascii(char digit)
{
  return (digit >= 0x30 && digit <= 0x39) /* 0-9 */
    || (digit >= 0x41 && digit <= 0x46) /* A-F */
    || (digit >= 0x61 && digit <= 0x66); /* a-f */
}
#else
#define isxdigit_ascii(x) Curl_isxdigit(x)
#endif

void Curl_httpchunk_init(struct Curl_easy *data)
{
  struct connectdata *conn = data->conn;
  struct Curl_chunker *chunk = &conn->chunk;
  chunk->hexindex = 0;      /* start at 0 */

  chunk->state = CHUNK_HEX; /* we get hex first! */
  Curl_dyn_init(&conn->trailer, DYN_H1_TRAILER);
}

/*
 * 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'.
 */
CHUNKcode Curl_httpchunk_read(struct Curl_easy *data,
                              char *datap,
                              ssize_t datalen,
                              ssize_t *wrotep,
                              CURLcode *extrap)
{
  CURLcode result = CURLE_OK;
  struct connectdata *conn = data->conn;
  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(data, CLIENTWRITE_BODY, datap, datalen);
    if(result) {
      *extrap = result;
      return CHUNKE_PASSTHRU_ERROR;
    }
  }

  while(length) {
    switch(ch->state) {
    case CHUNK_HEX:
      if(isxdigit_ascii(*datap)) {
        if(ch->hexindex < CHUNK_MAXNUM_LEN) {
          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(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;
        }

        if(curlx_strtoofft(ch->hexbuffer, &endptr, 16, &ch->datasize))
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
    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 */
      if(!conn->data->set.http_te_skip && !k->ignorebody) {
        if(!conn->data->set.http_ce_skip && k->writer_stack)
          result = Curl_unencode_write(conn, k->writer_stack, datap, piece);
        else
          result = Curl_client_write(conn, CLIENTWRITE_BODY, datap, piece);

        if(result) {
          *extrap = result;
          return CHUNKE_PASSTHRU_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;








|
|
|

|




















|







189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
    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 */
      if(!data->set.http_te_skip && !k->ignorebody) {
        if(!data->set.http_ce_skip && k->writer_stack)
          result = Curl_unencode_write(data, k->writer_stack, datap, piece);
        else
          result = Curl_client_write(data, CLIENTWRITE_BODY, datap, piece);

        if(result) {
          *extrap = result;
          return CHUNKE_PASSTHRU_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(data); /* sets state back to CHUNK_HEX */
      }
      else if(*datap != 0x0d)
        return CHUNKE_BAD_CHUNK;
      datap++;
      length--;
      break;

238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
          result = Curl_dyn_add(&conn->trailer, (char *)"\x0d\x0a");
          if(result)
            return CHUNKE_OUT_OF_MEMORY;

          tr = Curl_dyn_ptr(&conn->trailer);
          trlen = Curl_dyn_len(&conn->trailer);
          /* Convert to host encoding before calling Curl_client_write */
          result = Curl_convert_from_network(conn->data, tr, trlen);
          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, tr, trlen);
            if(result) {
              *extrap = result;
              return CHUNKE_PASSTHRU_ERROR;
            }
          }
          Curl_dyn_reset(&conn->trailer);
          ch->state = CHUNK_TRAILER_CR;







|






|







237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
          result = Curl_dyn_add(&conn->trailer, (char *)"\x0d\x0a");
          if(result)
            return CHUNKE_OUT_OF_MEMORY;

          tr = Curl_dyn_ptr(&conn->trailer);
          trlen = Curl_dyn_len(&conn->trailer);
          /* Convert to host encoding before calling Curl_client_write */
          result = Curl_convert_from_network(data, tr, trlen);
          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(data, CLIENTWRITE_HEADER, tr, trlen);
            if(result) {
              *extrap = result;
              return CHUNKE_PASSTHRU_ERROR;
            }
          }
          Curl_dyn_reset(&conn->trailer);
          ch->state = CHUNK_TRAILER_CR;
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319

    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;
    }
  }







|







304
305
306
307
308
309
310
311
312
313
314
315
316
317
318

    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->datasize = curlx_sotouz(length);

        return CHUNKE_STOP; /* return stop */
      }
      else
        return CHUNKE_BAD_CHUNK;
    }
  }
Changes to jni/curl/lib/http_chunks.h.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
#ifndef HEADER_CURL_HTTP_CHUNKS_H
#define HEADER_CURL_HTTP_CHUNKS_H
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2020, 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 https://curl.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 connectdata;

/*
 * 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,









|


















|
|

|


















|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
#ifndef HEADER_CURL_HTTP_CHUNKS_H
#define HEADER_CURL_HTTP_CHUNKS_H
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2021, 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 https://curl.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 connectdata;

/*
 * The longest possible hexadecimal number we support in a chunked transfer.
 * Neither RFC2616 nor the later HTTP specs define a maximum chunk size.
 * For 64 bit curl_off_t we support 16 digits. For 32 bit, 8 digits.
 */
#define CHUNK_MAXNUM_LEN (SIZEOF_CURL_OFF_T * 2)

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 'datasize'
     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,
79
80
81
82
83
84
85
86
87
88
89
90

91
92
93
94
95
96
97
98
99
  CHUNKE_PASSTHRU_ERROR, /* Curl_httpchunk_read() returns a CURLcode to use */
  CHUNKE_LAST
} CHUNKcode;

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 */

};

/* The following functions are defined in http_chunks.c */
void Curl_httpchunk_init(struct connectdata *conn);
CHUNKcode Curl_httpchunk_read(struct connectdata *conn, char *datap,
                              ssize_t length, ssize_t *wrote,
                              CURLcode *passthru);

#endif /* HEADER_CURL_HTTP_CHUNKS_H */







<
|

|
<
>



|
|




79
80
81
82
83
84
85

86
87
88

89
90
91
92
93
94
95
96
97
98
  CHUNKE_PASSTHRU_ERROR, /* Curl_httpchunk_read() returns a CURLcode to use */
  CHUNKE_LAST
} CHUNKcode;

const char *Curl_chunked_strerror(CHUNKcode code);

struct Curl_chunker {

  curl_off_t datasize;
  ChunkyState state;
  unsigned char hexindex;

  char hexbuffer[ CHUNK_MAXNUM_LEN + 1]; /* +1 for null-terminator */
};

/* The following functions are defined in http_chunks.c */
void Curl_httpchunk_init(struct Curl_easy *data);
CHUNKcode Curl_httpchunk_read(struct Curl_easy *data, char *datap,
                              ssize_t length, ssize_t *wrote,
                              CURLcode *passthru);

#endif /* HEADER_CURL_HTTP_CHUNKS_H */
Changes to jni/curl/lib/http_digest.c.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2020, 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 https://curl.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







|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2021, 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 https://curl.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
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71

72
73
74
75
76
77
78
79
80
81
82
83
84
/* Test example headers:

WWW-Authenticate: Digest realm="testrealm", nonce="1053604598"
Proxy-Authenticate: Digest realm="testrealm", nonce="1053604598"

*/

CURLcode Curl_input_digest(struct connectdata *conn,
                           bool proxy,
                           const char *header) /* rest of the *-authenticate:
                                                  header */
{
  struct Curl_easy *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_auth_decode_digest_http_message(header, digest);
}

CURLcode Curl_output_digest(struct connectdata *conn,

                            bool proxy,
                            const unsigned char *request,
                            const unsigned char *uripath)
{
  CURLcode result;
  struct Curl_easy *data = conn->data;
  unsigned char *path = NULL;
  char *tmp = NULL;
  char *response;
  size_t len;
  bool have_chlg;

  /* Point to the address of the pointer that holds the string to send to the







|




<
<




















|
>





<







37
38
39
40
41
42
43
44
45
46
47
48


49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75

76
77
78
79
80
81
82
/* Test example headers:

WWW-Authenticate: Digest realm="testrealm", nonce="1053604598"
Proxy-Authenticate: Digest realm="testrealm", nonce="1053604598"

*/

CURLcode Curl_input_digest(struct Curl_easy *data,
                           bool proxy,
                           const char *header) /* rest of the *-authenticate:
                                                  header */
{


  /* 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_auth_decode_digest_http_message(header, digest);
}

CURLcode Curl_output_digest(struct Curl_easy *data,
                            struct connectdata *conn,
                            bool proxy,
                            const unsigned char *request,
                            const unsigned char *uripath)
{
  CURLcode result;

  unsigned char *path = NULL;
  char *tmp = NULL;
  char *response;
  size_t len;
  bool have_chlg;

  /* Point to the address of the pointer that holds the string to send to the
Changes to jni/curl/lib/http_digest.h.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33

34
35
36
37
38
39
40
41
42
#ifndef HEADER_CURL_HTTP_DIGEST_H
#define HEADER_CURL_HTTP_DIGEST_H
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2020, 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 https://curl.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)

/* this is for digest header input */
CURLcode Curl_input_digest(struct connectdata *conn,
                           bool proxy, const char *header);

/* this is for creating digest header output */
CURLcode Curl_output_digest(struct connectdata *conn,

                            bool proxy,
                            const unsigned char *request,
                            const unsigned char *uripath);

void Curl_http_auth_cleanup_digest(struct Curl_easy *data);

#endif /* !CURL_DISABLE_HTTP && !CURL_DISABLE_CRYPTO_AUTH */

#endif /* HEADER_CURL_HTTP_DIGEST_H */









|


















|



|
>









1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
#ifndef HEADER_CURL_HTTP_DIGEST_H
#define HEADER_CURL_HTTP_DIGEST_H
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2021, 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 https://curl.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)

/* this is for digest header input */
CURLcode Curl_input_digest(struct Curl_easy *data,
                           bool proxy, const char *header);

/* this is for creating digest header output */
CURLcode Curl_output_digest(struct Curl_easy *data,
                            struct connectdata *conn,
                            bool proxy,
                            const unsigned char *request,
                            const unsigned char *uripath);

void Curl_http_auth_cleanup_digest(struct Curl_easy *data);

#endif /* !CURL_DISABLE_HTTP && !CURL_DISABLE_CRYPTO_AUTH */

#endif /* HEADER_CURL_HTTP_DIGEST_H */
Changes to jni/curl/lib/http_negotiate.c.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2020, 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 https://curl.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







|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2021, 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 https://curl.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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
#include "vauth/vauth.h"

/* The last 3 #include files should be in this order */
#include "curl_printf.h"
#include "curl_memory.h"
#include "memdebug.h"

CURLcode Curl_input_negotiate(struct connectdata *conn, bool proxy,
                              const char *header)
{
  CURLcode result;
  struct Curl_easy *data = conn->data;
  size_t len;

  /* Point to the username, password, service and host */
  const char *userp;
  const char *passwdp;
  const char *service;
  const char *host;







|
|


<







30
31
32
33
34
35
36
37
38
39
40

41
42
43
44
45
46
47
#include "vauth/vauth.h"

/* The last 3 #include files should be in this order */
#include "curl_printf.h"
#include "curl_memory.h"
#include "memdebug.h"

CURLcode Curl_input_negotiate(struct Curl_easy *data, struct connectdata *conn,
                              bool proxy, const char *header)
{
  CURLcode result;

  size_t len;

  /* Point to the username, password, service and host */
  const char *userp;
  const char *passwdp;
  const char *service;
  const char *host;
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
  while(*header && ISSPACE(*header))
    header++;

  len = strlen(header);
  neg_ctx->havenegdata = len != 0;
  if(!len) {
    if(state == GSS_AUTHSUCC) {
      infof(conn->data, "Negotiate auth restarted\n");
      Curl_http_auth_cleanup_negotiate(conn);
    }
    else if(state != GSS_AUTHNONE) {
      /* The server rejected our authentication and hasn't supplied any more
      negotiation mechanisms */
      Curl_http_auth_cleanup_negotiate(conn);
      return CURLE_LOGIN_DENIED;







|







85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
  while(*header && ISSPACE(*header))
    header++;

  len = strlen(header);
  neg_ctx->havenegdata = len != 0;
  if(!len) {
    if(state == GSS_AUTHSUCC) {
      infof(data, "Negotiate auth restarted\n");
      Curl_http_auth_cleanup_negotiate(conn);
    }
    else if(state != GSS_AUTHNONE) {
      /* The server rejected our authentication and hasn't supplied any more
      negotiation mechanisms */
      Curl_http_auth_cleanup_negotiate(conn);
      return CURLE_LOGIN_DENIED;
112
113
114
115
116
117
118
119

120
121
122
123
124
125
126
127
128
129
130
131
132
133
134

  if(result)
    Curl_http_auth_cleanup_negotiate(conn);

  return result;
}

CURLcode Curl_output_negotiate(struct connectdata *conn, bool proxy)

{
  struct negotiatedata *neg_ctx = proxy ? &conn->proxyneg :
    &conn->negotiate;
  struct auth *authp = proxy ? &conn->data->state.authproxy :
    &conn->data->state.authhost;
  curlnegotiate *state = proxy ? &conn->proxy_negotiate_state :
    &conn->http_negotiate_state;
  struct Curl_easy *data = conn->data;
  char *base64 = NULL;
  size_t len = 0;
  char *userp;
  CURLcode result;

  authp->done = FALSE;








|
>



|
<


<







111
112
113
114
115
116
117
118
119
120
121
122
123

124
125

126
127
128
129
130
131
132

  if(result)
    Curl_http_auth_cleanup_negotiate(conn);

  return result;
}

CURLcode Curl_output_negotiate(struct Curl_easy *data,
                               struct connectdata *conn, bool proxy)
{
  struct negotiatedata *neg_ctx = proxy ? &conn->proxyneg :
    &conn->negotiate;
  struct auth *authp = proxy ? &data->state.authproxy : &data->state.authhost;

  curlnegotiate *state = proxy ? &conn->proxy_negotiate_state :
    &conn->http_negotiate_state;

  char *base64 = NULL;
  size_t len = 0;
  char *userp;
  CURLcode result;

  authp->done = FALSE;

143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
    }
  }

  if(neg_ctx->noauthpersist ||
    (*state != GSS_AUTHDONE && *state != GSS_AUTHSUCC)) {

    if(neg_ctx->noauthpersist && *state == GSS_AUTHSUCC) {
      infof(conn->data, "Curl_output_negotiate, "
       "no persistent authentication: cleanup existing context");
      Curl_http_auth_cleanup_negotiate(conn);
    }
    if(!neg_ctx->context) {
      result = Curl_input_negotiate(conn, proxy, "Negotiate");
      if(result == CURLE_AUTH_ERROR) {
        /* negotiate auth failed, let's continue unauthenticated to stay
         * compatible with the behavior before curl-7_64_0-158-g6c6035532 */
        authp->done = TRUE;
        return CURLE_OK;
      }
      else if(result)
        return result;
    }

    result = Curl_auth_create_spnego_message(conn->data,
      neg_ctx, &base64, &len);
    if(result)
      return result;

    userp = aprintf("%sAuthorization: Negotiate %s\r\n", proxy ? "Proxy-" : "",
                    base64);

    if(proxy) {







|




|










|
<







141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164

165
166
167
168
169
170
171
    }
  }

  if(neg_ctx->noauthpersist ||
    (*state != GSS_AUTHDONE && *state != GSS_AUTHSUCC)) {

    if(neg_ctx->noauthpersist && *state == GSS_AUTHSUCC) {
      infof(data, "Curl_output_negotiate, "
       "no persistent authentication: cleanup existing context");
      Curl_http_auth_cleanup_negotiate(conn);
    }
    if(!neg_ctx->context) {
      result = Curl_input_negotiate(data, conn, proxy, "Negotiate");
      if(result == CURLE_AUTH_ERROR) {
        /* negotiate auth failed, let's continue unauthenticated to stay
         * compatible with the behavior before curl-7_64_0-158-g6c6035532 */
        authp->done = TRUE;
        return CURLE_OK;
      }
      else if(result)
        return result;
    }

    result = Curl_auth_create_spnego_message(data, neg_ctx, &base64, &len);

    if(result)
      return result;

    userp = aprintf("%sAuthorization: Negotiate %s\r\n", proxy ? "Proxy-" : "",
                    base64);

    if(proxy) {
Changes to jni/curl/lib/http_negotiate.h.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32

33
34
35
36
37
38
39
40
#ifndef HEADER_CURL_HTTP_NEGOTIATE_H
#define HEADER_CURL_HTTP_NEGOTIATE_H
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2020, 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 https://curl.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_HTTP) && defined(USE_SPNEGO)

/* this is for Negotiate header input */
CURLcode Curl_input_negotiate(struct connectdata *conn, bool proxy,
                              const char *header);

/* this is for creating Negotiate header output */
CURLcode Curl_output_negotiate(struct connectdata *conn, bool proxy);


void Curl_http_auth_cleanup_negotiate(struct connectdata *conn);

#else /* !CURL_DISABLE_HTTP && USE_SPNEGO */
#define Curl_http_auth_cleanup_negotiate(x)
#endif

#endif /* HEADER_CURL_HTTP_NEGOTIATE_H */









|

















|
|


|
>








1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
#ifndef HEADER_CURL_HTTP_NEGOTIATE_H
#define HEADER_CURL_HTTP_NEGOTIATE_H
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2021, 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 https://curl.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_HTTP) && defined(USE_SPNEGO)

/* this is for Negotiate header input */
CURLcode Curl_input_negotiate(struct Curl_easy *data, struct connectdata *conn,
                              bool proxy, const char *header);

/* this is for creating Negotiate header output */
CURLcode Curl_output_negotiate(struct Curl_easy *data,
                               struct connectdata *conn, bool proxy);

void Curl_http_auth_cleanup_negotiate(struct connectdata *conn);

#else /* !CURL_DISABLE_HTTP && USE_SPNEGO */
#define Curl_http_auth_cleanup_negotiate(x)
#endif

#endif /* HEADER_CURL_HTTP_NEGOTIATE_H */
Changes to jni/curl/lib/http_ntlm.c.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2020, 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 https://curl.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







|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2021, 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 https://curl.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
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70

71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171

#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;
  curlntlm *state;
  CURLcode result = CURLE_OK;


  ntlm = proxy ? &conn->proxyntlm : &conn->ntlm;
  state = proxy ? &conn->proxy_ntlm_state : &conn->http_ntlm_state;

  if(checkprefix("NTLM", header)) {
    header += strlen("NTLM");

    while(*header && ISSPACE(*header))
      header++;

    if(*header) {
      result = Curl_auth_decode_ntlm_type2_message(conn->data, header, ntlm);
      if(result)
        return result;

      *state = NTLMSTATE_TYPE2; /* We got a type-2 message */
    }
    else {
      if(*state == NTLMSTATE_LAST) {
        infof(conn->data, "NTLM auth restarted\n");
        Curl_http_auth_cleanup_ntlm(conn);
      }
      else if(*state == NTLMSTATE_TYPE3) {
        infof(conn->data, "NTLM handshake rejected\n");
        Curl_http_auth_cleanup_ntlm(conn);
        *state = NTLMSTATE_NONE;
        return CURLE_REMOTE_ACCESS_DENIED;
      }
      else if(*state >= NTLMSTATE_TYPE1) {
        infof(conn->data, "NTLM handshake failure (internal error)\n");
        return CURLE_REMOTE_ACCESS_DENIED;
      }

      *state = NTLMSTATE_TYPE1; /* We should send away a type-1 */
    }
  }

  return result;
}

/*
 * This is for creating ntlm header output
 */
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 username, password, service and host */
  const char *userp;
  const char *passwdp;
  const char *service = NULL;
  const char *hostname = NULL;

  /* point to the correct struct with this */
  struct ntlmdata *ntlm;
  curlntlm *state;
  struct auth *authp;
  struct Curl_easy *data = conn->data;


  DEBUGASSERT(conn);
  DEBUGASSERT(data);

  if(proxy) {
#ifndef CURL_DISABLE_PROXY
    allocuserpwd = &data->state.aptr.proxyuserpwd;
    userp = conn->http_proxy.user;
    passwdp = conn->http_proxy.passwd;
    service = conn->data->set.str[STRING_PROXY_SERVICE_NAME] ?
              conn->data->set.str[STRING_PROXY_SERVICE_NAME] : "HTTP";
    hostname = conn->http_proxy.host.name;
    ntlm = &conn->proxyntlm;
    state = &conn->proxy_ntlm_state;
    authp = &conn->data->state.authproxy;
#else
    return CURLE_NOT_BUILT_IN;
#endif
  }
  else {
    allocuserpwd = &data->state.aptr.userpwd;
    userp = conn->user;
    passwdp = conn->passwd;
    service = conn->data->set.str[STRING_SERVICE_NAME] ?
              conn->data->set.str[STRING_SERVICE_NAME] : "HTTP";
    hostname = conn->host.name;
    ntlm = &conn->ntlm;
    state = &conn->http_ntlm_state;
    authp = &conn->data->state.authhost;
  }
  authp->done = FALSE;

  /* not set means empty */
  if(!userp)
    userp = "";








|








>











|







|



|





|













|



















<
|









|
|



|








|
|



|







55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134

135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171

#if DEBUG_ME
# define DEBUG_OUT(x) x
#else
# define DEBUG_OUT(x) Curl_nop_stmt
#endif

CURLcode Curl_input_ntlm(struct Curl_easy *data,
                         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;
  curlntlm *state;
  CURLcode result = CURLE_OK;
  struct connectdata *conn = data->conn;

  ntlm = proxy ? &conn->proxyntlm : &conn->ntlm;
  state = proxy ? &conn->proxy_ntlm_state : &conn->http_ntlm_state;

  if(checkprefix("NTLM", header)) {
    header += strlen("NTLM");

    while(*header && ISSPACE(*header))
      header++;

    if(*header) {
      result = Curl_auth_decode_ntlm_type2_message(data, header, ntlm);
      if(result)
        return result;

      *state = NTLMSTATE_TYPE2; /* We got a type-2 message */
    }
    else {
      if(*state == NTLMSTATE_LAST) {
        infof(data, "NTLM auth restarted\n");
        Curl_http_auth_cleanup_ntlm(conn);
      }
      else if(*state == NTLMSTATE_TYPE3) {
        infof(data, "NTLM handshake rejected\n");
        Curl_http_auth_cleanup_ntlm(conn);
        *state = NTLMSTATE_NONE;
        return CURLE_REMOTE_ACCESS_DENIED;
      }
      else if(*state >= NTLMSTATE_TYPE1) {
        infof(data, "NTLM handshake failure (internal error)\n");
        return CURLE_REMOTE_ACCESS_DENIED;
      }

      *state = NTLMSTATE_TYPE1; /* We should send away a type-1 */
    }
  }

  return result;
}

/*
 * This is for creating ntlm header output
 */
CURLcode Curl_output_ntlm(struct Curl_easy *data, 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 username, password, service and host */
  const char *userp;
  const char *passwdp;
  const char *service = NULL;
  const char *hostname = NULL;

  /* point to the correct struct with this */
  struct ntlmdata *ntlm;
  curlntlm *state;
  struct auth *authp;

  struct connectdata *conn = data->conn;

  DEBUGASSERT(conn);
  DEBUGASSERT(data);

  if(proxy) {
#ifndef CURL_DISABLE_PROXY
    allocuserpwd = &data->state.aptr.proxyuserpwd;
    userp = conn->http_proxy.user;
    passwdp = conn->http_proxy.passwd;
    service = data->set.str[STRING_PROXY_SERVICE_NAME] ?
              data->set.str[STRING_PROXY_SERVICE_NAME] : "HTTP";
    hostname = conn->http_proxy.host.name;
    ntlm = &conn->proxyntlm;
    state = &conn->proxy_ntlm_state;
    authp = &data->state.authproxy;
#else
    return CURLE_NOT_BUILT_IN;
#endif
  }
  else {
    allocuserpwd = &data->state.aptr.userpwd;
    userp = conn->user;
    passwdp = conn->passwd;
    service = data->set.str[STRING_SERVICE_NAME] ?
              data->set.str[STRING_SERVICE_NAME] : "HTTP";
    hostname = conn->host.name;
    ntlm = &conn->ntlm;
    state = &conn->http_ntlm_state;
    authp = &data->state.authhost;
  }
  authp->done = FALSE;

  /* not set means empty */
  if(!userp)
    userp = "";

184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
#endif
#endif

  switch(*state) {
  case NTLMSTATE_TYPE1:
  default: /* for the weird cases we (re)start here */
    /* Create a type-1 message */
    result = Curl_auth_create_ntlm_type1_message(conn->data, userp, passwdp,
                                                 service, hostname,
                                                 ntlm, &base64,
                                                 &len);
    if(result)
      return result;

    if(base64) {







|







184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
#endif
#endif

  switch(*state) {
  case NTLMSTATE_TYPE1:
  default: /* for the weird cases we (re)start here */
    /* Create a type-1 message */
    result = Curl_auth_create_ntlm_type1_message(data, userp, passwdp,
                                                 service, hostname,
                                                 ntlm, &base64,
                                                 &len);
    if(result)
      return result;

    if(base64) {
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220

      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_auth_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",







|







206
207
208
209
210
211
212
213
214
215
216
217
218
219
220

      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_auth_create_ntlm_type3_message(data, userp, passwdp,
                                                 ntlm, &base64, &len);
    if(result)
      return result;

    if(base64) {
      free(*allocuserpwd);
      *allocuserpwd = aprintf("%sAuthorization: NTLM %s\r\n",
Changes to jni/curl/lib/http_ntlm.h.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
#ifndef HEADER_CURL_HTTP_NTLM_H
#define HEADER_CURL_HTTP_NTLM_H
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2020, 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 https://curl.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 */
CURLcode Curl_input_ntlm(struct connectdata *conn, bool proxy,
                         const char *header);

/* this is for creating ntlm header output */
CURLcode Curl_output_ntlm(struct connectdata *conn, bool proxy);

void Curl_http_auth_cleanup_ntlm(struct connectdata *conn);

#else /* !CURL_DISABLE_HTTP && USE_NTLM */
#define Curl_http_auth_cleanup_ntlm(x)
#endif

#endif /* HEADER_CURL_HTTP_NTLM_H */









|



















|



|








1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
#ifndef HEADER_CURL_HTTP_NTLM_H
#define HEADER_CURL_HTTP_NTLM_H
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2021, 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 https://curl.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 */
CURLcode Curl_input_ntlm(struct Curl_easy *data, bool proxy,
                         const char *header);

/* this is for creating ntlm header output */
CURLcode Curl_output_ntlm(struct Curl_easy *data, bool proxy);

void Curl_http_auth_cleanup_ntlm(struct connectdata *conn);

#else /* !CURL_DISABLE_HTTP && USE_NTLM */
#define Curl_http_auth_cleanup_ntlm(x)
#endif

#endif /* HEADER_CURL_HTTP_NTLM_H */
Changes to jni/curl/lib/http_proxy.c.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2020, 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 https://curl.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







|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2021, 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 https://curl.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
23
24
25
26
27
28
29



30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52

53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
#include "curl_setup.h"

#include "http_proxy.h"

#if !defined(CURL_DISABLE_PROXY) && !defined(CURL_DISABLE_HTTP)

#include <curl/curl.h>



#include "sendf.h"
#include "http.h"
#include "url.h"
#include "select.h"
#include "progress.h"
#include "non-ascii.h"
#include "connect.h"
#include "curlx.h"
#include "vtls/vtls.h"

/* The last 3 #include files should be in this order */
#include "curl_printf.h"
#include "curl_memory.h"
#include "memdebug.h"

/*
 * Perform SSL initialization for HTTPS proxy.  Sets
 * proxy_ssl_connected connection bit when complete.  Can be
 * called multiple times.
 */
static CURLcode https_proxy_connect(struct connectdata *conn, int sockindex)
{
#ifdef USE_SSL

  CURLcode result = CURLE_OK;
  DEBUGASSERT(conn->http_proxy.proxytype == CURLPROXY_HTTPS);
  if(!conn->bits.proxy_ssl_connected[sockindex]) {
    /* perform SSL initialization for this socket */
    result =
      Curl_ssl_connect_nonblocking(conn, sockindex,
                                   &conn->bits.proxy_ssl_connected[sockindex]);
    if(result)
      /* a failed connection is marked for closure to prevent (bad) re-use or
         similar */
      connclose(conn, "TLS handshake failed");
  }
  return result;
#else
  (void) conn;
  (void) sockindex;
  return CURLE_NOT_BUILT_IN;
#endif
}

CURLcode Curl_proxy_connect(struct connectdata *conn, int sockindex)
{
  struct Curl_easy *data = conn->data;
  if(conn->http_proxy.proxytype == CURLPROXY_HTTPS) {
    const CURLcode result = https_proxy_connect(conn, sockindex);
    if(result)
      return result;
    if(!conn->bits.proxy_ssl_connected[sockindex])
      return result; /* wait for HTTPS proxy SSL initialization to complete */
  }

  if(conn->bits.tunnel_proxy && conn->bits.httpproxy) {







>
>
>




















|


>





|








|





|

|

|







23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
#include "curl_setup.h"

#include "http_proxy.h"

#if !defined(CURL_DISABLE_PROXY) && !defined(CURL_DISABLE_HTTP)

#include <curl/curl.h>
#ifdef USE_HYPER
#include <hyper.h>
#endif
#include "sendf.h"
#include "http.h"
#include "url.h"
#include "select.h"
#include "progress.h"
#include "non-ascii.h"
#include "connect.h"
#include "curlx.h"
#include "vtls/vtls.h"

/* The last 3 #include files should be in this order */
#include "curl_printf.h"
#include "curl_memory.h"
#include "memdebug.h"

/*
 * Perform SSL initialization for HTTPS proxy.  Sets
 * proxy_ssl_connected connection bit when complete.  Can be
 * called multiple times.
 */
static CURLcode https_proxy_connect(struct Curl_easy *data, int sockindex)
{
#ifdef USE_SSL
  struct connectdata *conn = data->conn;
  CURLcode result = CURLE_OK;
  DEBUGASSERT(conn->http_proxy.proxytype == CURLPROXY_HTTPS);
  if(!conn->bits.proxy_ssl_connected[sockindex]) {
    /* perform SSL initialization for this socket */
    result =
      Curl_ssl_connect_nonblocking(data, conn, sockindex,
                                   &conn->bits.proxy_ssl_connected[sockindex]);
    if(result)
      /* a failed connection is marked for closure to prevent (bad) re-use or
         similar */
      connclose(conn, "TLS handshake failed");
  }
  return result;
#else
  (void) data;
  (void) sockindex;
  return CURLE_NOT_BUILT_IN;
#endif
}

CURLcode Curl_proxy_connect(struct Curl_easy *data, int sockindex)
{
  struct connectdata *conn = data->conn;
  if(conn->http_proxy.proxytype == CURLPROXY_HTTPS) {
    const CURLcode result = https_proxy_connect(data, sockindex);
    if(result)
      return result;
    if(!conn->bits.proxy_ssl_connected[sockindex])
      return result; /* wait for HTTPS proxy SSL initialization to complete */
  }

  if(conn->bits.tunnel_proxy && conn->bits.httpproxy) {
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
     * 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 CONNECT response is not instant.
     */
    prot_save = conn->data->req.p.http;
    memset(&http_proxy, 0, sizeof(http_proxy));
    conn->data->req.p.http = &http_proxy;
    connkeep(conn, "HTTP proxy CONNECT");

    /* for the secondary socket (FTP), use the "connect to host"
     * but ignore the "connect to port" (use the secondary port)
     */

    if(conn->bits.conn_to_host)
      hostname = conn->conn_to_host.name;
    else if(sockindex == SECONDARYSOCKET)
      hostname = conn->secondaryhostname;
    else
      hostname = conn->host.name;

    if(sockindex == SECONDARYSOCKET)
      remote_port = conn->secondary_port;
    else if(conn->bits.conn_to_port)
      remote_port = conn->conn_to_port;
    else
      remote_port = conn->remote_port;
    result = Curl_proxyCONNECT(conn, sockindex, hostname, remote_port);
    conn->data->req.p.http = prot_save;
    if(CURLE_OK != result)
      return result;
    Curl_safefree(data->state.aptr.proxyuserpwd);
#else
    return CURLE_NOT_BUILT_IN;
#endif
  }







|

|



















|
|







102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
     * 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 CONNECT response is not instant.
     */
    prot_save = data->req.p.http;
    memset(&http_proxy, 0, sizeof(http_proxy));
    data->req.p.http = &http_proxy;
    connkeep(conn, "HTTP proxy CONNECT");

    /* for the secondary socket (FTP), use the "connect to host"
     * but ignore the "connect to port" (use the secondary port)
     */

    if(conn->bits.conn_to_host)
      hostname = conn->conn_to_host.name;
    else if(sockindex == SECONDARYSOCKET)
      hostname = conn->secondaryhostname;
    else
      hostname = conn->host.name;

    if(sockindex == SECONDARYSOCKET)
      remote_port = conn->secondary_port;
    else if(conn->bits.conn_to_port)
      remote_port = conn->conn_to_port;
    else
      remote_port = conn->remote_port;
    result = Curl_proxyCONNECT(data, sockindex, hostname, remote_port);
    data->req.p.http = prot_save;
    if(CURLE_OK != result)
      return result;
    Curl_safefree(data->state.aptr.proxyuserpwd);
#else
    return CURLE_NOT_BUILT_IN;
#endif
  }
145
146
147
148
149
150
151
152
153
154

155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177

178
179
180
181
182
183
































184
185
186
187

188
189
190
191
192

193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211


212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228





229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304

305
306
307
308
309
310
311

bool Curl_connect_ongoing(struct connectdata *conn)
{
  return conn->connect_state &&
    (conn->connect_state->tunnel_state != TUNNEL_COMPLETE);
}

static CURLcode connect_init(struct connectdata *conn, bool reinit)
{
  struct http_connect_state *s;

  if(!reinit) {
    DEBUGASSERT(!conn->connect_state);
    s = calloc(1, sizeof(struct http_connect_state));
    if(!s)
      return CURLE_OUT_OF_MEMORY;
    infof(conn->data, "allocate connect buffer!\n");
    conn->connect_state = s;
    Curl_dyn_init(&s->rcvbuf, DYN_PROXY_CONNECT_HEADERS);
  }
  else {
    DEBUGASSERT(conn->connect_state);
    s = conn->connect_state;
    Curl_dyn_reset(&s->rcvbuf);
  }
  s->tunnel_state = TUNNEL_INIT;
  s->keepon = KEEPON_CONNECT;
  s->cl = 0;
  s->close_connection = FALSE;
  return CURLE_OK;
}

static void connect_done(struct connectdata *conn)
{

  struct http_connect_state *s = conn->connect_state;
  s->tunnel_state = TUNNEL_COMPLETE;
  Curl_dyn_free(&s->rcvbuf);
  infof(conn->data, "CONNECT phase completed!\n");
}

































static CURLcode CONNECT(struct connectdata *conn,
                        int sockindex,
                        const char *hostname,
                        int remote_port)

{
  int subversion = 0;
  struct Curl_easy *data = conn->data;
  struct SingleRequest *k = &data->req;
  CURLcode result;

  curl_socket_t tunnelsocket = conn->sock[sockindex];
  struct http_connect_state *s = conn->connect_state;
  char *linep;
  size_t perline;

#define SELECT_OK      0
#define SELECT_ERROR   1

  if(Curl_connect_complete(conn))
    return CURLE_OK; /* CONNECT is already completed */

  conn->bits.proxy_connect_closed = FALSE;

  do {
    timediff_t check;
    if(TUNNEL_INIT == s->tunnel_state) {
      /* BEGIN CONNECT PHASE */
      char *host_port;
      struct dynbuf req;



      infof(data, "Establish HTTP proxy tunnel to %s:%d\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;

      host_port = aprintf("%s:%d", hostname, remote_port);
      if(!host_port)
        return CURLE_OUT_OF_MEMORY;

      /* initialize a dynamic send-buffer */
      Curl_dyn_init(&req, DYN_HTTP_REQUEST);






      /* Setup the proxy-authorization header, if any */
      result = Curl_http_output_auth(conn, "CONNECT", host_port, TRUE);

      free(host_port);

      if(!result) {
        char *host = NULL;
        const char *proxyconn = "";
        const char *useragent = "";
        const char *httpv =
          (conn->http_proxy.proxytype == CURLPROXY_HTTP_1_0) ? "1.0" : "1.1";
        bool ipv6_ip = conn->bits.ipv6_ip;
        char *hostheader;

        /* the hostname may be different */
        if(hostname != conn->host.name)
          ipv6_ip = (strchr(hostname, ':') != NULL);
        hostheader = /* host:port with IPv6 support */
          aprintf("%s%s%s:%d", ipv6_ip?"[":"", hostname, ipv6_ip?"]":"",
                  remote_port);
        if(!hostheader) {
          Curl_dyn_free(&req);
          return CURLE_OUT_OF_MEMORY;
        }

        if(!Curl_checkProxyheaders(conn, "Host")) {
          host = aprintf("Host: %s\r\n", hostheader);
          if(!host) {
            free(hostheader);
            Curl_dyn_free(&req);
            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 = data->state.aptr.uagent;

        result =
          Curl_dyn_addf(&req,
                        "CONNECT %s HTTP/%s\r\n"
                        "%s"  /* Host: */
                        "%s"  /* Proxy-Authorization */
                        "%s"  /* User-Agent */
                        "%s", /* Proxy-Connection */
                        hostheader,
                        httpv,
                        host?host:"",
                        data->state.aptr.proxyuserpwd?
                        data->state.aptr.proxyuserpwd:"",
                        useragent,
                        proxyconn);

        if(host)
          free(host);
        free(hostheader);

        if(!result)
          result = Curl_add_custom_headers(conn, TRUE, &req);

        if(!result)
          /* CRLF terminate the request */
          result = Curl_dyn_add(&req, "\r\n");

        if(!result) {
          /* Send the connect request to the proxy */
          /* BLOCKING */
          result = Curl_buffer_send(&req, conn, &data->info.request_size, 0,
                                    sockindex);
        }
        if(result)
          failf(data, "Failed sending CONNECT to proxy");
      }


      Curl_dyn_free(&req);
      if(result)
        return result;

      s->tunnel_state = TUNNEL_CONNECT;
    } /* END CONNECT PHASE */








|


>





|















|

>



|


>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|



>


<


>

















<

>
>










<
<
<
<



>
>
>
>
>

|
|
<


<




<
<

<
<
<
<
<
<
<
<
<
<
<
|
<
<
<
<
<
<
<
<


|


















<
<
<
<

|








|





|
>







149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228

229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248

249
250
251
252
253
254
255
256
257
258
259
260
261




262
263
264
265
266
267
268
269
270
271
272

273
274

275
276
277
278


279











280








281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301




302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326

bool Curl_connect_ongoing(struct connectdata *conn)
{
  return conn->connect_state &&
    (conn->connect_state->tunnel_state != TUNNEL_COMPLETE);
}

static CURLcode connect_init(struct Curl_easy *data, bool reinit)
{
  struct http_connect_state *s;
  struct connectdata *conn = data->conn;
  if(!reinit) {
    DEBUGASSERT(!conn->connect_state);
    s = calloc(1, sizeof(struct http_connect_state));
    if(!s)
      return CURLE_OUT_OF_MEMORY;
    infof(data, "allocate connect buffer!\n");
    conn->connect_state = s;
    Curl_dyn_init(&s->rcvbuf, DYN_PROXY_CONNECT_HEADERS);
  }
  else {
    DEBUGASSERT(conn->connect_state);
    s = conn->connect_state;
    Curl_dyn_reset(&s->rcvbuf);
  }
  s->tunnel_state = TUNNEL_INIT;
  s->keepon = KEEPON_CONNECT;
  s->cl = 0;
  s->close_connection = FALSE;
  return CURLE_OK;
}

static void connect_done(struct Curl_easy *data)
{
  struct connectdata *conn = data->conn;
  struct http_connect_state *s = conn->connect_state;
  s->tunnel_state = TUNNEL_COMPLETE;
  Curl_dyn_free(&s->rcvbuf);
  infof(data, "CONNECT phase completed!\n");
}

static CURLcode CONNECT_host(struct Curl_easy *data,
                             struct connectdata *conn,
                             const char *hostname,
                             int remote_port,
                             char **connecthostp,
                             char **hostp)
{
  char *hostheader; /* for CONNECT */
  char *host = NULL; /* Host: */
  bool ipv6_ip = conn->bits.ipv6_ip;

  /* the hostname may be different */
  if(hostname != conn->host.name)
    ipv6_ip = (strchr(hostname, ':') != NULL);
  hostheader = /* host:port with IPv6 support */
    aprintf("%s%s%s:%d", ipv6_ip?"[":"", hostname, ipv6_ip?"]":"",
            remote_port);
  if(!hostheader)
    return CURLE_OUT_OF_MEMORY;

  if(!Curl_checkProxyheaders(data, conn, "Host")) {
    host = aprintf("Host: %s\r\n", hostheader);
    if(!host) {
      free(hostheader);
      return CURLE_OUT_OF_MEMORY;
    }
  }
  *connecthostp = hostheader;
  *hostp = host;
  return CURLE_OK;
}

static CURLcode CONNECT(struct Curl_easy *data,
                        int sockindex,
                        const char *hostname,
                        int remote_port)
#ifndef USE_HYPER
{
  int subversion = 0;

  struct SingleRequest *k = &data->req;
  CURLcode result;
  struct connectdata *conn = data->conn;
  curl_socket_t tunnelsocket = conn->sock[sockindex];
  struct http_connect_state *s = conn->connect_state;
  char *linep;
  size_t perline;

#define SELECT_OK      0
#define SELECT_ERROR   1

  if(Curl_connect_complete(conn))
    return CURLE_OK; /* CONNECT is already completed */

  conn->bits.proxy_connect_closed = FALSE;

  do {
    timediff_t check;
    if(TUNNEL_INIT == s->tunnel_state) {
      /* BEGIN CONNECT PHASE */

      struct dynbuf req;
      char *hostheader = NULL;
      char *host = NULL;

      infof(data, "Establish HTTP proxy tunnel to %s:%d\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 */
      Curl_dyn_init(&req, DYN_HTTP_REQUEST);

      result = CONNECT_host(data, conn,
                            hostname, remote_port, &hostheader, &host);
      if(result)
        return result;

      /* Setup the proxy-authorization header, if any */
      result = Curl_http_output_auth(data, conn, "CONNECT", HTTPREQ_GET,
                                     hostheader, TRUE);


      if(!result) {

        const char *proxyconn = "";
        const char *useragent = "";
        const char *httpv =
          (conn->http_proxy.proxytype == CURLPROXY_HTTP_1_0) ? "1.0" : "1.1";














        if(!Curl_checkProxyheaders(data, conn, "Proxy-Connection"))








          proxyconn = "Proxy-Connection: Keep-Alive\r\n";

        if(!Curl_checkProxyheaders(data, conn, "User-Agent") &&
           data->set.str[STRING_USERAGENT])
          useragent = data->state.aptr.uagent;

        result =
          Curl_dyn_addf(&req,
                        "CONNECT %s HTTP/%s\r\n"
                        "%s"  /* Host: */
                        "%s"  /* Proxy-Authorization */
                        "%s"  /* User-Agent */
                        "%s", /* Proxy-Connection */
                        hostheader,
                        httpv,
                        host?host:"",
                        data->state.aptr.proxyuserpwd?
                        data->state.aptr.proxyuserpwd:"",
                        useragent,
                        proxyconn);





        if(!result)
          result = Curl_add_custom_headers(data, TRUE, &req);

        if(!result)
          /* CRLF terminate the request */
          result = Curl_dyn_add(&req, "\r\n");

        if(!result) {
          /* Send the connect request to the proxy */
          /* BLOCKING */
          result = Curl_buffer_send(&req, data, &data->info.request_size, 0,
                                    sockindex);
        }
        if(result)
          failf(data, "Failed sending CONNECT to proxy");
      }
      free(host);
      free(hostheader);
      Curl_dyn_free(&req);
      if(result)
        return result;

      s->tunnel_state = TUNNEL_CONNECT;
    } /* END CONNECT PHASE */

326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345

      while(s->keepon) {
        ssize_t gotbytes;
        char byte;

        /* Read one byte at a time to avoid a race condition. Wait at most one
           second before looping to ensure continuous pgrsUpdates. */
        result = Curl_read(conn, tunnelsocket, &byte, 1, &gotbytes);
        if(result == CURLE_AGAIN)
          /* socket buffer drained, return */
          return CURLE_OK;

        if(Curl_pgrsUpdate(conn))
          return CURLE_ABORTED_BY_CALLBACK;

        if(result) {
          s->keepon = KEEPON_DONE;
          break;
        }
        else if(gotbytes <= 0) {







|




|







341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360

      while(s->keepon) {
        ssize_t gotbytes;
        char byte;

        /* Read one byte at a time to avoid a race condition. Wait at most one
           second before looping to ensure continuous pgrsUpdates. */
        result = Curl_read(data, tunnelsocket, &byte, 1, &gotbytes);
        if(result == CURLE_AGAIN)
          /* socket buffer drained, return */
          return CURLE_OK;

        if(Curl_pgrsUpdate(data))
          return CURLE_ABORTED_BY_CALLBACK;

        if(result) {
          s->keepon = KEEPON_DONE;
          break;
        }
        else if(gotbytes <= 0) {
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
               properly to know when the end of the body is reached */
            CHUNKcode r;
            CURLcode extra;
            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, &byte, 1, &tookcareof, &extra);
            if(r == CHUNKE_STOP) {
              /* we're done reading chunks! */
              infof(data, "chunk reading DONE\n");
              s->keepon = KEEPON_DONE;
              /* we did the full CONNECT treatment, go COMPLETE */
              s->tunnel_state = TUNNEL_COMPLETE;
            }







|







390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
               properly to know when the end of the body is reached */
            CHUNKcode r;
            CURLcode extra;
            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(data, &byte, 1, &tookcareof, &extra);
            if(r == CHUNKE_STOP) {
              /* we're done reading chunks! */
              infof(data, "chunk reading DONE\n");
              s->keepon = KEEPON_DONE;
              /* we did the full CONNECT treatment, go COMPLETE */
              s->tunnel_state = TUNNEL_COMPLETE;
            }
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428

        if(!data->set.suppress_connect_headers) {
          /* send the header to the callback */
          int writetype = CLIENTWRITE_HEADER;
          if(data->set.include_header)
            writetype |= CLIENTWRITE_BODY;

          result = Curl_client_write(conn, writetype, linep, perline);
          if(result)
            return result;
        }

        data->info.header_size += (long)perline;

        /* Newlines are CRLF, so the CR is ignored as the line isn't







|







429
430
431
432
433
434
435
436
437
438
439
440
441
442
443

        if(!data->set.suppress_connect_headers) {
          /* send the header to the callback */
          int writetype = CLIENTWRITE_HEADER;
          if(data->set.include_header)
            writetype |= CLIENTWRITE_BODY;

          result = Curl_client_write(data, writetype, linep, perline);
          if(result)
            return result;
        }

        data->info.header_size += (long)perline;

        /* Newlines are CRLF, so the CR is ignored as the line isn't
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482

483
484


485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505

              if(linep[1] == '\n')
                /* this can only be a LF if the letter at index 0 was a CR */
                linep++;

              /* now parse the chunked piece of data so that we can properly
                 tell when the stream ends */
              r = Curl_httpchunk_read(conn, linep + 1, 1, &gotbytes,
                                      &extra);
              if(r == CHUNKE_STOP) {
                /* we're done reading chunks! */
                infof(data, "chunk reading DONE\n");
                s->keepon = KEEPON_DONE;
                /* we did the full CONNECT treatment, go to COMPLETE */
                s->tunnel_state = TUNNEL_COMPLETE;
              }
            }
            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 */
              s->keepon = KEEPON_DONE;
            }
          }
          else
            s->keepon = KEEPON_DONE;
          if(!s->cl)

            /* we did the full CONNECT treatment, go to COMPLETE */
            s->tunnel_state = TUNNEL_COMPLETE;


          continue;
        }

        if((checkprefix("WWW-Authenticate:", linep) &&
            (401 == k->httpcode)) ||
           (checkprefix("Proxy-authenticate:", linep) &&
            (407 == k->httpcode))) {

          bool proxy = (k->httpcode == 407) ? TRUE : FALSE;
          char *auth = Curl_copy_header_value(linep);
          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:", linep)) {







|


















|
>


>
>













|







471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523

              if(linep[1] == '\n')
                /* this can only be a LF if the letter at index 0 was a CR */
                linep++;

              /* now parse the chunked piece of data so that we can properly
                 tell when the stream ends */
              r = Curl_httpchunk_read(data, linep + 1, 1, &gotbytes,
                                      &extra);
              if(r == CHUNKE_STOP) {
                /* we're done reading chunks! */
                infof(data, "chunk reading DONE\n");
                s->keepon = KEEPON_DONE;
                /* we did the full CONNECT treatment, go to COMPLETE */
                s->tunnel_state = TUNNEL_COMPLETE;
              }
            }
            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 */
              s->keepon = KEEPON_DONE;
            }
          }
          else
            s->keepon = KEEPON_DONE;

          if(s->keepon == KEEPON_DONE && !s->cl)
            /* we did the full CONNECT treatment, go to COMPLETE */
            s->tunnel_state = TUNNEL_COMPLETE;

          DEBUGASSERT(s->keepon == KEEPON_IGNORE || s->keepon == KEEPON_DONE);
          continue;
        }

        if((checkprefix("WWW-Authenticate:", linep) &&
            (401 == k->httpcode)) ||
           (checkprefix("Proxy-authenticate:", linep) &&
            (407 == k->httpcode))) {

          bool proxy = (k->httpcode == 407) ? TRUE : FALSE;
          char *auth = Curl_copy_header_value(linep);
          if(!auth)
            return CURLE_OUT_OF_MEMORY;

          result = Curl_http_input_auth(data, proxy, auth);

          free(auth);

          if(result)
            return result;
        }
        else if(checkprefix("Content-Length:", linep)) {
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
                  "CONNECT %03d response\n", k->httpcode);
          }
          else if(Curl_compareheader(linep,
                                     "Transfer-Encoding:", "chunked")) {
            infof(data, "CONNECT responded chunked\n");
            s->chunked_encoding = TRUE;
            /* init our chunky engine */
            Curl_httpchunk_init(conn);
          }
        }
        else if(Curl_compareheader(linep, "Proxy-Connection:", "close"))
          s->close_connection = TRUE;
        else if(2 == sscanf(linep, "HTTP/1.%d %d",
                            &subversion,
                            &k->httpcode)) {
          /* store the HTTP code from the proxy */
          data->info.httpproxycode = k->httpcode;
        }

        Curl_dyn_reset(&s->rcvbuf);
      } /* while there's buffer left and loop is requested */

      if(Curl_pgrsUpdate(conn))
        return CURLE_ABORTED_BY_CALLBACK;

      if(error)
        return CURLE_RECV_ERROR;

      if(data->info.httpproxycode/100 != 2) {
        /* 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 */
          s->close_connection = TRUE;
      }

      if(s->close_connection && 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 == s->tunnel_state)) {
      connect_init(conn, TRUE); /* reinit */
    }

  } while(data->req.newurl);

  if(data->info.httpproxycode/100 != 2) {
    if(s->close_connection && data->req.newurl) {
      conn->bits.proxy_connect_closed = TRUE;
      infof(data, "Connect me again please\n");
      connect_done(conn);
    }
    else {
      free(data->req.newurl);
      data->req.newurl = NULL;
      /* failure, close this connection to avoid re-use */
      streamclose(conn, "proxy CONNECT failure");
      Curl_closesocket(conn, conn->sock[sockindex]);
      conn->sock[sockindex] = CURL_SOCKET_BAD;
    }

    /* to back to init state */
    s->tunnel_state = TUNNEL_INIT;

    if(conn->bits.proxy_connect_closed)







|














|








|












|









|








|






|







544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
                  "CONNECT %03d response\n", k->httpcode);
          }
          else if(Curl_compareheader(linep,
                                     "Transfer-Encoding:", "chunked")) {
            infof(data, "CONNECT responded chunked\n");
            s->chunked_encoding = TRUE;
            /* init our chunky engine */
            Curl_httpchunk_init(data);
          }
        }
        else if(Curl_compareheader(linep, "Proxy-Connection:", "close"))
          s->close_connection = TRUE;
        else if(2 == sscanf(linep, "HTTP/1.%d %d",
                            &subversion,
                            &k->httpcode)) {
          /* store the HTTP code from the proxy */
          data->info.httpproxycode = k->httpcode;
        }

        Curl_dyn_reset(&s->rcvbuf);
      } /* while there's buffer left and loop is requested */

      if(Curl_pgrsUpdate(data))
        return CURLE_ABORTED_BY_CALLBACK;

      if(error)
        return CURLE_RECV_ERROR;

      if(data->info.httpproxycode/100 != 2) {
        /* Deal with the possibly already received authenticate
           headers. 'newurl' is set to a new URL if we must loop. */
        result = Curl_http_auth_act(data);
        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 */
          s->close_connection = TRUE;
      }

      if(s->close_connection && data->req.newurl) {
        /* Connection closed by server. Don't use it anymore */
        Curl_closesocket(data, 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 == s->tunnel_state)) {
      connect_init(data, TRUE); /* reinit */
    }

  } while(data->req.newurl);

  if(data->info.httpproxycode/100 != 2) {
    if(s->close_connection && data->req.newurl) {
      conn->bits.proxy_connect_closed = TRUE;
      infof(data, "Connect me again please\n");
      connect_done(data);
    }
    else {
      free(data->req.newurl);
      data->req.newurl = NULL;
      /* failure, close this connection to avoid re-use */
      streamclose(conn, "proxy CONNECT failure");
      Curl_closesocket(data, conn, conn->sock[sockindex]);
      conn->sock[sockindex] = CURL_SOCKET_BAD;
    }

    /* to back to init state */
    s->tunnel_state = TUNNEL_INIT;

    if(conn->bits.proxy_connect_closed)
624
625
626
627
628
629
630



























































































































































































































631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653

654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
        data->info.httpproxycode);
  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  */
  Curl_dyn_free(&s->rcvbuf);
  return CURLE_OK;
}




























































































































































































































void Curl_connect_free(struct Curl_easy *data)
{
  struct connectdata *conn = data->conn;
  struct http_connect_state *s = conn->connect_state;
  if(s) {
    free(s);
    conn->connect_state = NULL;
  }
}

/*
 * 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.
 */

CURLcode Curl_proxyCONNECT(struct connectdata *conn,
                           int sockindex,
                           const char *hostname,
                           int remote_port)
{
  CURLcode result;

  if(!conn->connect_state) {
    result = connect_init(conn, FALSE);
    if(result)
      return result;
  }
  result = CONNECT(conn, sockindex, hostname, remote_port);

  if(result || Curl_connect_complete(conn))
    connect_done(conn);

  return result;
}

#else
void Curl_connect_free(struct Curl_easy *data)
{
  (void)data;
}

#endif /* CURL_DISABLE_PROXY */







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

















|





>

|



|


|











642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
        data->info.httpproxycode);
  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  */
  Curl_dyn_free(&s->rcvbuf);
  return CURLE_OK;
}
#else
/* The Hyper version of CONNECT */
{
  struct connectdata *conn = data->conn;
  struct hyptransfer *h = &data->hyp;
  curl_socket_t tunnelsocket = conn->sock[sockindex];
  struct http_connect_state *s = conn->connect_state;
  CURLcode result = CURLE_OUT_OF_MEMORY;
  hyper_io *io = NULL;
  hyper_request *req = NULL;
  hyper_headers *headers = NULL;
  hyper_clientconn_options *options = NULL;
  hyper_task *handshake = NULL;
  hyper_task *task = NULL; /* for the handshake */
  hyper_task *sendtask = NULL; /* for the send */
  hyper_clientconn *client = NULL;
  hyper_error *hypererr = NULL;
  char *hostheader = NULL; /* for CONNECT */
  char *host = NULL; /* Host: */

  if(Curl_connect_complete(conn))
    return CURLE_OK; /* CONNECT is already completed */

  conn->bits.proxy_connect_closed = FALSE;

  do {
    switch(s->tunnel_state) {
    case TUNNEL_INIT:
      /* BEGIN CONNECT PHASE */
      io = hyper_io_new();
      if(!io) {
        failf(data, "Couldn't create hyper IO");
        goto error;
      }
      /* tell Hyper how to read/write network data */
      hyper_io_set_userdata(io, data);
      hyper_io_set_read(io, Curl_hyper_recv);
      hyper_io_set_write(io, Curl_hyper_send);
      conn->sockfd = tunnelsocket;

      /* create an executor to poll futures */
      if(!h->exec) {
        h->exec = hyper_executor_new();
        if(!h->exec) {
          failf(data, "Couldn't create hyper executor");
          goto error;
        }
      }

      options = hyper_clientconn_options_new();
      if(!options) {
        failf(data, "Couldn't create hyper client options");
        goto error;
      }

      hyper_clientconn_options_exec(options, h->exec);

      /* "Both the `io` and the `options` are consumed in this function
         call" */
      handshake = hyper_clientconn_handshake(io, options);
      if(!handshake) {
        failf(data, "Couldn't create hyper client handshake");
        goto error;
      }
      io = NULL;
      options = NULL;

      if(HYPERE_OK != hyper_executor_push(h->exec, handshake)) {
        failf(data, "Couldn't hyper_executor_push the handshake");
        goto error;
      }
      handshake = NULL; /* ownership passed on */

      task = hyper_executor_poll(h->exec);
      if(!task) {
        failf(data, "Couldn't hyper_executor_poll the handshake");
        goto error;
      }

      client = hyper_task_value(task);
      hyper_task_free(task);
      req = hyper_request_new();
      if(!req) {
        failf(data, "Couldn't hyper_request_new");
        goto error;
      }
      if(hyper_request_set_method(req, (uint8_t *)"CONNECT",
                                  strlen("CONNECT"))) {
        failf(data, "error setting method");
        goto error;
      }

      result = CONNECT_host(data, conn, hostname, remote_port,
                            &hostheader, &host);
      if(result)
        goto error;

      if(hyper_request_set_uri(req, (uint8_t *)hostheader,
                               strlen(hostheader))) {
        failf(data, "error setting path");
        result = CURLE_OUT_OF_MEMORY;
      }
      /* Setup the proxy-authorization header, if any */
      result = Curl_http_output_auth(data, conn, "CONNECT", HTTPREQ_GET,
                                     hostheader, TRUE);
      if(result)
        goto error;
      Curl_safefree(hostheader);

      /* default is 1.1 */
      if((conn->http_proxy.proxytype == CURLPROXY_HTTP_1_0) &&
         (HYPERE_OK != hyper_request_set_version(req,
                                                 HYPER_HTTP_VERSION_1_0))) {
        failf(data, "error settting HTTP version");
        goto error;
      }

      headers = hyper_request_headers(req);
      if(!headers) {
        failf(data, "hyper_request_headers");
        goto error;
      }
      if(host && Curl_hyper_header(data, headers, host))
        goto error;
      Curl_safefree(host);

      if(data->state.aptr.proxyuserpwd &&
         Curl_hyper_header(data, headers, data->state.aptr.proxyuserpwd))
        goto error;

      if(data->set.str[STRING_USERAGENT] &&
         *data->set.str[STRING_USERAGENT] &&
         data->state.aptr.uagent &&
         Curl_hyper_header(data, headers, data->state.aptr.uagent))
        goto error;

      if(!Curl_checkProxyheaders(data, conn, "Proxy-Connection") &&
         Curl_hyper_header(data, headers, "Proxy-Connection: Keep-Alive"))
        goto error;

      sendtask = hyper_clientconn_send(client, req);
      if(!sendtask) {
        failf(data, "hyper_clientconn_send");
        goto error;
      }

      if(HYPERE_OK != hyper_executor_push(h->exec, sendtask)) {
        failf(data, "Couldn't hyper_executor_push the send");
        goto error;
      }

      hyper_clientconn_free(client);

      do {
        task = hyper_executor_poll(h->exec);
        if(task) {
          bool error = hyper_task_type(task) == HYPER_TASK_ERROR;
          if(error)
            hypererr = hyper_task_value(task);
          hyper_task_free(task);
          if(error)
            goto error;
        }
      } while(task);
      s->tunnel_state = TUNNEL_CONNECT;
      /* FALLTHROUGH */
    case TUNNEL_CONNECT: {
      int didwhat;
      bool done = FALSE;
      result = Curl_hyper_stream(data, conn, &didwhat, &done,
                                 CURL_CSELECT_IN | CURL_CSELECT_OUT);
      if(result)
        goto error;
      if(!done)
        break;
      fprintf(stderr, "done\n");
      s->tunnel_state = TUNNEL_COMPLETE;
      if(h->exec) {
        hyper_executor_free(h->exec);
        h->exec = NULL;
      }
      if(h->read_waker) {
        hyper_waker_free(h->read_waker);
        h->read_waker = NULL;
      }
      if(h->write_waker) {
        hyper_waker_free(h->write_waker);
        h->write_waker = NULL;
      }
    }
      /* FALLTHROUGH */
    default:
      break;
    }
  } while(data->req.newurl);

  result = CURLE_OK;
  error:
  free(host);
  free(hostheader);
  if(io)
    hyper_io_free(io);

  if(options)
    hyper_clientconn_options_free(options);

  if(handshake)
    hyper_task_free(handshake);

  if(hypererr) {
    uint8_t errbuf[256];
    size_t errlen = hyper_error_print(hypererr, errbuf, sizeof(errbuf));
    failf(data, "Hyper: %.*s", (int)errlen, errbuf);
    hyper_error_free(hypererr);
  }
  return result;
}

#endif

void Curl_connect_free(struct Curl_easy *data)
{
  struct connectdata *conn = data->conn;
  struct http_connect_state *s = conn->connect_state;
  if(s) {
    free(s);
    conn->connect_state = NULL;
  }
}

/*
 * 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.
 */

CURLcode Curl_proxyCONNECT(struct Curl_easy *data,
                           int sockindex,
                           const char *hostname,
                           int remote_port)
{
  CURLcode result;
  struct connectdata *conn = data->conn;
  if(!conn->connect_state) {
    result = connect_init(data, FALSE);
    if(result)
      return result;
  }
  result = CONNECT(data, sockindex, hostname, remote_port);

  if(result || Curl_connect_complete(conn))
    connect_done(data);

  return result;
}

#else
void Curl_connect_free(struct Curl_easy *data)
{
  (void)data;
}

#endif /* CURL_DISABLE_PROXY */
Changes to jni/curl/lib/http_proxy.h.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
#ifndef HEADER_CURL_HTTP_PROXY_H
#define HEADER_CURL_HTTP_PROXY_H
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2020, 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 https://curl.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"

#if !defined(CURL_DISABLE_PROXY) && !defined(CURL_DISABLE_HTTP)
/* ftp can use this as well */
CURLcode Curl_proxyCONNECT(struct connectdata *conn,
                           int tunnelsocket,
                           const char *hostname, int remote_port);

/* Default proxy timeout in milliseconds */
#define PROXY_TIMEOUT (3600*1000)

CURLcode Curl_proxy_connect(struct connectdata *conn, int sockindex);

bool Curl_connect_complete(struct connectdata *conn);
bool Curl_connect_ongoing(struct connectdata *conn);

#else
#define Curl_proxyCONNECT(x,y,z,w) CURLE_NOT_BUILT_IN
#define Curl_proxy_connect(x,y) CURLE_OK









|



















|






|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
#ifndef HEADER_CURL_HTTP_PROXY_H
#define HEADER_CURL_HTTP_PROXY_H
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2021, 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 https://curl.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"

#if !defined(CURL_DISABLE_PROXY) && !defined(CURL_DISABLE_HTTP)
/* ftp can use this as well */
CURLcode Curl_proxyCONNECT(struct Curl_easy *data,
                           int tunnelsocket,
                           const char *hostname, int remote_port);

/* Default proxy timeout in milliseconds */
#define PROXY_TIMEOUT (3600*1000)

CURLcode Curl_proxy_connect(struct Curl_easy *data, int sockindex);

bool Curl_connect_complete(struct connectdata *conn);
bool Curl_connect_ongoing(struct connectdata *conn);

#else
#define Curl_proxyCONNECT(x,y,z,w) CURLE_NOT_BUILT_IN
#define Curl_proxy_connect(x,y) CURLE_OK
Changes to jni/curl/lib/imap.c.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2020, 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 https://curl.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







|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2021, 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 https://curl.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
84
85
86
87
88
89
90
91
92
93
94
95
96

97

98
99
100

101
102

103
104
105
106

107
108
109

110
111
112
113
114
115
116

/* The last 3 #include files should be in this order */
#include "curl_printf.h"
#include "curl_memory.h"
#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);
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, bool escape_only);
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.
 */








|
|
|

|
|
>
|
>
|
|
|
>

|
>

|
|
|
>


|
>







84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122

/* The last 3 #include files should be in this order */
#include "curl_printf.h"
#include "curl_memory.h"
#include "memdebug.h"

/* Local API functions */
static CURLcode imap_regular_transfer(struct Curl_easy *data, bool *done);
static CURLcode imap_do(struct Curl_easy *data, bool *done);
static CURLcode imap_done(struct Curl_easy *data, CURLcode status,
                          bool premature);
static CURLcode imap_connect(struct Curl_easy *data, bool *done);
static CURLcode imap_disconnect(struct Curl_easy *data,
                                struct connectdata *conn, bool dead);
static CURLcode imap_multi_statemach(struct Curl_easy *data, bool *done);
static int imap_getsock(struct Curl_easy *data, struct connectdata *conn,
                        curl_socket_t *socks);
static CURLcode imap_doing(struct Curl_easy *data, bool *dophase_done);
static CURLcode imap_setup_connection(struct Curl_easy *data,
                                      struct connectdata *conn);
static char *imap_atom(const char *str, bool escape_only);
static CURLcode imap_sendf(struct Curl_easy *data,
                           struct connectdata *conn, const char *fmt, ...);
static CURLcode imap_parse_url_options(struct connectdata *conn);
static CURLcode imap_parse_url_path(struct Curl_easy *data);
static CURLcode imap_parse_custom_request(struct Curl_easy *data);
static CURLcode imap_perform_authenticate(struct Curl_easy *data,
                                          struct connectdata *conn,
                                          const char *mech,
                                          const char *initresp);
static CURLcode imap_continue_authenticate(struct Curl_easy *data,
                                           struct connectdata *conn,
                                           const char *resp);
static void imap_get_message(char *buffer, char **outptr);

/*
 * IMAP protocol handler.
 */

239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
/***********************************************************************
 *
 * 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.p.imap;
  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;







|
|

|







245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
/***********************************************************************
 *
 * 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 Curl_easy *data, struct connectdata *conn,
                           char *line, size_t len, int *resp)
{
  struct IMAP *imap = data->req.p.imap;
  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;
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
      /* 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;
  }








|







330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
      /* States which are interested in continuation responses */
      case IMAP_AUTHENTICATE:
      case IMAP_APPEND:
        *resp = '+';
        break;

      default:
        failf(data, "Unexpected continuation response");
        *resp = -1;
        break;
    }

    return TRUE;
  }

377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393

/***********************************************************************
 *
 * 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",







|

|







383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399

/***********************************************************************
 *
 * state()
 *
 * This is the ONLY way to change IMAP state!
 */
static void state(struct Curl_easy *data, imapstate newstate)
{
  struct imap_conn *imapc = &data->conn->proto.imapc;
#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
  /* for debug purposes */
  static const char * const names[]={
    "STOP",
    "SERVERGREET",
    "CAPABILITY",
    "STARTTLS",
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423

424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446

447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463

464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489

490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527

528
529
530
531

532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551

552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567

568
569
570
571
572
573
574
575
576
577
578
579
580
581
582

583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681

682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781

782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799

800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825

826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
    "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)

{
  /* Send the STARTTLS command */
  CURLcode 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)

{
  /* Start the SSL connection */
  struct imap_conn *imapc = &conn->proto.imapc;
  CURLcode 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, false);
  passwd = imap_atom(conn->passwd, false);

  /* 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 if already authenticated OR if there is enough data to authenticate
     with and end the connect phase if we don't */
  if(imapc->preauth ||
     !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 Curl_easy *data = conn->data;
  struct IMAP *imap = data->req.p.imap;

  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 if necessary */
    char *mailbox = imap->mailbox ? imap_atom(imap->mailbox, true)
                                  : strdup("");
    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 Curl_easy *data = conn->data;
  struct IMAP *imap = data->req.p.imap;
  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, false);
  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.p.imap;
  /* Check we have a UID */
  if(imap->uid) {

    /* Send the FETCH command */
    if(imap->partial)
      result = imap_sendf(conn, "UID FETCH %s BODY[%s]<%s>",
                            imap->uid,
                            imap->section ? imap->section : "",
                            imap->partial);
    else
      result = imap_sendf(conn, "UID FETCH %s BODY[%s]",
                            imap->uid,
                            imap->section ? imap->section : "");
  }
  else if(imap->mindex) {

    /* Send the FETCH command */
    if(imap->partial)
      result = imap_sendf(conn, "FETCH %s BODY[%s]<%s>",
                            imap->mindex,
                            imap->section ? imap->section : "",
                            imap->partial);
    else
      result = imap_sendf(conn, "FETCH %s BODY[%s]",
                            imap->mindex,
                            imap->section ? imap->section : "");
  }
  else {
        failf(conn->data, "Cannot FETCH without a UID.");
        return CURLE_URL_MALFORMAT;
  }
  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 Curl_easy *data = conn->data;
  struct IMAP *imap = data->req.p.imap;
  char *mailbox;

  /* Check we have a mailbox */
  if(!imap->mailbox) {
    failf(data, "Cannot APPEND without a mailbox.");
    return CURLE_URL_MALFORMAT;
  }

  /* Prepare the mime data if some. */
  if(data->set.mimepost.kind != MIMEKIND_NONE) {
    /* Use the whole structure as data. */
    data->set.mimepost.flags &= ~MIME_BODY_ONLY;

    /* Add external headers and mime version. */
    curl_mime_headers(&data->set.mimepost, data->set.headers, 0);
    result = Curl_mime_prepare_headers(&data->set.mimepost, NULL,
                                       NULL, MIMESTRATEGY_MAIL);

    if(!result)
      if(!Curl_checkheaders(conn, "Mime-Version"))
        result = Curl_mime_add_header(&data->set.mimepost.curlheaders,
                                      "Mime-Version: 1.0");

    /* Make sure we will read the entire mime structure. */
    if(!result)
      result = Curl_mime_rewind(&data->set.mimepost);

    if(result)
      return result;

    data->state.infilesize = Curl_mime_size(&data->set.mimepost);

    /* Read from mime structure. */
    data->state.fread_func = (curl_read_callback) Curl_mime_read;
    data->state.in = (void *) &data->set.mimepost;
  }

  /* Check we know the size of the upload */
  if(data->state.infilesize < 0) {
    failf(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, false);
  if(!mailbox)
    return CURLE_OUT_OF_MEMORY;

  /* Send the APPEND command */

  result = imap_sendf(conn, "APPEND %s (\\Seen) {%" CURL_FORMAT_CURL_OFF_T "}",
                      mailbox, 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.p.imap;

  /* 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)

{
  /* Send the LOGOUT command */
  CURLcode 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)
{
  struct Curl_easy *data = conn->data;
  (void)instate; /* no use for this yet */

  if(imapcode == IMAP_RESP_PREAUTH) {
    /* PREAUTH */
    struct imap_conn *imapc = &conn->proto.imapc;
    imapc->preauth = TRUE;
    infof(data, "PREAUTH connection, already authenticated!\n");
  }
  else if(imapcode != IMAP_RESP_OK) {
    failf(data, "Got unexpected imap-server response");
    return CURLE_WEIRD_SERVER_REPLY;
  }

  return imap_perform_capability(conn);
}

/* For CAPABILITY responses */
static CURLcode imap_state_capability_resp(struct connectdata *conn,
                                           int imapcode,
                                           imapstate instate)
{
  CURLcode result = CURLE_OK;
  struct Curl_easy *data = conn->data;
  struct imap_conn *imapc = &conn->proto.imapc;
  const char *line = data->state.buffer;

  (void)instate; /* no use for this yet */

  /* Do we have a untagged response? */
  if(imapcode == '*') {







|













|
>








|


|










|
>


|


|










|
>



|




|



|












|
>








|









|






|











|
>




>



|



|











|
>




|










|
>









|




|
>



|


|


|













|


|




|









|





|










|


|










|









|




|










|
>


|





|
<
|
|

|
<
|


<


|
<
|
|

|
<
|


|
|


|










|


|




















|



















|









>
|





|










|
>


|



|




|


|










|
>


|


|





|



|













|



|




|







408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706

707
708
709
710

711
712
713

714
715
716

717
718
719
720

721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
    "APPEND_FINAL",
    "SEARCH",
    "LOGOUT",
    /* LAST */
  };

  if(imapc->state != newstate)
    infof(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 Curl_easy *data,
                                        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(data, conn, "CAPABILITY");

  if(!result)
    state(data, IMAP_CAPABILITY);

  return result;
}

/***********************************************************************
 *
 * imap_perform_starttls()
 *
 * Sends the STARTTLS command to start the upgrade to TLS.
 */
static CURLcode imap_perform_starttls(struct Curl_easy *data,
                                      struct connectdata *conn)
{
  /* Send the STARTTLS command */
  CURLcode result = imap_sendf(data, conn, "STARTTLS");

  if(!result)
    state(data, IMAP_STARTTLS);

  return result;
}

/***********************************************************************
 *
 * imap_perform_upgrade_tls()
 *
 * Performs the upgrade to TLS.
 */
static CURLcode imap_perform_upgrade_tls(struct Curl_easy *data,
                                         struct connectdata *conn)
{
  /* Start the SSL connection */
  struct imap_conn *imapc = &conn->proto.imapc;
  CURLcode result = Curl_ssl_connect_nonblocking(data, conn, FIRSTSOCKET,
                                                 &imapc->ssldone);

  if(!result) {
    if(imapc->state != IMAP_UPGRADETLS)
      state(data, IMAP_UPGRADETLS);

    if(imapc->ssldone) {
      imap_to_imaps(conn);
      result = imap_perform_capability(data, conn);
    }
  }

  return result;
}

/***********************************************************************
 *
 * imap_perform_login()
 *
 * Sends a clear text LOGIN command to authenticate with.
 */
static CURLcode imap_perform_login(struct Curl_easy *data,
                                   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(data, IMAP_STOP);

    return result;
  }

  /* Make sure the username and password are in the correct atom format */
  user = imap_atom(conn->user, false);
  passwd = imap_atom(conn->passwd, false);

  /* Send the LOGIN command */
  result = imap_sendf(data, conn, "LOGIN %s %s", user ? user : "",
                      passwd ? passwd : "");

  free(user);
  free(passwd);

  if(!result)
    state(data, 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 Curl_easy *data,
                                          struct connectdata *conn,
                                          const char *mech,
                                          const char *initresp)
{
  CURLcode result = CURLE_OK;
  (void)data;

  if(initresp) {
    /* Send the AUTHENTICATE command with the initial response */
    result = imap_sendf(data, conn, "AUTHENTICATE %s %s", mech, initresp);
  }
  else {
    /* Send the AUTHENTICATE command */
    result = imap_sendf(data, conn, "AUTHENTICATE %s", mech);
  }

  return result;
}

/***********************************************************************
 *
 * imap_continue_authenticate()
 *
 * Sends SASL continuation data or cancellation.
 */
static CURLcode imap_continue_authenticate(struct Curl_easy *data,
                                           struct connectdata *conn,
                                           const char *resp)
{
  struct imap_conn *imapc = &conn->proto.imapc;

  return Curl_pp_sendf(data, &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 Curl_easy *data,
                                            struct connectdata *conn)
{
  CURLcode result = CURLE_OK;
  struct imap_conn *imapc = &conn->proto.imapc;
  saslprogress progress;

  /* Check if already authenticated OR if there is enough data to authenticate
     with and end the connect phase if we don't */
  if(imapc->preauth ||
     !Curl_sasl_can_authenticate(&imapc->sasl, conn)) {
    state(data, IMAP_STOP);
    return result;
  }

  /* Calculate the SASL login details */
  result = Curl_sasl_start(&imapc->sasl, data, conn,
                           imapc->ir_supported, &progress);

  if(!result) {
    if(progress == SASL_INPROGRESS)
      state(data, IMAP_AUTHENTICATE);
    else if(!imapc->login_disabled && (imapc->preftype & IMAP_TYPE_CLEARTEXT))
      /* Perform clear text authentication */
      result = imap_perform_login(data, conn);
    else {
      /* Other mechanisms not supported */
      infof(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 Curl_easy *data)
{
  CURLcode result = CURLE_OK;
  struct connectdata *conn = data->conn;
  struct IMAP *imap = data->req.p.imap;

  if(imap->custom)
    /* Send the custom request */
    result = imap_sendf(data, conn, "%s%s", imap->custom,
                        imap->custom_params ? imap->custom_params : "");
  else {
    /* Make sure the mailbox is in the correct atom format if necessary */
    char *mailbox = imap->mailbox ? imap_atom(imap->mailbox, true)
                                  : strdup("");
    if(!mailbox)
      return CURLE_OUT_OF_MEMORY;

    /* Send the LIST command */
    result = imap_sendf(data, conn, "LIST \"%s\" *", mailbox);

    free(mailbox);
  }

  if(!result)
    state(data, 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 Curl_easy *data)
{
  CURLcode result = CURLE_OK;
  struct connectdata *conn = data->conn;
  struct IMAP *imap = data->req.p.imap;
  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(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, false);
  if(!mailbox)
    return CURLE_OUT_OF_MEMORY;

  /* Send the SELECT command */
  result = imap_sendf(data, conn, "SELECT %s", mailbox);

  free(mailbox);

  if(!result)
    state(data, IMAP_SELECT);

  return result;
}

/***********************************************************************
 *
 * imap_perform_fetch()
 *
 * Sends a FETCH command to initiate the download of a message.
 */
static CURLcode imap_perform_fetch(struct Curl_easy *data,
                                   struct connectdata *conn)
{
  CURLcode result = CURLE_OK;
  struct IMAP *imap = data->req.p.imap;
  /* Check we have a UID */
  if(imap->uid) {

    /* Send the FETCH command */
    if(imap->partial)
      result = imap_sendf(data, conn, "UID FETCH %s BODY[%s]<%s>",

                          imap->uid, imap->section ? imap->section : "",
                          imap->partial);
    else
      result = imap_sendf(data, conn, "UID FETCH %s BODY[%s]",

                          imap->uid, imap->section ? imap->section : "");
  }
  else if(imap->mindex) {

    /* Send the FETCH command */
    if(imap->partial)
      result = imap_sendf(data, conn, "FETCH %s BODY[%s]<%s>",

                          imap->mindex, imap->section ? imap->section : "",
                          imap->partial);
    else
      result = imap_sendf(data, conn, "FETCH %s BODY[%s]",

                          imap->mindex, imap->section ? imap->section : "");
  }
  else {
    failf(data, "Cannot FETCH without a UID.");
    return CURLE_URL_MALFORMAT;
  }
  if(!result)
    state(data, IMAP_FETCH);

  return result;
}

/***********************************************************************
 *
 * imap_perform_append()
 *
 * Sends an APPEND command to initiate the upload of a message.
 */
static CURLcode imap_perform_append(struct Curl_easy *data)
{
  CURLcode result = CURLE_OK;
  struct connectdata *conn = data->conn;
  struct IMAP *imap = data->req.p.imap;
  char *mailbox;

  /* Check we have a mailbox */
  if(!imap->mailbox) {
    failf(data, "Cannot APPEND without a mailbox.");
    return CURLE_URL_MALFORMAT;
  }

  /* Prepare the mime data if some. */
  if(data->set.mimepost.kind != MIMEKIND_NONE) {
    /* Use the whole structure as data. */
    data->set.mimepost.flags &= ~MIME_BODY_ONLY;

    /* Add external headers and mime version. */
    curl_mime_headers(&data->set.mimepost, data->set.headers, 0);
    result = Curl_mime_prepare_headers(&data->set.mimepost, NULL,
                                       NULL, MIMESTRATEGY_MAIL);

    if(!result)
      if(!Curl_checkheaders(data, "Mime-Version"))
        result = Curl_mime_add_header(&data->set.mimepost.curlheaders,
                                      "Mime-Version: 1.0");

    /* Make sure we will read the entire mime structure. */
    if(!result)
      result = Curl_mime_rewind(&data->set.mimepost);

    if(result)
      return result;

    data->state.infilesize = Curl_mime_size(&data->set.mimepost);

    /* Read from mime structure. */
    data->state.fread_func = (curl_read_callback) Curl_mime_read;
    data->state.in = (void *) &data->set.mimepost;
  }

  /* Check we know the size of the upload */
  if(data->state.infilesize < 0) {
    failf(data, "Cannot APPEND with unknown input file size");
    return CURLE_UPLOAD_FAILED;
  }

  /* Make sure the mailbox is in the correct atom format */
  mailbox = imap_atom(imap->mailbox, false);
  if(!mailbox)
    return CURLE_OUT_OF_MEMORY;

  /* Send the APPEND command */
  result = imap_sendf(data, conn,
                      "APPEND %s (\\Seen) {%" CURL_FORMAT_CURL_OFF_T "}",
                      mailbox, data->state.infilesize);

  free(mailbox);

  if(!result)
    state(data, IMAP_APPEND);

  return result;
}

/***********************************************************************
 *
 * imap_perform_search()
 *
 * Sends a SEARCH command.
 */
static CURLcode imap_perform_search(struct Curl_easy *data,
                                    struct connectdata *conn)
{
  CURLcode result = CURLE_OK;
  struct IMAP *imap = data->req.p.imap;

  /* Check we have a query string */
  if(!imap->query) {
    failf(data, "Cannot SEARCH without a query string.");
    return CURLE_URL_MALFORMAT;
  }

  /* Send the SEARCH command */
  result = imap_sendf(data, conn, "SEARCH %s", imap->query);

  if(!result)
    state(data, IMAP_SEARCH);

  return result;
}

/***********************************************************************
 *
 * imap_perform_logout()
 *
 * Performs the logout action prior to sclose() being called.
 */
static CURLcode imap_perform_logout(struct Curl_easy *data,
                                    struct connectdata *conn)
{
  /* Send the LOGOUT command */
  CURLcode result = imap_sendf(data, conn, "LOGOUT");

  if(!result)
    state(data, IMAP_LOGOUT);

  return result;
}

/* For the initial server greeting */
static CURLcode imap_state_servergreet_resp(struct Curl_easy *data,
                                            int imapcode,
                                            imapstate instate)
{
  struct connectdata *conn = data->conn;
  (void)instate; /* no use for this yet */

  if(imapcode == IMAP_RESP_PREAUTH) {
    /* PREAUTH */
    struct imap_conn *imapc = &conn->proto.imapc;
    imapc->preauth = TRUE;
    infof(data, "PREAUTH connection, already authenticated!\n");
  }
  else if(imapcode != IMAP_RESP_OK) {
    failf(data, "Got unexpected imap-server response");
    return CURLE_WEIRD_SERVER_REPLY;
  }

  return imap_perform_capability(data, conn);
}

/* For CAPABILITY responses */
static CURLcode imap_state_capability_resp(struct Curl_easy *data,
                                           int imapcode,
                                           imapstate instate)
{
  CURLcode result = CURLE_OK;
  struct connectdata *conn = data->conn;
  struct imap_conn *imapc = &conn->proto.imapc;
  const char *line = data->state.buffer;

  (void)instate; /* no use for this yet */

  /* Do we have a untagged response? */
  if(imapcode == '*') {
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970

971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098

1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
    }
  }
  else if(imapcode == IMAP_RESP_OK) {
    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 Curl_easy *data = conn->data;

  (void)instate; /* no use for this yet */

  if(imapcode != IMAP_RESP_OK) {
    if(data->set.use_ssl != CURLUSESSL_TRY) {
      failf(data, "STARTTLS denied");
      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 Curl_easy *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 Curl_easy *data = conn->data;

  (void)instate; /* no use for this yet */

  if(imapcode != IMAP_RESP_OK) {
    failf(data, "Access denied. %c", imapcode);
    result = CURLE_LOGIN_DENIED;
  }
  else
    /* End of connect phase */
    state(conn, IMAP_STOP);

  return result;
}

/* For LIST and SEARCH responses */
static CURLcode imap_state_listsearch_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 != IMAP_RESP_OK)
    result = CURLE_QUOTE_ERROR;
  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 Curl_easy *data = conn->data;
  struct IMAP *imap = conn->data->req.p.imap;
  struct imap_conn *imapc = &conn->proto.imapc;
  const char *line = data->state.buffer;

  (void)instate; /* no use for this yet */

  if(imapcode == '*') {
    /* See if this is an UIDVALIDITY response */
    char tmp[20];
    if(sscanf(line + 2, "OK [UIDVALIDITY %19[0123456789]]", tmp) == 1) {
      Curl_safefree(imapc->mailbox_uidvalidity);
      imapc->mailbox_uidvalidity = strdup(tmp);
    }
  }
  else if(imapcode == IMAP_RESP_OK) {
    /* Check if the UIDVALIDITY has been specified and matches */
    if(imap->uidvalidity && imapc->mailbox_uidvalidity &&
       !strcasecompare(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 Curl_easy *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 = 0;

  (void)instate; /* no use for this yet */

  if(imapcode != '*') {
    Curl_pgrsSetDownloadSize(data, -1);
    state(conn, IMAP_STOP);
    return CURLE_REMOTE_FILE_NOT_FOUND;
  }

  /* 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++;







|


|






|


|





|




|









|


|





|
>




<





|



|




|













|




<
<








|





|




|







|






|





|



|
|

















|







|

|

|











|
>



<










|







934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989

990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022


1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114

1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
    }
  }
  else if(imapcode == IMAP_RESP_OK) {
    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(data, conn);
      else if(data->set.use_ssl == CURLUSESSL_TRY)
        /* Fallback and carry on with authentication */
        result = imap_perform_authentication(data, conn);
      else {
        failf(data, "STARTTLS not supported.");
        result = CURLE_USE_SSL_FAILED;
      }
    }
    else
      result = imap_perform_authentication(data, conn);
  }
  else
    result = imap_perform_authentication(data, conn);

  return result;
}

/* For STARTTLS responses */
static CURLcode imap_state_starttls_resp(struct Curl_easy *data,
                                         int imapcode,
                                         imapstate instate)
{
  CURLcode result = CURLE_OK;
  struct connectdata *conn = data->conn;

  (void)instate; /* no use for this yet */

  if(imapcode != IMAP_RESP_OK) {
    if(data->set.use_ssl != CURLUSESSL_TRY) {
      failf(data, "STARTTLS denied");
      result = CURLE_USE_SSL_FAILED;
    }
    else
      result = imap_perform_authentication(data, conn);
  }
  else
    result = imap_perform_upgrade_tls(data, conn);

  return result;
}

/* For SASL authentication responses */
static CURLcode imap_state_auth_resp(struct Curl_easy *data,
                                     struct connectdata *conn,
                                     int imapcode,
                                     imapstate instate)
{
  CURLcode result = CURLE_OK;

  struct imap_conn *imapc = &conn->proto.imapc;
  saslprogress progress;

  (void)instate; /* no use for this yet */

  result = Curl_sasl_continue(&imapc->sasl, data, conn, imapcode, &progress);
  if(!result)
    switch(progress) {
    case SASL_DONE:
      state(data, 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(data, 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 Curl_easy *data,
                                      int imapcode,
                                      imapstate instate)
{
  CURLcode result = CURLE_OK;


  (void)instate; /* no use for this yet */

  if(imapcode != IMAP_RESP_OK) {
    failf(data, "Access denied. %c", imapcode);
    result = CURLE_LOGIN_DENIED;
  }
  else
    /* End of connect phase */
    state(data, IMAP_STOP);

  return result;
}

/* For LIST and SEARCH responses */
static CURLcode imap_state_listsearch_resp(struct Curl_easy *data,
                                           int imapcode,
                                           imapstate instate)
{
  CURLcode result = CURLE_OK;
  char *line = 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(data, CLIENTWRITE_BODY, line, len + 1);
    line[len] = '\0';
  }
  else if(imapcode != IMAP_RESP_OK)
    result = CURLE_QUOTE_ERROR;
  else
    /* End of DO phase */
    state(data, IMAP_STOP);

  return result;
}

/* For SELECT responses */
static CURLcode imap_state_select_resp(struct Curl_easy *data, int imapcode,
                                       imapstate instate)
{
  CURLcode result = CURLE_OK;
  struct connectdata *conn = data->conn;
  struct IMAP *imap = data->req.p.imap;
  struct imap_conn *imapc = &conn->proto.imapc;
  const char *line = data->state.buffer;

  (void)instate; /* no use for this yet */

  if(imapcode == '*') {
    /* See if this is an UIDVALIDITY response */
    char tmp[20];
    if(sscanf(line + 2, "OK [UIDVALIDITY %19[0123456789]]", tmp) == 1) {
      Curl_safefree(imapc->mailbox_uidvalidity);
      imapc->mailbox_uidvalidity = strdup(tmp);
    }
  }
  else if(imapcode == IMAP_RESP_OK) {
    /* Check if the UIDVALIDITY has been specified and matches */
    if(imap->uidvalidity && imapc->mailbox_uidvalidity &&
       !strcasecompare(imap->uidvalidity, imapc->mailbox_uidvalidity)) {
      failf(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(data);
      else if(imap->query)
        result = imap_perform_search(data, conn);
      else
        result = imap_perform_fetch(data, 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 Curl_easy *data,
                                      struct connectdata *conn, int imapcode,
                                      imapstate instate)
{
  CURLcode result = CURLE_OK;

  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 = 0;

  (void)instate; /* no use for this yet */

  if(imapcode != '*') {
    Curl_pgrsSetDownloadSize(data, -1);
    state(data, IMAP_STOP);
    return CURLE_REMOTE_FILE_NOT_FOUND;
  }

  /* 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++;
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158

      if(chunk > (size_t)size)
        /* The conversion from curl_off_t to size_t is always fine here */
        chunk = (size_t)size;

      if(!chunk) {
        /* no size, we're done with the data */
        state(conn, IMAP_STOP);
        return CURLE_OK;
      }
      result = Curl_client_write(conn, CLIENTWRITE_BODY, pp->cache, chunk);
      if(result)
        return result;

      data->req.bytecount += chunk;

      infof(data, "Written %zu bytes, %" CURL_FORMAT_CURL_OFF_TU
            " bytes are left for transfer\n", chunk, size - chunk);







|


|







1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170

      if(chunk > (size_t)size)
        /* The conversion from curl_off_t to size_t is always fine here */
        chunk = (size_t)size;

      if(!chunk) {
        /* no size, we're done with the data */
        state(data, IMAP_STOP);
        return CURLE_OK;
      }
      result = Curl_client_write(data, CLIENTWRITE_BODY, pp->cache, chunk);
      if(result)
        return result;

      data->req.bytecount += chunk;

      infof(data, "Written %zu bytes, %" CURL_FORMAT_CURL_OFF_TU
            " bytes are left for transfer\n", chunk, size - chunk);
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261

1262
1263
1264
1265
1266
1267
1268

1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353

1354
1355
1356
1357

1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368

1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396


1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413

1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
       read off the socket already */
      data->conn->cselect_bits = CURL_CSELECT_IN;
      Curl_setup_transfer(data, FIRSTSOCKET, size, FALSE, -1);
    }
  }
  else {
    /* We don't know how to parse this line */
    failf(pp->conn->data, "Failed to parse FETCH response.");
    result = CURLE_WEIRD_SERVER_REPLY;
  }

  /* 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 != IMAP_RESP_OK)
    result = CURLE_WEIRD_SERVER_REPLY;
  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 Curl_easy *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(data, -1, -1, FALSE, FIRSTSOCKET);

    /* 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 != IMAP_RESP_OK)
    result = CURLE_UPLOAD_FAILED;
  else
    /* End of DONE 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_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:
    case IMAP_SEARCH:
      result = imap_state_listsearch_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_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, FALSE);
  *done = (imapc->state == IMAP_STOP) ? TRUE : FALSE;

  return result;
}

static CURLcode imap_block_statemach(struct connectdata *conn,

                                     bool disconnecting)
{
  CURLcode result = CURLE_OK;
  struct imap_conn *imapc = &conn->proto.imapc;

  while(imapc->state != IMAP_STOP && !result)
    result = Curl_pp_statemach(&imapc->pp, TRUE, disconnecting);

  return result;
}

/* Allocate and initialize the struct IMAP for the current Curl_easy if
   required */
static CURLcode imap_init(struct connectdata *conn)
{
  CURLcode result = CURLE_OK;
  struct Curl_easy *data = conn->data;
  struct IMAP *imap;

  imap = data->req.p.imap = 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)


{
  return Curl_pp_getsock(&conn->proto.imapc.pp, socks);
}

/***********************************************************************
 *
 * 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);

  Curl_dyn_init(&imapc->dyn, DYN_IMAP_CMD);
  /* Initialise the pingpong layer */
  Curl_pp_setup(pp);
  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 Curl_easy *data = conn->data;
  struct IMAP *imap = data->req.p.imap;

  (void)premature;

  if(!imap)
    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 || imap->mindex || data->set.upload ||
          data->set.mimepost.kind != MIMEKIND_NONE)) {
    /* Handle responses after FETCH or APPEND transfer has finished */

    if(!data->set.upload && data->set.mimepost.kind == MIMEKIND_NONE)
      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 */
    if(!result)
      result = imap_block_statemach(conn, FALSE);
  }

  /* Cleanup our per-request based variables */
  Curl_safefree(imap->mailbox);
  Curl_safefree(imap->uidvalidity);
  Curl_safefree(imap->uid);
  Curl_safefree(imap->mindex);







|




|





|











|





|



<
<













|






|











|




|
>







>



|



|



|













|



|



|



|



|




|



|



|



|



|



|






|








|


>



|
>




|





|
>






|






|


<










|
>
>

|












|


>








<
<
|
<
<








|







|




|













|



|

















|


|

|




|







1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233


1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399

1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438


1439


1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
       read off the socket already */
      data->conn->cselect_bits = CURL_CSELECT_IN;
      Curl_setup_transfer(data, FIRSTSOCKET, size, FALSE, -1);
    }
  }
  else {
    /* We don't know how to parse this line */
    failf(data, "Failed to parse FETCH response.");
    result = CURLE_WEIRD_SERVER_REPLY;
  }

  /* End of DO phase */
  state(data, IMAP_STOP);

  return result;
}

/* For final FETCH responses performed after the download */
static CURLcode imap_state_fetch_final_resp(struct Curl_easy *data,
                                            int imapcode,
                                            imapstate instate)
{
  CURLcode result = CURLE_OK;

  (void)instate; /* No use for this yet */

  if(imapcode != IMAP_RESP_OK)
    result = CURLE_WEIRD_SERVER_REPLY;
  else
    /* End of DONE phase */
    state(data, IMAP_STOP);

  return result;
}

/* For APPEND responses */
static CURLcode imap_state_append_resp(struct Curl_easy *data, int imapcode,
                                       imapstate instate)
{
  CURLcode result = CURLE_OK;


  (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(data, -1, -1, FALSE, FIRSTSOCKET);

    /* End of DO phase */
    state(data, IMAP_STOP);
  }

  return result;
}

/* For final APPEND responses performed after the upload */
static CURLcode imap_state_append_final_resp(struct Curl_easy *data,
                                             int imapcode,
                                             imapstate instate)
{
  CURLcode result = CURLE_OK;

  (void)instate; /* No use for this yet */

  if(imapcode != IMAP_RESP_OK)
    result = CURLE_UPLOAD_FAILED;
  else
    /* End of DONE phase */
    state(data, IMAP_STOP);

  return result;
}

static CURLcode imap_statemachine(struct Curl_easy *data,
                                  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;
  (void)data;

  /* Busy upgrading the connection; right now all I/O is SSL/TLS, not IMAP */
  if(imapc->state == IMAP_UPGRADETLS)
    return imap_perform_upgrade_tls(data, conn);

  /* Flush any data that needs to be sent */
  if(pp->sendleft)
    return Curl_pp_flushsend(data, pp);

  do {
    /* Read the response from the server */
    result = Curl_pp_readresp(data, sock, pp, &imapcode, &nread);
    if(result)
      return result;

    /* Was there an error parsing the response line? */
    if(imapcode == -1)
      return CURLE_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(data, imapcode, imapc->state);
      break;

    case IMAP_CAPABILITY:
      result = imap_state_capability_resp(data, imapcode, imapc->state);
      break;

    case IMAP_STARTTLS:
      result = imap_state_starttls_resp(data, imapcode, imapc->state);
      break;

    case IMAP_AUTHENTICATE:
      result = imap_state_auth_resp(data, conn, imapcode, imapc->state);
      break;

    case IMAP_LOGIN:
      result = imap_state_login_resp(data, imapcode, imapc->state);
      break;

    case IMAP_LIST:
    case IMAP_SEARCH:
      result = imap_state_listsearch_resp(data, imapcode, imapc->state);
      break;

    case IMAP_SELECT:
      result = imap_state_select_resp(data, imapcode, imapc->state);
      break;

    case IMAP_FETCH:
      result = imap_state_fetch_resp(data, conn, imapcode, imapc->state);
      break;

    case IMAP_FETCH_FINAL:
      result = imap_state_fetch_final_resp(data, imapcode, imapc->state);
      break;

    case IMAP_APPEND:
      result = imap_state_append_resp(data, imapcode, imapc->state);
      break;

    case IMAP_APPEND_FINAL:
      result = imap_state_append_final_resp(data, imapcode, imapc->state);
      break;

    case IMAP_LOGOUT:
      /* fallthrough, just stop! */
    default:
      /* internal error */
      state(data, 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 Curl_easy *data, bool *done)
{
  CURLcode result = CURLE_OK;
  struct connectdata *conn = data->conn;
  struct imap_conn *imapc = &conn->proto.imapc;

  if((conn->handler->flags & PROTOPT_SSL) && !imapc->ssldone) {
    result = Curl_ssl_connect_nonblocking(data, conn,
                                          FIRSTSOCKET, &imapc->ssldone);
    if(result || !imapc->ssldone)
      return result;
  }

  result = Curl_pp_statemach(data, &imapc->pp, FALSE, FALSE);
  *done = (imapc->state == IMAP_STOP) ? TRUE : FALSE;

  return result;
}

static CURLcode imap_block_statemach(struct Curl_easy *data,
                                     struct connectdata *conn,
                                     bool disconnecting)
{
  CURLcode result = CURLE_OK;
  struct imap_conn *imapc = &conn->proto.imapc;

  while(imapc->state != IMAP_STOP && !result)
    result = Curl_pp_statemach(data, &imapc->pp, TRUE, disconnecting);

  return result;
}

/* Allocate and initialize the struct IMAP for the current Curl_easy if
   required */
static CURLcode imap_init(struct Curl_easy *data)
{
  CURLcode result = CURLE_OK;

  struct IMAP *imap;

  imap = data->req.p.imap = 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 Curl_easy *data,
                        struct connectdata *conn,
                        curl_socket_t *socks)
{
  return Curl_pp_getsock(data, &conn->proto.imapc.pp, socks);
}

/***********************************************************************
 *
 * 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 Curl_easy *data, bool *done)
{
  CURLcode result = CURLE_OK;
  struct connectdata *conn = data->conn;
  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");



  PINGPONG_SETUP(pp, imap_statemachine, imap_endofresp);



  /* Set the default preferred authentication type and mechanism */
  imapc->preftype = IMAP_TYPE_ANY;
  Curl_sasl_init(&imapc->sasl, &saslimap);

  Curl_dyn_init(&imapc->dyn, DYN_IMAP_CMD);
  /* Initialise the pingpong layer */
  Curl_pp_setup(pp);
  Curl_pp_init(data, pp);

  /* Parse the URL options */
  result = imap_parse_url_options(conn);
  if(result)
    return result;

  /* Start off waiting for the server greeting response */
  state(data, IMAP_SERVERGREET);

  /* Start off with an response id of '*' */
  strcpy(imapc->resptag, "*");

  result = imap_multi_statemach(data, 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 Curl_easy *data, CURLcode status,
                          bool premature)
{
  CURLcode result = CURLE_OK;
  struct connectdata *conn = data->conn;
  struct IMAP *imap = data->req.p.imap;

  (void)premature;

  if(!imap)
    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 || imap->mindex || data->set.upload ||
          data->set.mimepost.kind != MIMEKIND_NONE)) {
    /* Handle responses after FETCH or APPEND transfer has finished */

    if(!data->set.upload && data->set.mimepost.kind == MIMEKIND_NONE)
      state(data, IMAP_FETCH_FINAL);
    else {
      /* End the APPEND command first by sending an empty line */
      result = Curl_pp_sendf(data, &conn->proto.imapc.pp, "%s", "");
      if(!result)
        state(data, IMAP_APPEND_FINAL);
    }

    /* Run the state-machine */
    if(!result)
      result = imap_block_statemach(data, conn, FALSE);
  }

  /* Cleanup our per-request based variables */
  Curl_safefree(imap->mailbox);
  Curl_safefree(imap->uidvalidity);
  Curl_safefree(imap->uid);
  Curl_safefree(imap->mindex);
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620

1621
1622

1623
1624
1625
1626
1627
1628
1629
1630
1631
1632

1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713

1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734

1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
/***********************************************************************
 *
 * 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 Curl_easy *data = conn->data;
  struct IMAP *imap = data->req.p.imap;
  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 &&
     strcasecompare(imap->mailbox, imapc->mailbox) &&
     (!imap->uidvalidity || !imapc->mailbox_uidvalidity ||
      strcasecompare(imap->uidvalidity, imapc->mailbox_uidvalidity)))
    selected = TRUE;

  /* Start the first command in the DO phase */
  if(conn->data->set.upload || data->set.mimepost.kind != MIMEKIND_NONE)
    /* 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 || imap->mindex))
    /* 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->mindex || 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, TRUE); /* ignore errors on LOGOUT */


  /* Disconnect from the server */
  Curl_pp_disconnect(&imapc->pp);
  Curl_dyn_free(&imapc->dyn);

  /* 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.p.imap;

  (void)connected;

  if(imap->transfer != FTPTRANSFER_BODY)
    /* no data to transfer */
    Curl_setup_transfer(conn->data, -1, -1, FALSE, -1);

  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 Curl_easy *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)

{
  /* Initialise the IMAP layer */
  CURLcode result = imap_init(conn);
  if(result)
    return result;

  /* Clear the TLS upgraded flag */
  conn->bits.tls_upgraded = FALSE;

  return CURLE_OK;
}

/***********************************************************************
 *
 * imap_sendf()
 *
 * Sends the formatted 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;

  DEBUGASSERT(fmt);

  /* Calculate the tag based on the connection ID and command ID */
  msnprintf(imapc->resptag, sizeof(imapc->resptag), "%c%03d",
            'A' + curlx_sltosi(conn->connection_id % 26),
            (++imapc->cmdid)%1000);

  /* start with a blank buffer */
  Curl_dyn_reset(&imapc->dyn);

  /* append tag + space + fmt */
  result = Curl_dyn_addf(&imapc->dyn, "%s %s", imapc->resptag, fmt);
  if(!result) {
    va_list ap;
    va_start(ap, fmt);
    result = Curl_pp_vsendf(&imapc->pp, Curl_dyn_ptr(&imapc->dyn), ap);
    va_end(ap);
  }
  return result;
}

/***********************************************************************
 *







|




|




|

|















|

|


|


|


|



|


|





|




|













|


<



|




|



|











|
>


>







|
|
|
>
















|

|





|





|

|


|

|

|














|




<











|



|




|
>


|

















|
>



















|







1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607

1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706

1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
/***********************************************************************
 *
 * 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 Curl_easy *data, bool *connected,
                             bool *dophase_done)
{
  /* This is IMAP and no proxy */
  CURLcode result = CURLE_OK;
  struct connectdata *conn = data->conn;
  struct IMAP *imap = data->req.p.imap;
  struct imap_conn *imapc = &conn->proto.imapc;
  bool selected = FALSE;

  DEBUGF(infof(data, "DO phase starts\n"));

  if(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 &&
     strcasecompare(imap->mailbox, imapc->mailbox) &&
     (!imap->uidvalidity || !imapc->mailbox_uidvalidity ||
      strcasecompare(imap->uidvalidity, imapc->mailbox_uidvalidity)))
    selected = TRUE;

  /* Start the first command in the DO phase */
  if(data->set.upload || data->set.mimepost.kind != MIMEKIND_NONE)
    /* APPEND can be executed directly */
    result = imap_perform_append(data);
  else if(imap->custom && (selected || !imap->mailbox))
    /* Custom command using the same mailbox or no mailbox */
    result = imap_perform_list(data);
  else if(!imap->custom && selected && (imap->uid || imap->mindex))
    /* FETCH from the same mailbox */
    result = imap_perform_fetch(data, conn);
  else if(!imap->custom && selected && imap->query)
    /* SEARCH the current mailbox */
    result = imap_perform_search(data, conn);
  else if(imap->mailbox && !selected &&
         (imap->custom || imap->uid || imap->mindex || imap->query))
    /* SELECT the mailbox */
    result = imap_perform_select(data);
  else
    /* LIST */
    result = imap_perform_list(data);

  if(result)
    return result;

  /* Run the state-machine */
  result = imap_multi_statemach(data, dophase_done);

  *connected = conn->bits.tcpconnect[FIRSTSOCKET];

  if(*dophase_done)
    DEBUGF(infof(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 Curl_easy *data, bool *done)
{
  CURLcode result = CURLE_OK;

  *done = FALSE; /* default to false */

  /* Parse the URL path */
  result = imap_parse_url_path(data);
  if(result)
    return result;

  /* Parse the custom request */
  result = imap_parse_custom_request(data);
  if(result)
    return result;

  result = imap_regular_transfer(data, done);

  return result;
}

/***********************************************************************
 *
 * imap_disconnect()
 *
 * Disconnect from an IMAP server. Cleanup protocol-specific per-connection
 * resources. BLOCKING.
 */
static CURLcode imap_disconnect(struct Curl_easy *data,
                                struct connectdata *conn, bool dead_connection)
{
  struct imap_conn *imapc = &conn->proto.imapc;
  (void)data;

  /* 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 && conn->bits.protoconnstart) {
    if(!imap_perform_logout(data, conn))
      (void)imap_block_statemach(data, conn, TRUE); /* ignore errors */
  }

  /* Disconnect from the server */
  Curl_pp_disconnect(&imapc->pp);
  Curl_dyn_free(&imapc->dyn);

  /* 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 Curl_easy *data, bool connected)
{
  struct IMAP *imap = data->req.p.imap;

  (void)connected;

  if(imap->transfer != FTPTRANSFER_BODY)
    /* no data to transfer */
    Curl_setup_transfer(data, -1, -1, FALSE, -1);

  return CURLE_OK;
}

/* Called from multi.c while DOing */
static CURLcode imap_doing(struct Curl_easy *data, bool *dophase_done)
{
  CURLcode result = imap_multi_statemach(data, dophase_done);

  if(result)
    DEBUGF(infof(data, "DO phase failed\n"));
  else if(*dophase_done) {
    result = imap_dophase_done(data, FALSE /* not connected */);

    DEBUGF(infof(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 Curl_easy *data,
                                      bool *dophase_done)
{
  CURLcode result = CURLE_OK;
  bool connected = FALSE;


  /* 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(data, &connected, dophase_done);

  /* Perform post DO phase operations if necessary */
  if(!result && *dophase_done)
    result = imap_dophase_done(data, connected);

  return result;
}

static CURLcode imap_setup_connection(struct Curl_easy *data,
                                      struct connectdata *conn)
{
  /* Initialise the IMAP layer */
  CURLcode result = imap_init(data);
  if(result)
    return result;

  /* Clear the TLS upgraded flag */
  conn->bits.tls_upgraded = FALSE;

  return CURLE_OK;
}

/***********************************************************************
 *
 * imap_sendf()
 *
 * Sends the formatted string as an IMAP command to the server.
 *
 * Designed to never block.
 */
static CURLcode imap_sendf(struct Curl_easy *data,
                           struct connectdata *conn, const char *fmt, ...)
{
  CURLcode result = CURLE_OK;
  struct imap_conn *imapc = &conn->proto.imapc;

  DEBUGASSERT(fmt);

  /* Calculate the tag based on the connection ID and command ID */
  msnprintf(imapc->resptag, sizeof(imapc->resptag), "%c%03d",
            'A' + curlx_sltosi(conn->connection_id % 26),
            (++imapc->cmdid)%1000);

  /* start with a blank buffer */
  Curl_dyn_reset(&imapc->dyn);

  /* append tag + space + fmt */
  result = Curl_dyn_addf(&imapc->dyn, "%s %s", imapc->resptag, fmt);
  if(!result) {
    va_list ap;
    va_start(ap, fmt);
    result = Curl_pp_vsendf(data, &imapc->pp, Curl_dyn_ptr(&imapc->dyn), ap);
    va_end(ap);
  }
  return result;
}

/***********************************************************************
 *
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
/***********************************************************************
 *
 * 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 Curl_easy *data = conn->data;
  struct IMAP *imap = data->req.p.imap;
  const char *begin = &data->state.up.path[1]; /* skip leading slash */
  const char *ptr = begin;

  /* See how much of the URL is a valid path and decode it */
  while(imap_is_bchar(*ptr))
    ptr++;







|



<







1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962

1963
1964
1965
1966
1967
1968
1969
/***********************************************************************
 *
 * imap_parse_url_path()
 *
 * Parse the URL path into separate path components.
 *
 */
static CURLcode imap_parse_url_path(struct Curl_easy *data)
{
  /* The imap struct is already initialised in imap_connect() */
  CURLcode result = CURLE_OK;

  struct IMAP *imap = data->req.p.imap;
  const char *begin = &data->state.up.path[1]; /* skip leading slash */
  const char *ptr = begin;

  /* See how much of the URL is a valid path and decode it */
  while(imap_is_bchar(*ptr))
    ptr++;
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
    result = Curl_urldecode(data, begin, ptr - begin, &value, &valuelen,
                            REJECT_CTRL);
    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(strcasecompare(name, "UIDVALIDITY") && !imap->uidvalidity) {
      if(valuelen > 0 && value[valuelen - 1] == '/')







|







2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
    result = Curl_urldecode(data, begin, ptr - begin, &value, &valuelen,
                            REJECT_CTRL);
    if(result) {
      free(name);
      return result;
    }

    DEBUGF(infof(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(strcasecompare(name, "UIDVALIDITY") && !imap->uidvalidity) {
      if(valuelen > 0 && value[valuelen - 1] == '/')
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086

/***********************************************************************
 *
 * imap_parse_custom_request()
 *
 * Parse the custom request.
 */
static CURLcode imap_parse_custom_request(struct connectdata *conn)
{
  CURLcode result = CURLE_OK;
  struct Curl_easy *data = conn->data;
  struct IMAP *imap = data->req.p.imap;
  const char *custom = data->set.str[STRING_CUSTOMREQUEST];

  if(custom) {
    /* URL decode the custom request */
    result = Curl_urldecode(data, custom, 0, &imap->custom, NULL, REJECT_CTRL);








|


<







2084
2085
2086
2087
2088
2089
2090
2091
2092
2093

2094
2095
2096
2097
2098
2099
2100

/***********************************************************************
 *
 * imap_parse_custom_request()
 *
 * Parse the custom request.
 */
static CURLcode imap_parse_custom_request(struct Curl_easy *data)
{
  CURLcode result = CURLE_OK;

  struct IMAP *imap = data->req.p.imap;
  const char *custom = data->set.str[STRING_CUSTOMREQUEST];

  if(custom) {
    /* URL decode the custom request */
    result = Curl_urldecode(data, custom, 0, &imap->custom, NULL, REJECT_CTRL);

Changes to jni/curl/lib/krb5.c.
1
2
3
4
5
6
7
8
9
10
11
12
/* GSSAPI/krb5 support for FTP - loosely based on old krb4.c
 *
 * Copyright (c) 1995, 1996, 1997, 1998, 1999 Kungliga Tekniska Högskolan
 * (Royal Institute of Technology, Stockholm, Sweden).
 * Copyright (c) 2004 - 2020 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




|







1
2
3
4
5
6
7
8
9
10
11
12
/* GSSAPI/krb5 support for FTP - loosely based on old krb4.c
 *
 * Copyright (c) 1995, 1996, 1997, 1998, 1999 Kungliga Tekniska Högskolan
 * (Royal Institute of Technology, Stockholm, Sweden).
 * Copyright (c) 2004 - 2021 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
52
53
54
55
56
57
58
59

60
61
62
63
64
65
66
#include "strdup.h"

/* The last 3 #include files should be in this order */
#include "curl_printf.h"
#include "curl_memory.h"
#include "memdebug.h"

static CURLcode ftpsend(struct connectdata *conn, const char *cmd)

{
  ssize_t bytes_written;
#define SBUF_SIZE 1024
  char s[SBUF_SIZE];
  size_t write_len;
  char *sptr = s;
  CURLcode result = CURLE_OK;







|
>







52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
#include "strdup.h"

/* The last 3 #include files should be in this order */
#include "curl_printf.h"
#include "curl_memory.h"
#include "memdebug.h"

static CURLcode ftpsend(struct Curl_easy *data, struct connectdata *conn,
                        const char *cmd)
{
  ssize_t bytes_written;
#define SBUF_SIZE 1024
  char s[SBUF_SIZE];
  size_t write_len;
  char *sptr = s;
  CURLcode result = CURLE_OK;
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
    return CURLE_BAD_FUNCTION_ARGUMENT;

  memcpy(&s, cmd, write_len);
  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;

    Curl_debug(conn->data, CURLINFO_HEADER_OUT, sptr, (size_t)bytes_written);

    if(bytes_written != (ssize_t)write_len) {
      write_len -= bytes_written;
      sptr += bytes_written;
    }
    else
      break;







|








|









|







77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
    return CURLE_BAD_FUNCTION_ARGUMENT;

  memcpy(&s, cmd, write_len);
  strcpy(&s[write_len], "\r\n"); /* append a trailing CRLF */
  write_len += 2;
  bytes_written = 0;

  result = Curl_convert_to_network(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(data, 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;

    Curl_debug(data, CURLINFO_HEADER_OUT, sptr, (size_t)bytes_written);

    if(bytes_written != (ssize_t)write_len) {
      write_len -= bytes_written;
      sptr += bytes_written;
    }
    else
      break;
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
  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 Curl_easy *data = conn->data;
  CURLcode result;
  const char *service = data->set.str[STRING_SERVICE_NAME] ?
                        data->set.str[STRING_SERVICE_NAME] :
                        "ftp";
  const char *srv_host = "host";
  gss_buffer_desc input_buffer, output_buffer, _gssresp, *gssresp;
  OM_uint32 maj, min;







|






<







199
200
201
202
203
204
205
206
207
208
209
210
211
212

213
214
215
216
217
218
219
  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 Curl_easy *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);

  CURLcode result;
  const char *service = data->set.str[STRING_SERVICE_NAME] ?
                        data->set.str[STRING_SERVICE_NAME] :
                        "ftp";
  const char *srv_host = "host";
  gss_buffer_desc input_buffer, output_buffer, _gssresp, *gssresp;
  OM_uint32 maj, min;
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
  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 = ftpsend(conn, "AUTH GSSAPI");
      if(result)
        return -2;

      if(Curl_GetFTPResponse(&nread, conn, NULL))
        return -1;

      if(data->state.buffer[0] != '3')
        return -1;
    }

    stringp = aprintf("%s@%s", service, host);







|



|







238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
  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 = ftpsend(data, conn, "AUTH GSSAPI");
      if(result)
        return -2;

      if(Curl_GetFTPResponse(data, &nread, NULL))
        return -1;

      if(data->state.buffer[0] != '3')
        return -1;
    }

    stringp = aprintf("%s@%s", service, host);
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
                     curl_easy_strerror(result));
          ret = AUTH_ERROR;
          break;
        }

        cmd = aprintf("ADAT %s", p);
        if(cmd)
          result = ftpsend(conn, cmd);
        else
          result = CURLE_OUT_OF_MEMORY;

        free(p);
        free(cmd);

        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;







|











|







315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
                     curl_easy_strerror(result));
          ret = AUTH_ERROR;
          break;
        }

        cmd = aprintf("ADAT %s", p);
        if(cmd)
          result = ftpsend(data, conn, cmd);
        else
          result = CURLE_OUT_OF_MEMORY;

        free(p);
        free(cmd);

        if(result) {
          ret = -2;
          break;
        }

        if(Curl_GetFTPResponse(data, &nread, 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;
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
  DEBUGASSERT(0);
  /* Default to the most secure alternative. */
  return 'P';
}

/* 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);
  mvsnprintf(print_buffer, sizeof(print_buffer), message, args);
  va_end(args);

  if(ftpsend(conn, print_buffer)) {
    ftp_code = -1;
  }
  else {
    if(Curl_GetFTPResponse(&nread, conn, &ftp_code))
      ftp_code = -1;
  }

  (void)nread; /* Unused */
  return ftp_code;
}








|










|



|







439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
  DEBUGASSERT(0);
  /* Default to the most secure alternative. */
  return 'P';
}

/* 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 Curl_easy *data, const char *message, ...)
{
  int ftp_code;
  ssize_t nread = 0;
  va_list args;
  char print_buffer[50];

  va_start(args, message);
  mvsnprintf(print_buffer, sizeof(print_buffer), message, args);
  va_end(args);

  if(ftpsend(data, data->conn, print_buffer)) {
    ftp_code = -1;
  }
  else {
    if(Curl_GetFTPResponse(data, &nread, &ftp_code))
      ftp_code = -1;
  }

  (void)nread; /* Unused */
  return ftp_code;
}

491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
}


/* 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 {
      if(result == CURLE_AGAIN)
        continue;







|







|







491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
}


/* 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 Curl_easy *data, 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(data, fd, to_p, len, &written);
    if(!result) {
      len -= written;
      to_p += written;
    }
    else {
      if(result == CURLE_AGAIN)
        continue;
552
553
554
555
556
557
558
559
560
561
562
563

564
565
566
567
568
569
570
571
572
573
574
575
576
577
    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 sread(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);







|




>






|







552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
    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 Curl_easy *data, int sockindex,
                        char *buffer, size_t len, CURLcode *err)
{
  size_t bytes_read;
  size_t total_read = 0;
  struct connectdata *conn = data->conn;
  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 sread(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);
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
    buffer += bytes_read;
  }
  return total_read;
}

/* Send |length| bytes from |from| to the |fd| socket taking care of encoding
   and negotiating with the server. |from| can be NULL. */
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;







|
|







594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
    buffer += bytes_read;
  }
  return total_read;
}

/* Send |length| bytes from |from| to the |fd| socket taking care of encoding
   and negotiating with the server. |from| can be NULL. */
static void do_sec_send(struct Curl_easy *data, 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;
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678

679
680
681
682
683
684
685
686
687
688
689
690
691
692
693


694
695
696
697
698
699
700
  }
  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);
}

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 = 0;
  size_t decoded_sz = 0;
  CURLcode error;



  if(!conn->mech)
    /* not inititalized, return error */
    return -1;

  DEBUGASSERT(level > PROT_NONE && level < PROT_LAST);








|









|

|

|
|
|






|
|




|
|











|








|


>


|


|
|








>
>







619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
  }
  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(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(data, fd, enc, 4);
      else
        socket_write(data, fd, mic, 4);

      socket_write(data, fd, cmd_buffer, cmd_size);
      socket_write(data, fd, "\r\n", 2);
      infof(data, "Send: %s%s\n", prot_level == PROT_PRIVATE?enc:mic,
            cmd_buffer);
      free(cmd_buffer);
    }
  }
  else {
    htonl_bytes = htonl(bytes);
    socket_write(data, fd, &htonl_bytes, sizeof(htonl_bytes));
    socket_write(data, fd, buffer, curlx_sitouz(bytes));
  }
  free(buffer);
}

static ssize_t sec_write(struct Curl_easy *data, 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(data, conn, fd, buffer, curlx_sztosi(len));
    length -= len;
    buffer += len;
    tx += len;
  }
  return tx;
}

/* Matches Curl_send signature */
static ssize_t sec_send(struct Curl_easy *data, int sockindex,
                        const void *buffer, size_t len, CURLcode *err)
{
  struct connectdata *conn = data->conn;
  curl_socket_t fd = conn->sock[sockindex];
  *err = CURLE_OK;
  return sec_write(data, conn, fd, buffer, len);
}

int Curl_sec_read_msg(struct Curl_easy *data, 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 = 0;
  size_t decoded_sz = 0;
  CURLcode error;

  (void) data;

  if(!conn->mech)
    /* not inititalized, return error */
    return -1;

  DEBUGASSERT(level > PROT_NONE && level < PROT_LAST);

713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741

742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
  if(decoded_len <= 0) {
    free(buf);
    return -1;
  }

  {
    buf[decoded_len] = '\n';
    Curl_debug(conn->data, CURLINFO_HEADER_IN, buf, decoded_len + 1);
  }

  buf[decoded_len] = '\0';
  if(decoded_len <= 3)
    /* suspiciously short */
    return 0;

  if(buf[3] != '-')
    /* safe to ignore return code */
    (void)sscanf(buf, "%d", &ret_code);

  if(buf[decoded_len - 1] == '\n')
    buf[decoded_len - 1] = '\0';
  strcpy(buffer, buf);
  free(buf);
  return ret_code;
}

static int sec_set_protection_level(struct connectdata *conn)
{
  int code;

  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) {
    char *pbsz;
    static unsigned int buffer_size = 1 << 20; /* 1048576 */

    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) {
      /* ignore return code, use default value if it fails */
      (void)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;








|


















|


>





|
|











|




|




|









|





|







717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
  if(decoded_len <= 0) {
    free(buf);
    return -1;
  }

  {
    buf[decoded_len] = '\n';
    Curl_debug(data, CURLINFO_HEADER_IN, buf, decoded_len + 1);
  }

  buf[decoded_len] = '\0';
  if(decoded_len <= 3)
    /* suspiciously short */
    return 0;

  if(buf[3] != '-')
    /* safe to ignore return code */
    (void)sscanf(buf, "%d", &ret_code);

  if(buf[decoded_len - 1] == '\n')
    buf[decoded_len - 1] = '\0';
  strcpy(buffer, buf);
  free(buf);
  return ret_code;
}

static int sec_set_protection_level(struct Curl_easy *data)
{
  int code;
  struct connectdata *conn = data->conn;
  enum protection_level level = conn->request_data_prot;

  DEBUGASSERT(level > PROT_NONE && level < PROT_LAST);

  if(!conn->sec_complete) {
    infof(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) {
    char *pbsz;
    static unsigned int buffer_size = 1 << 20; /* 1048576 */

    code = ftp_send_command(data, "PBSZ %u", buffer_size);
    if(code < 0)
      return -1;

    if(code/100 != 2) {
      failf(data, "Failed to set the protection's buffer size.");
      return -1;
    }
    conn->buffer_size = buffer_size;

    pbsz = strstr(data->state.buffer, "PBSZ=");
    if(pbsz) {
      /* ignore return code, use default value if it fails */
      (void)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(data, "PROT %c", level_to_char(level));

  if(code < 0)
    return -1;

  if(code/100 != 2) {
    failf(data, "Failed to set the protection level.");
    return -1;
  }

  conn->data_prot = level;
  if(level == PROT_PRIVATE)
    conn->command_prot = level;

801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
  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 Curl_easy *data = conn->data;
  void *tmp_allocation;
  const struct Curl_sec_client_mech *mech = &Curl_krb5_client_mech;

  tmp_allocation = realloc(conn->app_data, mech->size);
  if(tmp_allocation == NULL) {
    failf(data, "Failed realloc of size %zu", mech->size);
    mech = NULL;







|


<







806
807
808
809
810
811
812
813
814
815

816
817
818
819
820
821
822
  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 Curl_easy *data, struct connectdata *conn)
{
  int ret;

  void *tmp_allocation;
  const struct Curl_sec_client_mech *mech = &Curl_krb5_client_mech;

  tmp_allocation = realloc(conn->app_data, mech->size);
  if(tmp_allocation == NULL) {
    failf(data, "Failed realloc of size %zu", mech->size);
    mech = NULL;
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
      infof(data, "Failed initialization for %s. Skipping it.\n",
            mech->name);
      return CURLE_FAILED_INIT;
    }
  }

  infof(data, "Trying mechanism %s...\n", mech->name);
  ret = ftp_send_command(conn, "AUTH %s", mech->name);
  if(ret < 0)
    return CURLE_COULDNT_CONNECT;

  if(ret/100 != 3) {
    switch(ret) {
    case 504:
      infof(data, "Mechanism %s is not supported by the server (server "







|







830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
      infof(data, "Failed initialization for %s. Skipping it.\n",
            mech->name);
      return CURLE_FAILED_INIT;
    }
  }

  infof(data, "Trying mechanism %s...\n", mech->name);
  ret = ftp_send_command(data, "AUTH %s", mech->name);
  if(ret < 0)
    return CURLE_COULDNT_CONNECT;

  if(ret/100 != 3) {
    switch(ret) {
    case 504:
      infof(data, "Mechanism %s is not supported by the server (server "
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
      }
      break;
    }
    return CURLE_LOGIN_DENIED;
  }

  /* Authenticate */
  ret = mech->auth(conn->app_data, conn);

  if(ret != AUTH_CONTINUE) {
    if(ret != AUTH_OK) {
      /* Mechanism has dumped the error to stderr, don't error here. */
      return CURLE_USE_SSL_FAILED;
    }
    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);
  }

  return CURLE_OK;
}

CURLcode
Curl_sec_login(struct connectdata *conn)
{
  return choose_mech(conn);
}


void
Curl_sec_end(struct connectdata *conn)
{
  if(conn->mech != NULL && conn->mech->end)







|

















|






|

|







855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
      }
      break;
    }
    return CURLE_LOGIN_DENIED;
  }

  /* Authenticate */
  ret = mech->auth(conn->app_data, data, conn);

  if(ret != AUTH_CONTINUE) {
    if(ret != AUTH_OK) {
      /* Mechanism has dumped the error to stderr, don't error here. */
      return CURLE_USE_SSL_FAILED;
    }
    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(data);
  }

  return CURLE_OK;
}

CURLcode
Curl_sec_login(struct Curl_easy *data, struct connectdata *conn)
{
  return choose_mech(data, conn);
}


void
Curl_sec_end(struct connectdata *conn)
{
  if(conn->mech != NULL && conn->mech->end)
Changes to jni/curl/lib/ldap.c.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/***************************************************************************
 *                      _   _ ____  _
 *  Project         ___| | | |  _ \| |
 *                 / __| | | | |_) | |
 *                | (__| |_| |  _ <| |___
 *                 \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2020, 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 https://curl.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







|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/***************************************************************************
 *                      _   _ ____  _
 *  Project         ___| | | |  _ \| |
 *                 / __| | | | |_) | |
 *                | (__| |_| |  _ <| |___
 *                 \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2021, 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 https://curl.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
96
97
98
99
100
101
102
103

104
105
106
107
108
109
110
                               "real" struct so can only be used in code
                               without HAVE_LDAP_URL_PARSE defined */
};

#undef LDAPURLDesc
#define LDAPURLDesc struct ldap_urldesc

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








|
>







96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
                               "real" struct so can only be used in code
                               without HAVE_LDAP_URL_PARSE defined */
};

#undef LDAPURLDesc
#define LDAPURLDesc struct ldap_urldesc

static int  _ldap_url_parse(struct Curl_easy *data,
                            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

122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
#if defined(USE_WIN32_LDAP) && defined(ldap_err2string)
/* Use ansi error strings in UNICODE builds */
#undef ldap_err2string
#define ldap_err2string ldap_err2stringA
#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 */







|








|







123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
#if defined(USE_WIN32_LDAP) && defined(ldap_err2string)
/* Use ansi error strings in UNICODE builds */
#undef ldap_err2string
#define ldap_err2string ldap_err2stringA
#endif


static CURLcode ldap_do(struct Curl_easy *data, bool *done);

/*
 * LDAP protocol handler.
 */

const struct Curl_handler Curl_handler_ldap = {
  "LDAP",                               /* scheme */
  ZERO_NULL,                            /* setup_connection */
  ldap_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 */
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
/*
 * 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 */







|







159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
/*
 * LDAPS protocol handler.
 */

const struct Curl_handler Curl_handler_ldaps = {
  "LDAPS",                              /* scheme */
  ZERO_NULL,                            /* setup_connection */
  ldap_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 */
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
    method = LDAP_AUTH_NEGOTIATE;
    rc = ldap_bind_s(server, NULL, NULL, method);
  }
  return rc;
}
#endif /* #if defined(USE_WINDOWS_SSPI) */

static int ldap_win_bind(struct connectdata *conn, LDAP *server,
                         const char *user, const char *passwd)
{
  int rc = LDAP_INVALID_CREDENTIALS;

  PTCHAR inuser = NULL;
  PTCHAR inpass = NULL;

  if(user && passwd && (conn->data->set.httpauth & CURLAUTH_BASIC)) {
    inuser = curlx_convert_UTF8_to_tchar((char *) user);
    inpass = curlx_convert_UTF8_to_tchar((char *) passwd);

    rc = ldap_simple_bind_s(server, inuser, inpass);

    curlx_unicodefree(inuser);
    curlx_unicodefree(inpass);
  }
#if defined(USE_WINDOWS_SSPI)
  else {
    rc = ldap_win_bind_auth(server, user, passwd, conn->data->set.httpauth);
  }
#endif

  return rc;
}
#endif /* #if defined(USE_WIN32_LDAP) */

#if defined(USE_WIN32_LDAP)
#define FREE_ON_WINLDAP(x) curlx_unicodefree(x)
#else
#define FREE_ON_WINLDAP(x)
#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 Curl_easy *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 */







|







|










|














|








|







229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
    method = LDAP_AUTH_NEGOTIATE;
    rc = ldap_bind_s(server, NULL, NULL, method);
  }
  return rc;
}
#endif /* #if defined(USE_WINDOWS_SSPI) */

static int ldap_win_bind(struct Curl_easy *data, LDAP *server,
                         const char *user, const char *passwd)
{
  int rc = LDAP_INVALID_CREDENTIALS;

  PTCHAR inuser = NULL;
  PTCHAR inpass = NULL;

  if(user && passwd && (data->set.httpauth & CURLAUTH_BASIC)) {
    inuser = curlx_convert_UTF8_to_tchar((char *) user);
    inpass = curlx_convert_UTF8_to_tchar((char *) passwd);

    rc = ldap_simple_bind_s(server, inuser, inpass);

    curlx_unicodefree(inuser);
    curlx_unicodefree(inpass);
  }
#if defined(USE_WINDOWS_SSPI)
  else {
    rc = ldap_win_bind_auth(server, user, passwd, data->set.httpauth);
  }
#endif

  return rc;
}
#endif /* #if defined(USE_WIN32_LDAP) */

#if defined(USE_WIN32_LDAP)
#define FREE_ON_WINLDAP(x) curlx_unicodefree(x)
#else
#define FREE_ON_WINLDAP(x)
#endif


static CURLcode ldap_do(struct Curl_easy *data, bool *done)
{
  CURLcode result = CURLE_OK;
  int rc = 0;
  LDAP *server = NULL;
  LDAPURLDesc *ludp = NULL;
  LDAPMessage *ldapmsg = NULL;
  LDAPMessage *entryIterator;
  int num = 0;
  struct connectdata *conn = data->conn;
  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 */
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
  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;
  }








|







297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
  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(data, conn, &ludp);
#endif
  if(rc != 0) {
    failf(data, "LDAP local: %s", ldap_err2string(rc));
    result = CURLE_LDAP_INVALID_URL;
    goto quit;
  }

468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
            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);
  rc = ldap_win_bind(conn, server, user, passwd);
#else
  rc = ldap_simple_bind_s(server, user, passwd);
#endif
  if(!ldap_ssl && rc != 0) {
    ldap_proto = LDAP_VERSION2;
    ldap_set_option(server, LDAP_OPT_PROTOCOL_VERSION, &ldap_proto);
#ifdef USE_WIN32_LDAP
    rc = ldap_win_bind(conn, server, user, passwd);
#else
    rc = ldap_simple_bind_s(server, user, passwd);
#endif
  }
  if(rc != 0) {
#ifdef USE_WIN32_LDAP
    failf(data, "LDAP local: bind via ldap_win_bind %s",







|







|







469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
            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);
  rc = ldap_win_bind(data, server, user, passwd);
#else
  rc = ldap_simple_bind_s(server, user, passwd);
#endif
  if(!ldap_ssl && rc != 0) {
    ldap_proto = LDAP_VERSION2;
    ldap_set_option(server, LDAP_OPT_PROTOCOL_VERSION, &ldap_proto);
#ifdef USE_WIN32_LDAP
    rc = ldap_win_bind(data, server, user, passwd);
#else
    rc = ldap_simple_bind_s(server, user, passwd);
#endif
  }
  if(rc != 0) {
#ifdef USE_WIN32_LDAP
    failf(data, "LDAP local: bind via ldap_win_bind %s",
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
        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) {
        FREE_ON_WINLDAP(name);
        ldap_memfree(dn);
        goto quit;
      }

      result = Curl_client_write(conn, CLIENTWRITE_BODY, (char *) name,
                                 name_len);
      if(result) {
        FREE_ON_WINLDAP(name);
        ldap_memfree(dn);
        goto quit;
      }

      result = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)"\n", 1);
      if(result) {
        FREE_ON_WINLDAP(name);
        ldap_memfree(dn);

        goto quit;
      }








|






|







|







533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
        goto quit;
      }
#else
      char *dn = name = ldap_get_dn(server, entryIterator);
#endif
      name_len = strlen(name);

      result = Curl_client_write(data, CLIENTWRITE_BODY, (char *)"DN: ", 4);
      if(result) {
        FREE_ON_WINLDAP(name);
        ldap_memfree(dn);
        goto quit;
      }

      result = Curl_client_write(data, CLIENTWRITE_BODY, (char *) name,
                                 name_len);
      if(result) {
        FREE_ON_WINLDAP(name);
        ldap_memfree(dn);
        goto quit;
      }

      result = Curl_client_write(data, CLIENTWRITE_BODY, (char *)"\n", 1);
      if(result) {
        FREE_ON_WINLDAP(name);
        ldap_memfree(dn);

        goto quit;
      }

585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
      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);
            FREE_ON_WINLDAP(attr);
            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);
            FREE_ON_WINLDAP(attr);
            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);
            FREE_ON_WINLDAP(attr);
            ldap_memfree(attribute);
            if(ber)
              ber_free(ber, 0);








|










|











|







586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
      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(data, CLIENTWRITE_BODY, (char *)"\t", 1);
          if(result) {
            ldap_value_free_len(vals);
            FREE_ON_WINLDAP(attr);
            ldap_memfree(attribute);
            if(ber)
              ber_free(ber, 0);

            goto quit;
          }

          result = Curl_client_write(data, CLIENTWRITE_BODY,
                                     (char *) attr, attr_len);
          if(result) {
            ldap_value_free_len(vals);
            FREE_ON_WINLDAP(attr);
            ldap_memfree(attribute);
            if(ber)
              ber_free(ber, 0);

            goto quit;
          }

          result = Curl_client_write(data, CLIENTWRITE_BODY, (char *)": ", 2);
          if(result) {
            ldap_value_free_len(vals);
            FREE_ON_WINLDAP(attr);
            ldap_memfree(attribute);
            if(ber)
              ber_free(ber, 0);

640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
              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);
                FREE_ON_WINLDAP(attr);
                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);
              FREE_ON_WINLDAP(attr);
              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);
            FREE_ON_WINLDAP(attr);
            ldap_memfree(attribute);
            if(ber)
              ber_free(ber, 0);








|
















|














|







641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
              if(ber)
                ber_free(ber, 0);

              goto quit;
            }

            if(val_b64_sz > 0) {
              result = Curl_client_write(data, CLIENTWRITE_BODY, val_b64,
                                         val_b64_sz);
              free(val_b64);
              if(result) {
                ldap_value_free_len(vals);
                FREE_ON_WINLDAP(attr);
                ldap_memfree(attribute);
                if(ber)
                  ber_free(ber, 0);

                goto quit;
              }

              dlsize += val_b64_sz;
            }
          }
          else {
            result = Curl_client_write(data, CLIENTWRITE_BODY, vals[i]->bv_val,
                                       vals[i]->bv_len);
            if(result) {
              ldap_value_free_len(vals);
              FREE_ON_WINLDAP(attr);
              ldap_memfree(attribute);
              if(ber)
                ber_free(ber, 0);

              goto quit;
            }

            dlsize += vals[i]->bv_len;
          }

          result = Curl_client_write(data, CLIENTWRITE_BODY, (char *)"\n", 1);
          if(result) {
            ldap_value_free_len(vals);
            FREE_ON_WINLDAP(attr);
            ldap_memfree(attribute);
            if(ber)
              ber_free(ber, 0);

694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
        ldap_value_free_len(vals);
      }

      /* Free the attribute as we are done with it */
      FREE_ON_WINLDAP(attr);
      ldap_memfree(attribute);

      result = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)"\n", 1);
      if(result)
        goto quit;
      dlsize++;
      Curl_pgrsSetDownloadCounter(data, dlsize);
    }

    if(ber)







|







695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
        ldap_value_free_len(vals);
      }

      /* Free the attribute as we are done with it */
      FREE_ON_WINLDAP(attr);
      ldap_memfree(attribute);

      result = Curl_client_write(data, CLIENTWRITE_BODY, (char *)"\n", 1);
      if(result)
        goto quit;
      dlsize++;
      Curl_pgrsSetDownloadCounter(data, dlsize);
    }

    if(ber)
808
809
810
811
812
813
814
815
816
817
818
819
820
821

822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
/*
 * 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 *p;
  char *path;
  char *q = NULL;
  char *query = NULL;
  size_t i;

  if(!conn->data ||
     !conn->data->state.up.path ||
     conn->data->state.up.path[0] != '/' ||
     !strncasecompare("LDAP", conn->data->state.up.scheme, 4))
    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.up.path + 1);
  if(!path)
    return LDAP_NO_MEMORY;

  /* Duplicate the query if present */
  if(conn->data->state.up.query) {
    q = query = strdup(conn->data->state.up.query);
    if(!query) {
      free(path);
      return LDAP_NO_MEMORY;
    }
  }

  /* Parse the DN (Distinguished Name) */
  if(*p) {
    char *dn = p;
    char *unescaped;
    CURLcode result;

    LDAP_TRACE(("DN '%s'\n", dn));

    /* Unescape the DN */
    result = Curl_urldecode(conn->data, dn, 0, &unescaped, NULL, REJECT_ZERO);
    if(result) {
      rc = LDAP_NO_MEMORY;

      goto quit;
    }

#if defined(USE_WIN32_LDAP)







|






>
|








|
|
|
|







|




|
|















|







809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
/*
 * 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 '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(struct Curl_easy *data,
                            const struct connectdata *conn, LDAPURLDesc *ludp)
{
  int rc = LDAP_SUCCESS;
  char *p;
  char *path;
  char *q = NULL;
  char *query = NULL;
  size_t i;

  if(!data ||
     !data->state.up.path ||
     data->state.up.path[0] != '/' ||
     !strncasecompare("LDAP", data->state.up.scheme, 4))
    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(data->state.up.path + 1);
  if(!path)
    return LDAP_NO_MEMORY;

  /* Duplicate the query if present */
  if(data->state.up.query) {
    q = query = strdup(data->state.up.query);
    if(!query) {
      free(path);
      return LDAP_NO_MEMORY;
    }
  }

  /* Parse the DN (Distinguished Name) */
  if(*p) {
    char *dn = p;
    char *unescaped;
    CURLcode result;

    LDAP_TRACE(("DN '%s'\n", dn));

    /* Unescape the DN */
    result = Curl_urldecode(data, dn, 0, &unescaped, NULL, REJECT_ZERO);
    if(result) {
      rc = LDAP_NO_MEMORY;

      goto quit;
    }

#if defined(USE_WIN32_LDAP)
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
    for(i = 0; i < count; i++) {
      char *unescaped;
      CURLcode result;

      LDAP_TRACE(("attr[%zu] '%s'\n", i, attributes[i]));

      /* Unescape the attribute */
      result = Curl_urldecode(conn->data, attributes[i], 0, &unescaped, NULL,
                              REJECT_ZERO);
      if(result) {
        free(attributes);

        rc = LDAP_NO_MEMORY;

        goto quit;







|







924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
    for(i = 0; i < count; i++) {
      char *unescaped;
      CURLcode result;

      LDAP_TRACE(("attr[%zu] '%s'\n", i, attributes[i]));

      /* Unescape the attribute */
      result = Curl_urldecode(data, attributes[i], 0, &unescaped, NULL,
                              REJECT_ZERO);
      if(result) {
        free(attributes);

        rc = LDAP_NO_MEMORY;

        goto quit;
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
    char *filter = p;
    char *unescaped;
    CURLcode result;

    LDAP_TRACE(("filter '%s'\n", filter));

    /* Unescape the filter */
    result = Curl_urldecode(conn->data, filter, 0, &unescaped, NULL,
                            REJECT_ZERO);
    if(result) {
      rc = LDAP_NO_MEMORY;

      goto quit;
    }

#if defined(USE_WIN32_LDAP)







|
<







994
995
996
997
998
999
1000
1001

1002
1003
1004
1005
1006
1007
1008
    char *filter = p;
    char *unescaped;
    CURLcode result;

    LDAP_TRACE(("filter '%s'\n", filter));

    /* Unescape the filter */
    result = Curl_urldecode(data, filter, 0, &unescaped, NULL, REJECT_ZERO);

    if(result) {
      rc = LDAP_NO_MEMORY;

      goto quit;
    }

#if defined(USE_WIN32_LDAP)
1031
1032
1033
1034
1035
1036
1037
1038

1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
quit:
  free(path);
  free(query);

  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);
}







|
>









|







1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
quit:
  free(path);
  free(query);

  return rc;
}

static int _ldap_url_parse(struct Curl_easy *data,
                           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(data, conn, ludp);
  if(rc != LDAP_SUCCESS) {
    _ldap_free_urldesc(ludp);
    ludp = NULL;
  }
  *ludpp = ludp;
  return (rc);
}
Changes to jni/curl/lib/libcurl.plist.
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
	<key>CFBundleExecutable</key>
	<string>curl</string>

	<key>CFBundleIdentifier</key>
	<string>se.curl.libcurl</string>

	<key>CFBundleVersion</key>
	<string>7.74.0</string>

	<key>CFBundleName</key>
	<string>libcurl</string>

	<key>CFBundlePackageType</key>
	<string>FMWK</string>

	<key>CFBundleSignature</key>
	<string>????</string>

	<key>CFBundleShortVersionString</key>
	<string>libcurl 7.74.0</string>

	<key>CFBundleGetInfoString</key>
	<string>libcurl.plist 7.74.0</string>
</dict>
</plist>







|











|


|


11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
	<key>CFBundleExecutable</key>
	<string>curl</string>

	<key>CFBundleIdentifier</key>
	<string>se.curl.libcurl</string>

	<key>CFBundleVersion</key>
	<string>7.75.0</string>

	<key>CFBundleName</key>
	<string>libcurl</string>

	<key>CFBundlePackageType</key>
	<string>FMWK</string>

	<key>CFBundleSignature</key>
	<string>????</string>

	<key>CFBundleShortVersionString</key>
	<string>libcurl 7.75.0</string>

	<key>CFBundleGetInfoString</key>
	<string>libcurl.plist 7.75.0</string>
</dict>
</plist>
Changes to jni/curl/lib/makefile.dj.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
#***************************************************************************
#                                  _   _ ____  _
#  Project                     ___| | | |  _ \| |
#                             / __| | | | |_) | |
#                            | (__| |_| |  _ <| |___
#                             \___|\___/|_| \_\_____|
#
# Copyright (C) 2003 - 2008, Gisle Vanem <gvanem@yahoo.no>.
# Copyright (C) 2003 - 2020, 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 https://curl.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.
#
#***************************************************************************

#
#  Adapted for djgpp2 / Watt-32 / DOS
#

DEPEND_PREREQ = curl_config.h
VPATH  = vtls vauth
TOPDIR = ..

include ../packages/DOS/common.dj
include Makefile.inc

CFLAGS += -DBUILDING_LIBCURL








|




















|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
#***************************************************************************
#                                  _   _ ____  _
#  Project                     ___| | | |  _ \| |
#                             / __| | | | |_) | |
#                            | (__| |_| |  _ <| |___
#                             \___|\___/|_| \_\_____|
#
# Copyright (C) 2003 - 2021, Gisle Vanem <gvanem@yahoo.no>.
# Copyright (C) 2003 - 2020, 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 https://curl.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.
#
#***************************************************************************

#
#  Adapted for djgpp2 / Watt-32 / DOS
#

DEPEND_PREREQ = curl_config.h
VPATH  = vtls vauth vquic vssh
TOPDIR = ..

include ../packages/DOS/common.dj
include Makefile.inc

CFLAGS += -DBUILDING_LIBCURL

Changes to jni/curl/lib/mime.c.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2020, 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 https://curl.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







|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2021, 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 https://curl.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
1164
1165
1166
1167
1168
1169
1170

1171
1172
1173
1174
1175
1176
1177
  part->data = NULL;
  part->fp = NULL;
  part->datasize = (curl_off_t) 0;    /* No size yet. */
  cleanup_encoder_state(&part->encstate);
  part->kind = MIMEKIND_NONE;
  part->flags &= ~MIME_FAST_READ;
  part->lastreadstatus = 1; /* Successful read status. */

}

static void mime_subparts_free(void *ptr)
{
  curl_mime *mime = (curl_mime *) ptr;

  if(mime && mime->parent) {







>







1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
  part->data = NULL;
  part->fp = NULL;
  part->datasize = (curl_off_t) 0;    /* No size yet. */
  cleanup_encoder_state(&part->encstate);
  part->kind = MIMEKIND_NONE;
  part->flags &= ~MIME_FAST_READ;
  part->lastreadstatus = 1; /* Successful read status. */
  part->state.state = MIMESTATE_BEGIN;
}

static void mime_subparts_free(void *ptr)
{
  curl_mime *mime = (curl_mime *) ptr;

  if(mime && mime->parent) {
Changes to jni/curl/lib/mime.h.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#ifndef HEADER_CURL_MIME_H
#define HEADER_CURL_MIME_H
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2020, 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 https://curl.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









|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#ifndef HEADER_CURL_MIME_H
#define HEADER_CURL_MIME_H
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2021, 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 https://curl.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
106
107
108
109
110
111
112

113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132

/* A mime part. */
struct curl_mimepart {
  struct Curl_easy *easy;          /* The associated easy handle. */
  curl_mime *parent;               /* Parent mime structure. */
  curl_mimepart *nextpart;         /* Forward linked list. */
  enum mimekind kind;              /* The part kind. */

  char *data;                      /* Memory data or file name. */
  curl_read_callback readfunc;     /* Read function. */
  curl_seek_callback seekfunc;     /* Seek function. */
  curl_free_callback freefunc;     /* Argument free function. */
  void *arg;                       /* Argument to callback functions. */
  FILE *fp;                        /* File pointer. */
  struct curl_slist *curlheaders;  /* Part headers. */
  struct curl_slist *userheaders;  /* Part headers. */
  char *mimetype;                  /* Part mime type. */
  char *filename;                  /* Remote file name. */
  char *name;                      /* Data name. */
  curl_off_t datasize;             /* Expected data size. */
  unsigned int flags;              /* Flags. */
  struct mime_state state;         /* Current readback state. */
  const struct mime_encoder *encoder; /* Content data encoder. */
  struct mime_encoder_state encstate; /* Data encoder state. */
  size_t lastreadstatus;           /* Last read callback returned status. */
};

CURLcode Curl_mime_add_header(struct curl_slist **slp, const char *fmt, ...);







>












<







106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125

126
127
128
129
130
131
132

/* A mime part. */
struct curl_mimepart {
  struct Curl_easy *easy;          /* The associated easy handle. */
  curl_mime *parent;               /* Parent mime structure. */
  curl_mimepart *nextpart;         /* Forward linked list. */
  enum mimekind kind;              /* The part kind. */
  unsigned int flags;              /* Flags. */
  char *data;                      /* Memory data or file name. */
  curl_read_callback readfunc;     /* Read function. */
  curl_seek_callback seekfunc;     /* Seek function. */
  curl_free_callback freefunc;     /* Argument free function. */
  void *arg;                       /* Argument to callback functions. */
  FILE *fp;                        /* File pointer. */
  struct curl_slist *curlheaders;  /* Part headers. */
  struct curl_slist *userheaders;  /* Part headers. */
  char *mimetype;                  /* Part mime type. */
  char *filename;                  /* Remote file name. */
  char *name;                      /* Data name. */
  curl_off_t datasize;             /* Expected data size. */

  struct mime_state state;         /* Current readback state. */
  const struct mime_encoder *encoder; /* Content data encoder. */
  struct mime_encoder_state encstate; /* Data encoder state. */
  size_t lastreadstatus;           /* Last read callback returned status. */
};

CURLcode Curl_mime_add_header(struct curl_slist **slp, const char *fmt, ...);
Changes to jni/curl/lib/mk-ca-bundle.pl.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#!/usr/bin/env perl
# ***************************************************************************
# *                                  _   _ ____  _
# *  Project                     ___| | | |  _ \| |
# *                             / __| | | | |_) | |
# *                            | (__| |_| |  _ <| |___
# *                             \___|\___/|_| \_\_____|
# *
# * Copyright (C) 1998 - 2020, 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 https://curl.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








|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#!/usr/bin/env perl
# ***************************************************************************
# *                                  _   _ ____  _
# *  Project                     ___| | | |  _ \| |
# *                             / __| | | | |_) | |
# *                            | (__| |_| |  _ <| |___
# *                             \___|\___/|_| \_\_____|
# *
# * Copyright (C) 1998 - 2021, 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 https://curl.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
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
      my $pem = "-----BEGIN CERTIFICATE-----\n"
              . $encoded
              . "-----END CERTIFICATE-----\n";
      print CRT "\n$caname\n";
      print CRT @precert if($opt_m);
      my $maxStringLength = length(decode('UTF-8', $caname, Encode::FB_CROAK | Encode::LEAVE_SRC));
      if ($opt_t) {
        foreach my $key (keys %trust_purposes_by_level) {
           my $string = $key . ": " . join(", ", @{$trust_purposes_by_level{$key}});
           $maxStringLength = List::Util::max( length($string), $maxStringLength );
           print CRT $string . "\n";
        }
      }
      print CRT ("=" x $maxStringLength . "\n");
      if (!$opt_t) {







|







541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
      my $pem = "-----BEGIN CERTIFICATE-----\n"
              . $encoded
              . "-----END CERTIFICATE-----\n";
      print CRT "\n$caname\n";
      print CRT @precert if($opt_m);
      my $maxStringLength = length(decode('UTF-8', $caname, Encode::FB_CROAK | Encode::LEAVE_SRC));
      if ($opt_t) {
        foreach my $key (sort keys %trust_purposes_by_level) {
           my $string = $key . ": " . join(", ", @{$trust_purposes_by_level{$key}});
           $maxStringLength = List::Util::max( length($string), $maxStringLength );
           print CRT $string . "\n";
        }
      }
      print CRT ("=" x $maxStringLength . "\n");
      if (!$opt_t) {
Changes to jni/curl/lib/mqtt.c.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
 * Copyright (C) 2019, Björn Stenberg, <bjorn@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 https://curl.se/docs/copyright.html.
 *
 * You may opt to use, copy, modify, merge, publish, distribute and/or sell







|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 2020 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
 * Copyright (C) 2019, Björn Stenberg, <bjorn@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 https://curl.se/docs/copyright.html.
 *
 * You may opt to use, copy, modify, merge, publish, distribute and/or sell
55
56
57
58
59
60
61
62
63

64
65

66
67
68
69
70
71
72
#define MQTT_SUBACK_LEN 3
#define MQTT_CLIENTID_LEN 12 /* "curl0123abcd" */

/*
 * Forward declarations.
 */

static CURLcode mqtt_do(struct connectdata *conn, bool *done);
static CURLcode mqtt_doing(struct connectdata *conn, bool *done);

static int mqtt_getsock(struct connectdata *conn, curl_socket_t *sock);
static CURLcode mqtt_setup_conn(struct connectdata *conn);


/*
 * MQTT protocol handler.
 */

const struct Curl_handler Curl_handler_mqtt = {
  "MQTT",                             /* scheme */







|
|
>
|
|
>







55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
#define MQTT_SUBACK_LEN 3
#define MQTT_CLIENTID_LEN 12 /* "curl0123abcd" */

/*
 * Forward declarations.
 */

static CURLcode mqtt_do(struct Curl_easy *data, bool *done);
static CURLcode mqtt_doing(struct Curl_easy *data, bool *done);
static int mqtt_getsock(struct Curl_easy *data, struct connectdata *conn,
                        curl_socket_t *sock);
static CURLcode mqtt_setup_conn(struct Curl_easy *data,
                                struct connectdata *conn);

/*
 * MQTT protocol handler.
 */

const struct Curl_handler Curl_handler_mqtt = {
  "MQTT",                             /* scheme */
86
87
88
89
90
91
92
93

94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111

112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133

134
135

136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178

179
180
181
182
183
184
185
186
187
188
189
190
191
  ZERO_NULL,                          /* connection_check */
  PORT_MQTT,                          /* defport */
  CURLPROTO_MQTT,                     /* protocol */
  CURLPROTO_MQTT,                     /* family */
  PROTOPT_NONE                        /* flags */
};

static CURLcode mqtt_setup_conn(struct connectdata *conn)

{
  /* allocate the HTTP-specific struct for the Curl_easy, only to survive
     during this request */
  struct MQTT *mq;
  struct Curl_easy *data = conn->data;
  DEBUGASSERT(data->req.p.mqtt == NULL);

  mq = calloc(1, sizeof(struct MQTT));
  if(!mq)
    return CURLE_OUT_OF_MEMORY;
  data->req.p.mqtt = mq;
  return CURLE_OK;
}

static CURLcode mqtt_send(struct connectdata *conn,
                          char *buf, size_t len)
{
  CURLcode result = CURLE_OK;

  curl_socket_t sockfd = conn->sock[FIRSTSOCKET];
  struct Curl_easy *data = conn->data;
  struct MQTT *mq = data->req.p.mqtt;
  ssize_t n;
  result = Curl_write(conn, sockfd, buf, len, &n);
  if(!result)
    Curl_debug(data, CURLINFO_HEADER_OUT, buf, (size_t)n);
  if(len != (size_t)n) {
    size_t nsend = len - n;
    char *sendleftovers = Curl_memdup(&buf[n], nsend);
    if(!sendleftovers)
      return CURLE_OUT_OF_MEMORY;
    mq->sendleftovers = sendleftovers;
    mq->nsend = nsend;
  }
  return result;
}

/* 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 mqtt_getsock(struct connectdata *conn,

                        curl_socket_t *sock)
{

  sock[0] = conn->sock[FIRSTSOCKET];
  return GETSOCK_READSOCK(FIRSTSOCKET);
}

static CURLcode mqtt_connect(struct connectdata *conn)
{
  CURLcode result = CURLE_OK;
  const size_t client_id_offset = 14;
  const size_t packetlen = client_id_offset + MQTT_CLIENTID_LEN;
  char client_id[MQTT_CLIENTID_LEN + 1] = "curl";
  const size_t clen = strlen("curl");
  char packet[32] = {
    MQTT_MSG_CONNECT,  /* packet type */
    0x00,              /* remaining length */
    0x00, 0x04,        /* protocol length */
    'M','Q','T','T',   /* protocol name */
    0x04,              /* protocol level */
    0x02,              /* CONNECT flag: CleanSession */
    0x00, 0x3c,        /* keep-alive 0 = disabled */
    0x00, 0x00         /* payload1 length */
  };
  packet[1] = (packetlen - 2) & 0x7f;
  packet[client_id_offset - 1] = MQTT_CLIENTID_LEN;

  result = Curl_rand_hex(conn->data, (unsigned char *)&client_id[clen],
                         MQTT_CLIENTID_LEN - clen + 1);
  memcpy(&packet[client_id_offset], client_id, MQTT_CLIENTID_LEN);
  infof(conn->data, "Using client id '%s'\n", client_id);
  if(!result)
    result = mqtt_send(conn, packet, packetlen);
  return result;
}

static CURLcode mqtt_disconnect(struct connectdata *conn)
{
  CURLcode result = CURLE_OK;
  result = mqtt_send(conn, (char *)"\xe0\x00", 2);
  return result;
}

static CURLcode mqtt_verify_connack(struct connectdata *conn)
{
  CURLcode result;

  curl_socket_t sockfd = conn->sock[FIRSTSOCKET];
  unsigned char readbuf[MQTT_CONNACK_LEN];
  ssize_t nread;
  struct Curl_easy *data = conn->data;

  result = Curl_read(conn, sockfd, (char *)readbuf, MQTT_CONNACK_LEN, &nread);
  if(result)
    goto fail;

  Curl_debug(data, CURLINFO_HEADER_IN, (char *)readbuf, (size_t)nread);

  /* fixme */
  if(nread < MQTT_CONNACK_LEN) {







|
>




|









|



>

<


|
















|
>


>




|



















|


|

|



|


|



|


>



<

|







88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116

117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187

188
189
190
191
192
193
194
195
196
  ZERO_NULL,                          /* connection_check */
  PORT_MQTT,                          /* defport */
  CURLPROTO_MQTT,                     /* protocol */
  CURLPROTO_MQTT,                     /* family */
  PROTOPT_NONE                        /* flags */
};

static CURLcode mqtt_setup_conn(struct Curl_easy *data,
                                struct connectdata *conn)
{
  /* allocate the HTTP-specific struct for the Curl_easy, only to survive
     during this request */
  struct MQTT *mq;
  (void)conn;
  DEBUGASSERT(data->req.p.mqtt == NULL);

  mq = calloc(1, sizeof(struct MQTT));
  if(!mq)
    return CURLE_OUT_OF_MEMORY;
  data->req.p.mqtt = mq;
  return CURLE_OK;
}

static CURLcode mqtt_send(struct Curl_easy *data,
                          char *buf, size_t len)
{
  CURLcode result = CURLE_OK;
  struct connectdata *conn = data->conn;
  curl_socket_t sockfd = conn->sock[FIRSTSOCKET];

  struct MQTT *mq = data->req.p.mqtt;
  ssize_t n;
  result = Curl_write(data, sockfd, buf, len, &n);
  if(!result)
    Curl_debug(data, CURLINFO_HEADER_OUT, buf, (size_t)n);
  if(len != (size_t)n) {
    size_t nsend = len - n;
    char *sendleftovers = Curl_memdup(&buf[n], nsend);
    if(!sendleftovers)
      return CURLE_OUT_OF_MEMORY;
    mq->sendleftovers = sendleftovers;
    mq->nsend = nsend;
  }
  return result;
}

/* 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 mqtt_getsock(struct Curl_easy *data,
                        struct connectdata *conn,
                        curl_socket_t *sock)
{
  (void)data;
  sock[0] = conn->sock[FIRSTSOCKET];
  return GETSOCK_READSOCK(FIRSTSOCKET);
}

static CURLcode mqtt_connect(struct Curl_easy *data)
{
  CURLcode result = CURLE_OK;
  const size_t client_id_offset = 14;
  const size_t packetlen = client_id_offset + MQTT_CLIENTID_LEN;
  char client_id[MQTT_CLIENTID_LEN + 1] = "curl";
  const size_t clen = strlen("curl");
  char packet[32] = {
    MQTT_MSG_CONNECT,  /* packet type */
    0x00,              /* remaining length */
    0x00, 0x04,        /* protocol length */
    'M','Q','T','T',   /* protocol name */
    0x04,              /* protocol level */
    0x02,              /* CONNECT flag: CleanSession */
    0x00, 0x3c,        /* keep-alive 0 = disabled */
    0x00, 0x00         /* payload1 length */
  };
  packet[1] = (packetlen - 2) & 0x7f;
  packet[client_id_offset - 1] = MQTT_CLIENTID_LEN;

  result = Curl_rand_hex(data, (unsigned char *)&client_id[clen],
                         MQTT_CLIENTID_LEN - clen + 1);
  memcpy(&packet[client_id_offset], client_id, MQTT_CLIENTID_LEN);
  infof(data, "Using client id '%s'\n", client_id);
  if(!result)
    result = mqtt_send(data, packet, packetlen);
  return result;
}

static CURLcode mqtt_disconnect(struct Curl_easy *data)
{
  CURLcode result = CURLE_OK;
  result = mqtt_send(data, (char *)"\xe0\x00", 2);
  return result;
}

static CURLcode mqtt_verify_connack(struct Curl_easy *data)
{
  CURLcode result;
  struct connectdata *conn = data->conn;
  curl_socket_t sockfd = conn->sock[FIRSTSOCKET];
  unsigned char readbuf[MQTT_CONNACK_LEN];
  ssize_t nread;


  result = Curl_read(data, sockfd, (char *)readbuf, MQTT_CONNACK_LEN, &nread);
  if(result)
    goto fail;

  Curl_debug(data, CURLINFO_HEADER_IN, (char *)readbuf, (size_t)nread);

  /* fixme */
  if(nread < MQTT_CONNACK_LEN) {
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
    result = CURLE_WEIRD_SERVER_REPLY;
  }

fail:
  return result;
}

static CURLcode mqtt_get_topic(struct connectdata *conn,
                               char **topic, size_t *topiclen)
{
  CURLcode result = CURLE_OK;
  char *path = conn->data->state.up.path;

  if(strlen(path) > 1) {
    result = Curl_urldecode(conn->data, path + 1, 0, topic, topiclen,
                            REJECT_NADA);
  }
  else {
    failf(conn->data, "Error: No topic specified.");
    result = CURLE_URL_MALFORMAT;
  }
  return result;
}


static int mqtt_encode_len(char *buf, size_t len)







|



|


|



|







205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
    result = CURLE_WEIRD_SERVER_REPLY;
  }

fail:
  return result;
}

static CURLcode mqtt_get_topic(struct Curl_easy *data,
                               char **topic, size_t *topiclen)
{
  CURLcode result = CURLE_OK;
  char *path = data->state.up.path;

  if(strlen(path) > 1) {
    result = Curl_urldecode(data, path + 1, 0, topic, topiclen,
                            REJECT_NADA);
  }
  else {
    failf(data, "Error: No topic specified.");
    result = CURLE_URL_MALFORMAT;
  }
  return result;
}


static int mqtt_encode_len(char *buf, size_t len)
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249

250
251
252
253
254
255
256
257
258
      encoded |= 0x80;
    buf[i] = encoded;
  }

  return i;
}

static CURLcode mqtt_subscribe(struct connectdata *conn)
{
  CURLcode result = CURLE_OK;
  char *topic = NULL;
  size_t topiclen;
  unsigned char *packet = NULL;
  size_t packetlen;
  char encodedsize[4];
  size_t n;


  result = mqtt_get_topic(conn, &topic, &topiclen);
  if(result)
    goto fail;

  conn->proto.mqtt.packetid++;

  packetlen = topiclen + 5; /* packetid + topic (has a two byte length field)
                               + 2 bytes topic length + QoS byte */







|








>

|







239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
      encoded |= 0x80;
    buf[i] = encoded;
  }

  return i;
}

static CURLcode mqtt_subscribe(struct Curl_easy *data)
{
  CURLcode result = CURLE_OK;
  char *topic = NULL;
  size_t topiclen;
  unsigned char *packet = NULL;
  size_t packetlen;
  char encodedsize[4];
  size_t n;
  struct connectdata *conn = data->conn;

  result = mqtt_get_topic(data, &topic, &topiclen);
  if(result)
    goto fail;

  conn->proto.mqtt.packetid++;

  packetlen = topiclen + 5; /* packetid + topic (has a two byte length field)
                               + 2 bytes topic length + QoS byte */
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290

291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329

330







331
332
333
334
335
336
337
338
  packet[1 + n] = (conn->proto.mqtt.packetid >> 8) & 0xff;
  packet[2 + n] = conn->proto.mqtt.packetid & 0xff;
  packet[3 + n] = (topiclen >> 8) & 0xff;
  packet[4 + n ] = topiclen & 0xff;
  memcpy(&packet[5 + n], topic, topiclen);
  packet[5 + n + topiclen] = 0; /* QoS zero */

  result = mqtt_send(conn, (char *)packet, packetlen);

fail:
  free(topic);
  free(packet);
  return result;
}

/*
 * Called when the first byte was already read.
 */
static CURLcode mqtt_verify_suback(struct connectdata *conn)
{
  CURLcode result;

  curl_socket_t sockfd = conn->sock[FIRSTSOCKET];
  unsigned char readbuf[MQTT_SUBACK_LEN];
  ssize_t nread;
  struct mqtt_conn *mqtt = &conn->proto.mqtt;

  result = Curl_read(conn, sockfd, (char *)readbuf, MQTT_SUBACK_LEN, &nread);
  if(result)
    goto fail;

  Curl_debug(conn->data, CURLINFO_HEADER_IN, (char *)readbuf, (size_t)nread);

  /* fixme */
  if(nread < MQTT_SUBACK_LEN) {
    result = CURLE_WEIRD_SERVER_REPLY;
    goto fail;
  }

  /* verify SUBACK */
  if(readbuf[0] != ((mqtt->packetid >> 8) & 0xff) ||
     readbuf[1] != (mqtt->packetid & 0xff) ||
     readbuf[2] != 0x00)
    result = CURLE_WEIRD_SERVER_REPLY;

fail:
  return result;
}

static CURLcode mqtt_publish(struct connectdata *conn)
{
  CURLcode result;
  char *payload = conn->data->set.postfields;
  size_t payloadlen = (size_t)conn->data->set.postfieldsize;
  char *topic = NULL;
  size_t topiclen;
  unsigned char *pkt = NULL;
  size_t i = 0;
  size_t remaininglength;
  size_t encodelen;
  char encodedbytes[4];









  result = mqtt_get_topic(conn, &topic, &topiclen);
  if(result)
    goto fail;

  remaininglength = payloadlen + 2 + topiclen;
  encodelen = mqtt_encode_len(encodedbytes, remaininglength);

  /* add the control byte and the encoded remaining length */







|










|


>





|



|

















|


|
|







>

>
>
>
>
>
>
>
|







276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
  packet[1 + n] = (conn->proto.mqtt.packetid >> 8) & 0xff;
  packet[2 + n] = conn->proto.mqtt.packetid & 0xff;
  packet[3 + n] = (topiclen >> 8) & 0xff;
  packet[4 + n ] = topiclen & 0xff;
  memcpy(&packet[5 + n], topic, topiclen);
  packet[5 + n + topiclen] = 0; /* QoS zero */

  result = mqtt_send(data, (char *)packet, packetlen);

fail:
  free(topic);
  free(packet);
  return result;
}

/*
 * Called when the first byte was already read.
 */
static CURLcode mqtt_verify_suback(struct Curl_easy *data)
{
  CURLcode result;
  struct connectdata *conn = data->conn;
  curl_socket_t sockfd = conn->sock[FIRSTSOCKET];
  unsigned char readbuf[MQTT_SUBACK_LEN];
  ssize_t nread;
  struct mqtt_conn *mqtt = &conn->proto.mqtt;

  result = Curl_read(data, sockfd, (char *)readbuf, MQTT_SUBACK_LEN, &nread);
  if(result)
    goto fail;

  Curl_debug(data, CURLINFO_HEADER_IN, (char *)readbuf, (size_t)nread);

  /* fixme */
  if(nread < MQTT_SUBACK_LEN) {
    result = CURLE_WEIRD_SERVER_REPLY;
    goto fail;
  }

  /* verify SUBACK */
  if(readbuf[0] != ((mqtt->packetid >> 8) & 0xff) ||
     readbuf[1] != (mqtt->packetid & 0xff) ||
     readbuf[2] != 0x00)
    result = CURLE_WEIRD_SERVER_REPLY;

fail:
  return result;
}

static CURLcode mqtt_publish(struct Curl_easy *data)
{
  CURLcode result;
  char *payload = data->set.postfields;
  size_t payloadlen;
  char *topic = NULL;
  size_t topiclen;
  unsigned char *pkt = NULL;
  size_t i = 0;
  size_t remaininglength;
  size_t encodelen;
  char encodedbytes[4];
  curl_off_t postfieldsize = data->set.postfieldsize;

  if(!payload)
    return CURLE_BAD_FUNCTION_ARGUMENT;
  if(postfieldsize < 0)
    payloadlen = strlen(payload);
  else
    payloadlen = (size_t)postfieldsize;

  result = mqtt_get_topic(data, &topic, &topiclen);
  if(result)
    goto fail;

  remaininglength = payloadlen + 2 + topiclen;
  encodelen = mqtt_encode_len(encodedbytes, remaininglength);

  /* add the control byte and the encoded remaining length */
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
  i += encodelen;
  pkt[i++] = (topiclen >> 8) & 0xff;
  pkt[i++] = (topiclen & 0xff);
  memcpy(&pkt[i], topic, topiclen);
  i += topiclen;
  memcpy(&pkt[i], payload, payloadlen);
  i += payloadlen;
  result = mqtt_send(conn, (char *)pkt, i);

fail:
  free(pkt);
  free(topic);
  return result;
}








|







363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
  i += encodelen;
  pkt[i++] = (topiclen >> 8) & 0xff;
  pkt[i++] = (topiclen & 0xff);
  memcpy(&pkt[i], topic, topiclen);
  i += topiclen;
  memcpy(&pkt[i], payload, payloadlen);
  i += payloadlen;
  result = mqtt_send(data, (char *)pkt, i);

fail:
  free(pkt);
  free(topic);
  return result;
}

391
392
393
394
395
396
397
398
399
400
401

402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421

422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
  "MQTT_PUB_REMAIN",

  "NOT A STATE"
};
#endif

/* The only way to change state */
static void mqstate(struct connectdata *conn,
                    enum mqttstate state,
                    enum mqttstate nextstate) /* used if state == FIRST */
{

  struct mqtt_conn *mqtt = &conn->proto.mqtt;
#ifdef CURLDEBUG
  infof(conn->data, "%s (from %s) (next is %s)\n",
        statenames[state],
        statenames[mqtt->state],
        (state == MQTT_FIRST)? statenames[nextstate] : "");
#endif
  mqtt->state = state;
  if(state == MQTT_FIRST)
    mqtt->nextstate = nextstate;
}


/* for the publish packet */
#define MQTT_HEADER_LEN 5    /* max 5 bytes */

static CURLcode mqtt_read_publish(struct connectdata *conn,
                                  bool *done)
{
  CURLcode result = CURLE_OK;

  curl_socket_t sockfd = conn->sock[FIRSTSOCKET];
  ssize_t nread;
  struct Curl_easy *data = conn->data;
  unsigned char *pkt = (unsigned char *)data->state.buffer;
  size_t remlen;
  struct mqtt_conn *mqtt = &conn->proto.mqtt;
  struct MQTT *mq = data->req.p.mqtt;
  unsigned char packet;

  switch(mqtt->state) {
  MQTT_SUBACK_COMING:
  case MQTT_SUBACK_COMING:
    result = mqtt_verify_suback(conn);
    if(result)
      break;

    mqstate(conn, MQTT_FIRST, MQTT_PUBWAIT);
    break;

  case MQTT_SUBACK:
  case MQTT_PUBWAIT:
    /* we are expecting PUBLISH or SUBACK */
    packet = mq->firstbyte & 0xf0;
    if(packet == MQTT_MSG_PUBLISH)
      mqstate(conn, MQTT_PUB_REMAIN, MQTT_NOSTATE);
    else if(packet == MQTT_MSG_SUBACK) {
      mqstate(conn, MQTT_SUBACK_COMING, MQTT_NOSTATE);
      goto MQTT_SUBACK_COMING;
    }
    else if(packet == MQTT_MSG_DISCONNECT) {
      infof(data, "Got DISCONNECT\n");
      *done = TRUE;
      goto end;
    }







|



>


|













|
<


>


<









|



|







|

|







406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434

435
436
437
438
439

440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
  "MQTT_PUB_REMAIN",

  "NOT A STATE"
};
#endif

/* The only way to change state */
static void mqstate(struct Curl_easy *data,
                    enum mqttstate state,
                    enum mqttstate nextstate) /* used if state == FIRST */
{
  struct connectdata *conn = data->conn;
  struct mqtt_conn *mqtt = &conn->proto.mqtt;
#ifdef CURLDEBUG
  infof(data, "%s (from %s) (next is %s)\n",
        statenames[state],
        statenames[mqtt->state],
        (state == MQTT_FIRST)? statenames[nextstate] : "");
#endif
  mqtt->state = state;
  if(state == MQTT_FIRST)
    mqtt->nextstate = nextstate;
}


/* for the publish packet */
#define MQTT_HEADER_LEN 5    /* max 5 bytes */

static CURLcode mqtt_read_publish(struct Curl_easy *data, bool *done)

{
  CURLcode result = CURLE_OK;
  struct connectdata *conn = data->conn;
  curl_socket_t sockfd = conn->sock[FIRSTSOCKET];
  ssize_t nread;

  unsigned char *pkt = (unsigned char *)data->state.buffer;
  size_t remlen;
  struct mqtt_conn *mqtt = &conn->proto.mqtt;
  struct MQTT *mq = data->req.p.mqtt;
  unsigned char packet;

  switch(mqtt->state) {
  MQTT_SUBACK_COMING:
  case MQTT_SUBACK_COMING:
    result = mqtt_verify_suback(data);
    if(result)
      break;

    mqstate(data, MQTT_FIRST, MQTT_PUBWAIT);
    break;

  case MQTT_SUBACK:
  case MQTT_PUBWAIT:
    /* we are expecting PUBLISH or SUBACK */
    packet = mq->firstbyte & 0xf0;
    if(packet == MQTT_MSG_PUBLISH)
      mqstate(data, MQTT_PUB_REMAIN, MQTT_NOSTATE);
    else if(packet == MQTT_MSG_SUBACK) {
      mqstate(data, MQTT_SUBACK_COMING, MQTT_NOSTATE);
      goto MQTT_SUBACK_COMING;
    }
    else if(packet == MQTT_MSG_DISCONNECT) {
      infof(data, "Got DISCONNECT\n");
      *done = TRUE;
      goto end;
    }
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531

532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
    /* FALLTHROUGH */
  case MQTT_PUB_REMAIN: {
    /* read rest of packet, but no more. Cap to buffer size */
    struct SingleRequest *k = &data->req;
    size_t rest = mq->npacket;
    if(rest > (size_t)data->set.buffer_size)
      rest = (size_t)data->set.buffer_size;
    result = Curl_read(conn, sockfd, (char *)pkt, rest, &nread);
    if(result) {
      if(CURLE_AGAIN == result) {
        infof(data, "EEEE AAAAGAIN\n");
      }
      goto end;
    }
    if(!nread) {
      infof(data, "server disconnected\n");
      result = CURLE_PARTIAL_FILE;
      goto end;
    }
    Curl_debug(data, CURLINFO_DATA_IN, (char *)pkt, (size_t)nread);

    mq->npacket -= nread;
    k->bytecount += nread;
    Curl_pgrsSetDownloadCounter(data, k->bytecount);

    /* if QoS is set, message contains packet id */

    result = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)pkt, nread);
    if(result)
      goto end;

    if(!mq->npacket)
      /* no more PUBLISH payload, back to subscribe wait state */
      mqstate(conn, MQTT_FIRST, MQTT_PUBWAIT);
    break;
  }
  default:
    DEBUGASSERT(NULL); /* illegal state */
    result = CURLE_WEIRD_SERVER_REPLY;
    goto end;
  }
  end:
  return result;
}

static CURLcode mqtt_do(struct connectdata *conn, bool *done)
{
  CURLcode result = CURLE_OK;
  struct Curl_easy *data = conn->data;

  *done = FALSE; /* unconditionally */

  result = mqtt_connect(conn);
  if(result) {
    failf(data, "Error %d sending MQTT CONN request", result);
    return result;
  }
  mqstate(conn, MQTT_FIRST, MQTT_CONNACK);
  return CURLE_OK;
}

static CURLcode mqtt_doing(struct connectdata *conn, bool *done)
{
  CURLcode result = CURLE_OK;

  struct mqtt_conn *mqtt = &conn->proto.mqtt;
  struct Curl_easy *data = conn->data;
  struct MQTT *mq = data->req.p.mqtt;
  ssize_t nread;
  curl_socket_t sockfd = conn->sock[FIRSTSOCKET];
  unsigned char *pkt = (unsigned char *)data->state.buffer;
  unsigned char byte;

  *done = FALSE;

  if(mq->nsend) {
    /* send the remainder of an outgoing packet */
    char *ptr = mq->sendleftovers;
    result = mqtt_send(conn, mq->sendleftovers, mq->nsend);
    free(ptr);
    if(result)
      return result;
  }

  infof(data, "mqtt_doing: state [%d]\n", (int) mqtt->state);
  switch(mqtt->state) {
  case MQTT_FIRST:
    /* Read the initial byte only */
    result = Curl_read(conn, sockfd, (char *)&mq->firstbyte, 1, &nread);
    if(result)
      break;
    Curl_debug(data, CURLINFO_HEADER_IN, (char *)&mq->firstbyte, 1);
    /* remember the first byte */
    mq->npacket = 0;
    mqstate(conn, MQTT_REMAINING_LENGTH, MQTT_NOSTATE);
    /* FALLTHROUGH */
  case MQTT_REMAINING_LENGTH:
    do {
      result = Curl_read(conn, sockfd, (char *)&byte, 1, &nread);
      if(result)
        break;
      Curl_debug(data, CURLINFO_HEADER_IN, (char *)&byte, 1);
      pkt[mq->npacket++] = byte;
    } while((byte & 0x80) && (mq->npacket < 4));
    if(result)
      break;
    mq->remaining_length = mqtt_decode_len(&pkt[0], mq->npacket, NULL);
    mq->npacket = 0;
    if(mq->remaining_length) {
      mqstate(conn, mqtt->nextstate, MQTT_NOSTATE);
      break;
    }
    mqstate(conn, MQTT_FIRST, MQTT_FIRST);

    if(mq->firstbyte == MQTT_MSG_DISCONNECT) {
      infof(data, "Got DISCONNECT\n");
      *done = TRUE;
    }
    break;
  case MQTT_CONNACK:
    result = mqtt_verify_connack(conn);
    if(result)
      break;

    if(conn->data->state.httpreq == HTTPREQ_POST) {
      result = mqtt_publish(conn);
      if(!result) {
        result = mqtt_disconnect(conn);
        *done = TRUE;
      }
      mqtt->nextstate = MQTT_FIRST;
    }
    else {
      result = mqtt_subscribe(conn);
      if(!result) {
        mqstate(conn, MQTT_FIRST, MQTT_SUBACK);
      }
    }
    break;

  case MQTT_SUBACK:
  case MQTT_PUBWAIT:
  case MQTT_PUB_REMAIN:
    result = mqtt_read_publish(conn, done);
    break;

  default:
    failf(conn->data, "State not handled yet");
    *done = TRUE;
    break;
  }

  if(result == CURLE_AGAIN)
    result = CURLE_OK;
  return result;
}

#endif /* CURL_DISABLE_MQTT */







|



















|





|











|


<
<


|




|



|


>

<











|









|
|




|



|
|









|


|







|



|
|

|





|

|







|



|










483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530


531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546

547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
    /* FALLTHROUGH */
  case MQTT_PUB_REMAIN: {
    /* read rest of packet, but no more. Cap to buffer size */
    struct SingleRequest *k = &data->req;
    size_t rest = mq->npacket;
    if(rest > (size_t)data->set.buffer_size)
      rest = (size_t)data->set.buffer_size;
    result = Curl_read(data, sockfd, (char *)pkt, rest, &nread);
    if(result) {
      if(CURLE_AGAIN == result) {
        infof(data, "EEEE AAAAGAIN\n");
      }
      goto end;
    }
    if(!nread) {
      infof(data, "server disconnected\n");
      result = CURLE_PARTIAL_FILE;
      goto end;
    }
    Curl_debug(data, CURLINFO_DATA_IN, (char *)pkt, (size_t)nread);

    mq->npacket -= nread;
    k->bytecount += nread;
    Curl_pgrsSetDownloadCounter(data, k->bytecount);

    /* if QoS is set, message contains packet id */

    result = Curl_client_write(data, CLIENTWRITE_BODY, (char *)pkt, nread);
    if(result)
      goto end;

    if(!mq->npacket)
      /* no more PUBLISH payload, back to subscribe wait state */
      mqstate(data, MQTT_FIRST, MQTT_PUBWAIT);
    break;
  }
  default:
    DEBUGASSERT(NULL); /* illegal state */
    result = CURLE_WEIRD_SERVER_REPLY;
    goto end;
  }
  end:
  return result;
}

static CURLcode mqtt_do(struct Curl_easy *data, bool *done)
{
  CURLcode result = CURLE_OK;


  *done = FALSE; /* unconditionally */

  result = mqtt_connect(data);
  if(result) {
    failf(data, "Error %d sending MQTT CONN request", result);
    return result;
  }
  mqstate(data, MQTT_FIRST, MQTT_CONNACK);
  return CURLE_OK;
}

static CURLcode mqtt_doing(struct Curl_easy *data, bool *done)
{
  CURLcode result = CURLE_OK;
  struct connectdata *conn = data->conn;
  struct mqtt_conn *mqtt = &conn->proto.mqtt;

  struct MQTT *mq = data->req.p.mqtt;
  ssize_t nread;
  curl_socket_t sockfd = conn->sock[FIRSTSOCKET];
  unsigned char *pkt = (unsigned char *)data->state.buffer;
  unsigned char byte;

  *done = FALSE;

  if(mq->nsend) {
    /* send the remainder of an outgoing packet */
    char *ptr = mq->sendleftovers;
    result = mqtt_send(data, mq->sendleftovers, mq->nsend);
    free(ptr);
    if(result)
      return result;
  }

  infof(data, "mqtt_doing: state [%d]\n", (int) mqtt->state);
  switch(mqtt->state) {
  case MQTT_FIRST:
    /* Read the initial byte only */
    result = Curl_read(data, sockfd, (char *)&mq->firstbyte, 1, &nread);
    if(!nread)
      break;
    Curl_debug(data, CURLINFO_HEADER_IN, (char *)&mq->firstbyte, 1);
    /* remember the first byte */
    mq->npacket = 0;
    mqstate(data, MQTT_REMAINING_LENGTH, MQTT_NOSTATE);
    /* FALLTHROUGH */
  case MQTT_REMAINING_LENGTH:
    do {
      result = Curl_read(data, sockfd, (char *)&byte, 1, &nread);
      if(!nread)
        break;
      Curl_debug(data, CURLINFO_HEADER_IN, (char *)&byte, 1);
      pkt[mq->npacket++] = byte;
    } while((byte & 0x80) && (mq->npacket < 4));
    if(result)
      break;
    mq->remaining_length = mqtt_decode_len(&pkt[0], mq->npacket, NULL);
    mq->npacket = 0;
    if(mq->remaining_length) {
      mqstate(data, mqtt->nextstate, MQTT_NOSTATE);
      break;
    }
    mqstate(data, MQTT_FIRST, MQTT_FIRST);

    if(mq->firstbyte == MQTT_MSG_DISCONNECT) {
      infof(data, "Got DISCONNECT\n");
      *done = TRUE;
    }
    break;
  case MQTT_CONNACK:
    result = mqtt_verify_connack(data);
    if(result)
      break;

    if(data->state.httpreq == HTTPREQ_POST) {
      result = mqtt_publish(data);
      if(!result) {
        result = mqtt_disconnect(data);
        *done = TRUE;
      }
      mqtt->nextstate = MQTT_FIRST;
    }
    else {
      result = mqtt_subscribe(data);
      if(!result) {
        mqstate(data, MQTT_FIRST, MQTT_SUBACK);
      }
    }
    break;

  case MQTT_SUBACK:
  case MQTT_PUBWAIT:
  case MQTT_PUB_REMAIN:
    result = mqtt_read_publish(data, done);
    break;

  default:
    failf(data, "State not handled yet");
    *done = TRUE;
    break;
  }

  if(result == CURLE_AGAIN)
    result = CURLE_OK;
  return result;
}

#endif /* CURL_DISABLE_MQTT */
Changes to jni/curl/lib/multi.c.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2020, 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 https://curl.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







|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2021, 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 https://curl.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
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
#ifndef CURL_CONNECTION_HASH_SIZE
#define CURL_CONNECTION_HASH_SIZE 97
#endif

#define CURL_MULTI_HANDLE 0x000bab1e

#define GOOD_MULTI_HANDLE(x) \
  ((x) && (x)->type == CURL_MULTI_HANDLE)

static CURLMcode singlesocket(struct Curl_multi *multi,
                              struct Curl_easy *data);
static CURLMcode add_next_timeout(struct curltime now,
                                  struct Curl_multi *multi,
                                  struct Curl_easy *d);
static CURLMcode multi_timeout(struct Curl_multi *multi,







|







65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
#ifndef CURL_CONNECTION_HASH_SIZE
#define CURL_CONNECTION_HASH_SIZE 97
#endif

#define CURL_MULTI_HANDLE 0x000bab1e

#define GOOD_MULTI_HANDLE(x) \
  ((x) && (x)->magic == CURL_MULTI_HANDLE)

static CURLMcode singlesocket(struct Curl_multi *multi,
                              struct Curl_easy *data);
static CURLMcode add_next_timeout(struct curltime now,
                                  struct Curl_multi *multi,
                                  struct Curl_easy *d);
static CURLMcode multi_timeout(struct Curl_multi *multi,
101
102
103
104
105
106
107







108
109
110
111
112
113
114
115
  "MSGSENT",
};
#endif

/* function pointer called once when switching TO a state */
typedef void (*init_multistate_func)(struct Curl_easy *data);








static void Curl_init_completed(struct Curl_easy *data)
{
  /* this is a completed transfer */

  /* Important: reset the conn pointer so that we don't point to memory
     that could be freed anytime */
  Curl_detach_connnection(data);
  Curl_expire_clear(data); /* stop all timers */







>
>
>
>
>
>
>
|







101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
  "MSGSENT",
};
#endif

/* function pointer called once when switching TO a state */
typedef void (*init_multistate_func)(struct Curl_easy *data);

/* called when the PERFORM state starts  */
static void init_perform(struct Curl_easy *data)
{
  data->req.chunk = FALSE;
  Curl_pgrsTime(data, TIMER_PRETRANSFER);
}

static void init_completed(struct Curl_easy *data)
{
  /* this is a completed transfer */

  /* Important: reset the conn pointer so that we don't point to memory
     that could be freed anytime */
  Curl_detach_connnection(data);
  Curl_expire_clear(data); /* stop all timers */
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
    NULL,              /* WAITPROXYCONNECT */
    NULL,              /* SENDPROTOCONNECT */
    NULL,              /* PROTOCONNECT */
    Curl_connect_free, /* DO */
    NULL,              /* DOING */
    NULL,              /* DO_MORE */
    NULL,              /* DO_DONE */
    NULL,              /* PERFORM */
    NULL,              /* TOOFAST */
    NULL,              /* DONE */
    Curl_init_completed, /* COMPLETED */
    NULL               /* MSGSENT */
  };

#if defined(DEBUGBUILD) && defined(CURL_DISABLE_VERBOSE_STRINGS)
  (void) lineno;
#endif








|


|







139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
    NULL,              /* WAITPROXYCONNECT */
    NULL,              /* SENDPROTOCONNECT */
    NULL,              /* PROTOCONNECT */
    Curl_connect_free, /* DO */
    NULL,              /* DOING */
    NULL,              /* DO_MORE */
    NULL,              /* DO_DONE */
    init_perform,      /* PERFORM */
    NULL,              /* TOOFAST */
    NULL,              /* DONE */
    init_completed,    /* COMPLETED */
    NULL               /* MSGSENT */
  };

#if defined(DEBUGBUILD) && defined(CURL_DISABLE_VERBOSE_STRINGS)
  (void) lineno;
#endif

189
190
191
192
193
194
195
196
197

198
199
200
201
202
203
204
 * We add one of these structs to the sockhash for each socket
 */

struct Curl_sh_entry {
  struct Curl_hash transfers; /* hash of transfers using this socket */
  unsigned int action;  /* what combined action READ/WRITE this socket waits
                           for */
  void *socketp; /* settable by users with curl_multi_assign() */
  unsigned int users; /* number of transfers using this */

  unsigned int readers; /* this many transfers want to read */
  unsigned int writers; /* this many transfers want to write */
};
/* bits for 'action' having no bits means this socket is not expecting any
   action */
#define SH_READ  1
#define SH_WRITE 2







<

>







196
197
198
199
200
201
202

203
204
205
206
207
208
209
210
211
 * We add one of these structs to the sockhash for each socket
 */

struct Curl_sh_entry {
  struct Curl_hash transfers; /* hash of transfers using this socket */
  unsigned int action;  /* what combined action READ/WRITE this socket waits
                           for */

  unsigned int users; /* number of transfers using this */
  void *socketp; /* settable by users with curl_multi_assign() */
  unsigned int readers; /* this many transfers want to read */
  unsigned int writers; /* this many transfers want to write */
};
/* bits for 'action' having no bits means this socket is not expecting any
   action */
#define SH_READ  1
#define SH_WRITE 2
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
                                     int chashsize) /* connection hash */
{
  struct Curl_multi *multi = calloc(1, sizeof(struct Curl_multi));

  if(!multi)
    return NULL;

  multi->type = CURL_MULTI_HANDLE;

  if(Curl_mk_dnscache(&multi->hostcache))
    goto error;

  if(sh_init(&multi->sockhash, hashsize))
    goto error;








|







356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
                                     int chashsize) /* connection hash */
{
  struct Curl_multi *multi = calloc(1, sizeof(struct Curl_multi));

  if(!multi)
    return NULL;

  multi->magic = CURL_MULTI_HANDLE;

  if(Curl_mk_dnscache(&multi->hostcache))
    goto error;

  if(sh_init(&multi->sockhash, hashsize))
    goto error;

554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
  if(data->state.done)
    /* Stop if multi_done() has already been called */
    return CURLE_OK;

  conn->data = data; /* ensure the connection uses this transfer now */

  /* Stop the resolver and free its own resources (but not dns_entry yet). */
  Curl_resolver_kill(conn);

  /* Cleanup possible redirect junk */
  Curl_safefree(data->req.newurl);
  Curl_safefree(data->req.location);

  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(CURLE_ABORTED_BY_CALLBACK != result) {
    /* avoid this if we already aborted by callback to avoid this calling
       another callback */
    CURLcode rc = Curl_pgrsDone(conn);
    if(!result && rc)
      result = CURLE_ABORTED_BY_CALLBACK;
  }

  process_pending_handles(data->multi); /* connection / multiplex */

  CONNCACHE_LOCK(data);







|




















|






|







561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
  if(data->state.done)
    /* Stop if multi_done() has already been called */
    return CURLE_OK;

  conn->data = data; /* ensure the connection uses this transfer now */

  /* Stop the resolver and free its own resources (but not dns_entry yet). */
  Curl_resolver_kill(data);

  /* Cleanup possible redirect junk */
  Curl_safefree(data->req.newurl);
  Curl_safefree(data->req.location);

  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(data, status, premature);
  else
    result = status;

  if(CURLE_ABORTED_BY_CALLBACK != result) {
    /* avoid this if we already aborted by callback to avoid this calling
       another callback */
    CURLcode rc = Curl_pgrsDone(data);
    if(!result && rc)
      result = CURLE_ABORTED_BY_CALLBACK;
  }

  process_pending_handles(data->multi); /* connection / multiplex */

  CONNCACHE_LOCK(data);
686
687
688
689
690
691
692
693

694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
  }

  Curl_safefree(data->state.buffer);
  Curl_free_request_state(data);
  return result;
}

static int close_connect_only(struct connectdata *conn, void *param)

{
  struct Curl_easy *data = param;

  if(data->state.lastconnect_id != conn->connection_id)
    return 0;

  if(conn->data != data)
    return 1;
  conn->data = NULL;

  if(!conn->bits.connect_only)
    return 1;

  connclose(conn, "Removing connect-only easy handle");
  conn->bits.connect_only = FALSE;

  return 1;







|
>

<
|



<
<
<
<







693
694
695
696
697
698
699
700
701
702

703
704
705
706




707
708
709
710
711
712
713
  }

  Curl_safefree(data->state.buffer);
  Curl_free_request_state(data);
  return result;
}

static int close_connect_only(struct Curl_easy *data,
                              struct connectdata *conn, void *param)
{

  (void)param;
  if(data->state.lastconnect_id != conn->connection_id)
    return 0;





  if(!conn->bits.connect_only)
    return 1;

  connclose(conn, "Removing connect-only easy handle");
  conn->bits.connect_only = FALSE;

  return 1;
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819

  /* Remove the association between the connection and the handle */
  Curl_detach_connnection(data);

  if(data->state.lastconnect_id != -1) {
    /* Mark any connect-only connection for closure */
    Curl_conncache_foreach(data, data->state.conn_cache,
                           data, &close_connect_only);
  }

#ifdef USE_LIBPSL
  /* Remove the PSL association. */
  if(data->psl == &multi->psl)
    data->psl = NULL;
#endif







|







808
809
810
811
812
813
814
815
816
817
818
819
820
821
822

  /* Remove the association between the connection and the handle */
  Curl_detach_connnection(data);

  if(data->state.lastconnect_id != -1) {
    /* Mark any connect-only connection for closure */
    Curl_conncache_foreach(data, data->state.conn_cache,
                           NULL, close_connect_only);
  }

#ifdef USE_LIBPSL
  /* Remove the PSL association. */
  if(data->psl == &multi->psl)
    data->psl = NULL;
#endif
934
935
936
937
938
939
940
941

942
943
944
945
946
947
948
949

950
951
952
953
954
955
956
957

958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973

974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
     socket to become readable to be able to get the response headers */
  if(conn->connect_state)
    return GETSOCK_READSOCK(0);

  return GETSOCK_WRITESOCK(0);
}

static int domore_getsock(struct connectdata *conn,

                          curl_socket_t *socks)
{
  if(conn && conn->handler->domore_getsock)
    return conn->handler->domore_getsock(conn, socks);
  return GETSOCK_BLANK;
}

static int doing_getsock(struct connectdata *conn,

                         curl_socket_t *socks)
{
  if(conn && conn->handler->doing_getsock)
    return conn->handler->doing_getsock(conn, socks);
  return GETSOCK_BLANK;
}

static int protocol_getsock(struct connectdata *conn,

                            curl_socket_t *socks)
{
  if(conn->handler->proto_getsock)
    return conn->handler->proto_getsock(conn, socks);
  /* Backup getsock logic. Since there is a live socket in use, we must wait
     for it or it will be removed from watching when the multi_socket API is
     used. */
  socks[0] = conn->sock[FIRSTSOCKET];
  return GETSOCK_READSOCK(0) | GETSOCK_WRITESOCK(0);
}

/* returns bitmapped flags for this handle and its sockets. The 'socks[]'
   array contains MAX_SOCKSPEREASYHANDLE entries. */
static int multi_getsock(struct Curl_easy *data,
                         curl_socket_t *socks)
{

  /* The no connection case can happen when this is called from
     curl_multi_remove_handle() => singlesocket() => multi_getsock().
  */
  if(!data->conn)
    return 0;

  if(data->mstate > CURLM_STATE_CONNECT &&
     data->mstate < CURLM_STATE_COMPLETED) {
    /* Set up ownership correctly */
    data->conn->data = data;
  }

  switch(data->mstate) {
  default:
    return 0;

  case CURLM_STATE_WAITRESOLVE:
    return Curl_resolv_getsock(data->conn, socks);

  case CURLM_STATE_PROTOCONNECT:
  case CURLM_STATE_SENDPROTOCONNECT:
    return protocol_getsock(data->conn, socks);

  case CURLM_STATE_DO:
  case CURLM_STATE_DOING:
    return doing_getsock(data->conn, socks);

  case CURLM_STATE_WAITPROXYCONNECT:
    return waitproxyconnect_getsock(data->conn, socks);

  case CURLM_STATE_WAITCONNECT:
    return waitconnect_getsock(data->conn, socks);

  case CURLM_STATE_DO_MORE:
    return domore_getsock(data->conn, socks);

  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:
    return Curl_single_getsock(data->conn, socks);
  }

}

CURLMcode curl_multi_fdset(struct Curl_multi *multi,
                           fd_set *read_fd_set, fd_set *write_fd_set,
                           fd_set *exc_fd_set, int *max_fd)







|
>



|



|
>



|



|
>



|












>



|













|



|



|


|


|


|





|







937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
     socket to become readable to be able to get the response headers */
  if(conn->connect_state)
    return GETSOCK_READSOCK(0);

  return GETSOCK_WRITESOCK(0);
}

static int domore_getsock(struct Curl_easy *data,
                          struct connectdata *conn,
                          curl_socket_t *socks)
{
  if(conn && conn->handler->domore_getsock)
    return conn->handler->domore_getsock(data, conn, socks);
  return GETSOCK_BLANK;
}

static int doing_getsock(struct Curl_easy *data,
                         struct connectdata *conn,
                         curl_socket_t *socks)
{
  if(conn && conn->handler->doing_getsock)
    return conn->handler->doing_getsock(data, conn, socks);
  return GETSOCK_BLANK;
}

static int protocol_getsock(struct Curl_easy *data,
                            struct connectdata *conn,
                            curl_socket_t *socks)
{
  if(conn->handler->proto_getsock)
    return conn->handler->proto_getsock(data, conn, socks);
  /* Backup getsock logic. Since there is a live socket in use, we must wait
     for it or it will be removed from watching when the multi_socket API is
     used. */
  socks[0] = conn->sock[FIRSTSOCKET];
  return GETSOCK_READSOCK(0) | GETSOCK_WRITESOCK(0);
}

/* returns bitmapped flags for this handle and its sockets. The 'socks[]'
   array contains MAX_SOCKSPEREASYHANDLE entries. */
static int multi_getsock(struct Curl_easy *data,
                         curl_socket_t *socks)
{
  struct connectdata *conn = data->conn;
  /* The no connection case can happen when this is called from
     curl_multi_remove_handle() => singlesocket() => multi_getsock().
  */
  if(!conn)
    return 0;

  if(data->mstate > CURLM_STATE_CONNECT &&
     data->mstate < CURLM_STATE_COMPLETED) {
    /* Set up ownership correctly */
    data->conn->data = data;
  }

  switch(data->mstate) {
  default:
    return 0;

  case CURLM_STATE_WAITRESOLVE:
    return Curl_resolv_getsock(data, socks);

  case CURLM_STATE_PROTOCONNECT:
  case CURLM_STATE_SENDPROTOCONNECT:
    return protocol_getsock(data, conn, socks);

  case CURLM_STATE_DO:
  case CURLM_STATE_DOING:
    return doing_getsock(data, conn, socks);

  case CURLM_STATE_WAITPROXYCONNECT:
    return waitproxyconnect_getsock(conn, socks);

  case CURLM_STATE_WAITCONNECT:
    return waitconnect_getsock(conn, socks);

  case CURLM_STATE_DO_MORE:
    return domore_getsock(data, conn, socks);

  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:
    return Curl_single_getsock(data, conn, socks);
  }

}

CURLMcode curl_multi_fdset(struct Curl_multi *multi,
                           fd_set *read_fd_set, fd_set *write_fd_set,
                           fd_set *exc_fd_set, int *max_fd)
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
  *max_fd = this_max_fd;

  return CURLM_OK;
}

#define NUM_POLLS_ON_STACK 10

static CURLMcode Curl_multi_wait(struct Curl_multi *multi,
                                 struct curl_waitfd extra_fds[],
                                 unsigned int extra_nfds,
                                 int timeout_ms,
                                 int *ret,
                                 bool extrawait, /* when no socket, wait */
                                 bool use_wakeup)
{
  struct Curl_easy *data;
  curl_socket_t sockbunch[MAX_SOCKSPEREASYHANDLE];
  int bitmap;
  unsigned int i;
  unsigned int nfds = 0;
  unsigned int curlfds;







|
|
|
|
|
|
|







1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
  *max_fd = this_max_fd;

  return CURLM_OK;
}

#define NUM_POLLS_ON_STACK 10

static CURLMcode multi_wait(struct Curl_multi *multi,
                            struct curl_waitfd extra_fds[],
                            unsigned int extra_nfds,
                            int timeout_ms,
                            int *ret,
                            bool extrawait, /* when no socket, wait */
                            bool use_wakeup)
{
  struct Curl_easy *data;
  curl_socket_t sockbunch[MAX_SOCKSPEREASYHANDLE];
  int bitmap;
  unsigned int i;
  unsigned int nfds = 0;
  unsigned int curlfds;
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302

CURLMcode curl_multi_wait(struct Curl_multi *multi,
                          struct curl_waitfd extra_fds[],
                          unsigned int extra_nfds,
                          int timeout_ms,
                          int *ret)
{
  return Curl_multi_wait(multi, extra_fds, extra_nfds, timeout_ms, ret, FALSE,
                         FALSE);
}

CURLMcode curl_multi_poll(struct Curl_multi *multi,
                          struct curl_waitfd extra_fds[],
                          unsigned int extra_nfds,
                          int timeout_ms,
                          int *ret)
{
  return Curl_multi_wait(multi, extra_fds, extra_nfds, timeout_ms, ret, TRUE,
                         TRUE);
}

CURLMcode curl_multi_wakeup(struct Curl_multi *multi)
{
  /* this function is usually called from another thread,
     it has to be careful only to access parts of the
     Curl_multi struct that are constant */







|
|








|
|







1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309

CURLMcode curl_multi_wait(struct Curl_multi *multi,
                          struct curl_waitfd extra_fds[],
                          unsigned int extra_nfds,
                          int timeout_ms,
                          int *ret)
{
  return multi_wait(multi, extra_fds, extra_nfds, timeout_ms, ret, FALSE,
                    FALSE);
}

CURLMcode curl_multi_poll(struct Curl_multi *multi,
                          struct curl_waitfd extra_fds[],
                          unsigned int extra_nfds,
                          int timeout_ms,
                          int *ret)
{
  return multi_wait(multi, extra_fds, extra_nfds, timeout_ms, ret, TRUE,
                    TRUE);
}

CURLMcode curl_multi_wakeup(struct Curl_multi *multi)
{
  /* this function is usually called from another thread,
     it has to be careful only to access parts of the
     Curl_multi struct that are constant */
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
    while(1) {
      /* swrite() is not thread-safe in general, because concurrent calls
         can have their messages interleaved, but in this case the content
         of the messages does not matter, which makes it ok to call.

         The write socket is set to non-blocking, this way this function
         cannot block, making it safe to call even from the same thread
         that will call Curl_multi_wait(). If swrite() returns that it
         would block, it's considered successful because it means that
         previous calls to this function will wake up the poll(). */
      if(swrite(multi->wakeup_pair[1], buf, sizeof(buf)) < 0) {
        int err = SOCKERRNO;
        int return_success;
#ifdef USE_WINSOCK
        return_success = WSAEWOULDBLOCK == err;







|







1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
    while(1) {
      /* swrite() is not thread-safe in general, because concurrent calls
         can have their messages interleaved, but in this case the content
         of the messages does not matter, which makes it ok to call.

         The write socket is set to non-blocking, this way this function
         cannot block, making it safe to call even from the same thread
         that will call curl_multi_wait(). If swrite() returns that it
         would block, it's considered successful because it means that
         previous calls to this function will wake up the poll(). */
      if(swrite(multi->wakeup_pair[1], buf, sizeof(buf)) < 0) {
        int err = SOCKERRNO;
        int return_success;
#ifdef USE_WINSOCK
        return_success = WSAEWOULDBLOCK == err;
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429

1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452

1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471

1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
    multistate(data, CURLM_STATE_PERFORM);
    Curl_attach_connnection(data, conn);
    k->keepon |= KEEP_RECV; /* setup to receive! */
  }
  return rc;
}

/*
 * 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.
 */
static void do_complete(struct connectdata *conn)
{
  conn->data->req.chunk = FALSE;
  Curl_pgrsTime(conn->data, TIMER_PRETRANSFER);
}

static CURLcode multi_do(struct Curl_easy *data, bool *done)
{
  CURLcode result = CURLE_OK;
  struct connectdata *conn = data->conn;

  DEBUGASSERT(conn);
  DEBUGASSERT(conn->handler);
  DEBUGASSERT(conn->data == data);

  if(conn->handler->do_it) {
    /* generic protocol-specific function pointer set in curl_connect() */
    result = conn->handler->do_it(conn, done);

    if(!result && *done)
      /* do_complete must be called after the protocol-specific DO function */
      do_complete(conn);
  }
  return result;
}

/*
 * multi_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.
 *
 * 'complete' can return 0 for incomplete, 1 for done and -1 for go back to
 * DOING state there's more work to do!
 */

static CURLcode multi_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;
}

/*
 * 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.
 */

static CURLcode 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.
 */

static CURLcode 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.
 *
 */
static CURLcode protocol_connect(struct connectdata *conn,
                                 bool *protocol_done)
{
  CURLcode result = CURLE_OK;

  DEBUGASSERT(conn);
  DEBUGASSERT(protocol_done);

  *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) {
#ifndef CURL_DISABLE_PROXY
    result = Curl_proxy_connect(conn, FIRSTSOCKET);
    if(result)
      return result;

    if(CONNECT_FIRSTSOCKET_PROXY_SSL())
      /* wait for HTTPS proxy SSL initialization to complete */
      return CURLE_OK;

    if(conn->bits.tunnel_proxy && conn->bits.httpproxy &&
       Curl_connect_ongoing(conn))
      /* 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;
#endif
    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)







<
<
<
<
<
<
<
<
<
<
<
<









|

|

<
<
<
<












|


>




|
<
<
<
<










|
<


>



|












|


>



|












|



|




















|

















|







1386
1387
1388
1389
1390
1391
1392












1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405




1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426




1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437

1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
    multistate(data, CURLM_STATE_PERFORM);
    Curl_attach_connnection(data, conn);
    k->keepon |= KEEP_RECV; /* setup to receive! */
  }
  return rc;
}













static CURLcode multi_do(struct Curl_easy *data, bool *done)
{
  CURLcode result = CURLE_OK;
  struct connectdata *conn = data->conn;

  DEBUGASSERT(conn);
  DEBUGASSERT(conn->handler);
  DEBUGASSERT(conn->data == data);

  if(conn->handler->do_it)
    /* generic protocol-specific function pointer set in curl_connect() */
    result = conn->handler->do_it(data, done);





  return result;
}

/*
 * multi_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.
 *
 * 'complete' can return 0 for incomplete, 1 for done and -1 for go back to
 * DOING state there's more work to do!
 */

static CURLcode multi_do_more(struct Curl_easy *data, int *complete)
{
  CURLcode result = CURLE_OK;
  struct connectdata *conn = data->conn;

  *complete = 0;

  if(conn->handler->do_more)
    result = conn->handler->do_more(data, complete);





  return result;
}

/*
 * 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.
 */

static CURLcode protocol_connecting(struct Curl_easy *data, bool *done)

{
  CURLcode result = CURLE_OK;
  struct connectdata *conn = data->conn;

  if(conn && conn->handler->connecting) {
    *done = FALSE;
    result = conn->handler->connecting(data, 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.
 */

static CURLcode protocol_doing(struct Curl_easy *data, bool *done)
{
  CURLcode result = CURLE_OK;
  struct connectdata *conn = data->conn;

  if(conn && conn->handler->doing) {
    *done = FALSE;
    result = conn->handler->doing(data, done);
  }
  else
    *done = TRUE;

  return result;
}

/*
 * We have discovered that the TCP connection has been successful, we can now
 * proceed with some action.
 *
 */
static CURLcode protocol_connect(struct Curl_easy *data,
                                 bool *protocol_done)
{
  CURLcode result = CURLE_OK;
  struct connectdata *conn = data->conn;
  DEBUGASSERT(conn);
  DEBUGASSERT(protocol_done);

  *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) {
#ifndef CURL_DISABLE_PROXY
    result = Curl_proxy_connect(data, FIRSTSOCKET);
    if(result)
      return result;

    if(CONNECT_FIRSTSOCKET_PROXY_SSL())
      /* wait for HTTPS proxy SSL initialization to complete */
      return CURLE_OK;

    if(conn->bits.tunnel_proxy && conn->bits.httpproxy &&
       Curl_connect_ongoing(conn))
      /* 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;
#endif
    if(conn->handler->connect_it) {
      /* is there a protocol-specific connect() procedure? */

      /* Call the protocol-specific connect function */
      result = conn->handler->connect_it(data, protocol_done);
    }
    else
      *protocol_done = TRUE;

    /* it has started, possibly even completed but that knowledge isn't stored
       in this bit! */
    if(!result)
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594



1595
1596
1597
1598
1599
1600
1601
    rc = CURLM_OK;

    if(multi_ischanged(multi, TRUE)) {
      DEBUGF(infof(data, "multi changed, check CONNECT_PEND queue!\n"));
      process_pending_handles(multi); /* multiplexed */
    }

    if(data->conn && data->mstate > CURLM_STATE_CONNECT &&
       data->mstate < CURLM_STATE_COMPLETED) {
      /* Make sure we set the connection's current owner */



      data->conn->data = data;
    }

    if(data->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







|


>
>
>







1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
    rc = CURLM_OK;

    if(multi_ischanged(multi, TRUE)) {
      DEBUGF(infof(data, "multi changed, check CONNECT_PEND queue!\n"));
      process_pending_handles(multi); /* multiplexed */
    }

    if(data->mstate > CURLM_STATE_CONNECT &&
       data->mstate < CURLM_STATE_COMPLETED) {
      /* Make sure we set the connection's current owner */
      DEBUGASSERT(data->conn);
      if(!data->conn)
        return CURLM_INTERNAL_ERROR;
      data->conn->data = data;
    }

    if(data->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
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
#endif
        if(conn->bits.conn_to_host)
        hostname = conn->conn_to_host.name;
      else
        hostname = conn->host.name;

      /* check if we have the name resolved by now */
      dns = Curl_fetch_addr(conn, hostname, (int)conn->port);

      if(dns) {
#ifdef CURLRES_ASYNCH
        conn->async.dns = dns;
        conn->async.done = TRUE;
#endif
        result = CURLE_OK;
        infof(data, "Hostname '%s' was found in DNS cache\n", hostname);
      }

      if(!dns)
        result = Curl_resolv_check(data->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_once_resolved(data->conn, &protocol_connected);

        if(result)
          /* if Curl_once_resolved() returns failure, the connection struct
             is already freed and gone */
          data->conn = NULL; /* no more connection */
        else {
          /* call again please so that we get the next socket setup */







|



|
|






|












|







1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
#endif
        if(conn->bits.conn_to_host)
        hostname = conn->conn_to_host.name;
      else
        hostname = conn->host.name;

      /* check if we have the name resolved by now */
      dns = Curl_fetch_addr(data, hostname, (int)conn->port);

      if(dns) {
#ifdef CURLRES_ASYNCH
        data->state.async.dns = dns;
        data->state.async.done = TRUE;
#endif
        result = CURLE_OK;
        infof(data, "Hostname '%s' was found in DNS cache\n", hostname);
      }

      if(!dns)
        result = Curl_resolv_check(data, &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_once_resolved(data, &protocol_connected);

        if(result)
          /* if Curl_once_resolved() returns failure, the connection struct
             is already freed and gone */
          data->conn = NULL; /* no more connection */
        else {
          /* call again please so that we get the next socket setup */
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
    }
    break;

#ifndef CURL_DISABLE_HTTP
    case CURLM_STATE_WAITPROXYCONNECT:
      /* this is HTTP-specific, but sending CONNECT to a proxy is HTTP... */
      DEBUGASSERT(data->conn);
      result = Curl_http_connect(data->conn, &protocol_connected);
#ifndef CURL_DISABLE_PROXY
      if(data->conn->bits.proxy_connect_closed) {
        rc = CURLM_CALL_MULTI_PERFORM;
        /* connect back to proxy again */
        result = CURLE_OK;
        multi_done(data, CURLE_OK, FALSE);
        multistate(data, CURLM_STATE_CONNECT);







|







1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
    }
    break;

#ifndef CURL_DISABLE_HTTP
    case CURLM_STATE_WAITPROXYCONNECT:
      /* this is HTTP-specific, but sending CONNECT to a proxy is HTTP... */
      DEBUGASSERT(data->conn);
      result = Curl_http_connect(data, &protocol_connected);
#ifndef CURL_DISABLE_PROXY
      if(data->conn->bits.proxy_connect_closed) {
        rc = CURLM_CALL_MULTI_PERFORM;
        /* connect back to proxy again */
        result = CURLE_OK;
        multi_done(data, CURLE_OK, FALSE);
        multistate(data, CURLM_STATE_CONNECT);
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
        stream_error = TRUE;
      break;
#endif

    case CURLM_STATE_WAITCONNECT:
      /* awaiting a completion of an asynch TCP connect */
      DEBUGASSERT(data->conn);
      result = Curl_is_connected(data->conn, FIRSTSOCKET, &connected);
      if(connected && !result) {
#ifndef CURL_DISABLE_HTTP
        if(
#ifndef CURL_DISABLE_PROXY
          (data->conn->http_proxy.proxytype == CURLPROXY_HTTPS &&
           !data->conn->bits.proxy_ssl_connected[FIRSTSOCKET]) ||
#endif







|







1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
        stream_error = TRUE;
      break;
#endif

    case CURLM_STATE_WAITCONNECT:
      /* awaiting a completion of an asynch TCP connect */
      DEBUGASSERT(data->conn);
      result = Curl_is_connected(data, data->conn, FIRSTSOCKET, &connected);
      if(connected && !result) {
#ifndef CURL_DISABLE_HTTP
        if(
#ifndef CURL_DISABLE_PROXY
          (data->conn->http_proxy.proxytype == CURLPROXY_HTTPS &&
           !data->conn->bits.proxy_ssl_connected[FIRSTSOCKET]) ||
#endif
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
        multi_done(data, result, TRUE);
        stream_error = TRUE;
        break;
      }
      break;

    case CURLM_STATE_SENDPROTOCONNECT:
      result = protocol_connect(data->conn, &protocol_connected);
      if(!result && !protocol_connected)
        /* switch to waiting state */
        multistate(data, CURLM_STATE_PROTOCONNECT);
      else if(!result) {
        /* protocol connect has completed, go WAITDO or DO */
        multistate(data, CURLM_STATE_DO);
        rc = CURLM_CALL_MULTI_PERFORM;
      }
      else {
        /* failure detected */
        Curl_posttransfer(data);
        multi_done(data, result, TRUE);
        stream_error = TRUE;
      }
      break;

    case CURLM_STATE_PROTOCONNECT:
      /* protocol-specific connect phase */
      result = protocol_connecting(data->conn, &protocol_connected);
      if(!result && protocol_connected) {
        /* after the connect has completed, go WAITDO or DO */
        multistate(data, CURLM_STATE_DO);
        rc = CURLM_CALL_MULTI_PERFORM;
      }
      else if(result) {
        /* failure detected */







|


















|







1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
        multi_done(data, result, TRUE);
        stream_error = TRUE;
        break;
      }
      break;

    case CURLM_STATE_SENDPROTOCONNECT:
      result = protocol_connect(data, &protocol_connected);
      if(!result && !protocol_connected)
        /* switch to waiting state */
        multistate(data, CURLM_STATE_PROTOCONNECT);
      else if(!result) {
        /* protocol connect has completed, go WAITDO or DO */
        multistate(data, CURLM_STATE_DO);
        rc = CURLM_CALL_MULTI_PERFORM;
      }
      else {
        /* failure detected */
        Curl_posttransfer(data);
        multi_done(data, result, TRUE);
        stream_error = TRUE;
      }
      break;

    case CURLM_STATE_PROTOCONNECT:
      /* protocol-specific connect phase */
      result = protocol_connecting(data, &protocol_connected);
      if(!result && protocol_connected) {
        /* after the connect has completed, go WAITDO or DO */
        multistate(data, CURLM_STATE_DO);
        rc = CURLM_CALL_MULTI_PERFORM;
      }
      else if(result) {
        /* failure detected */
1912
1913
1914
1915
1916
1917
1918


1919

1920
1921
1922
1923
1924
1925
1926
#ifndef CURL_DISABLE_FTP
            /* some steps needed for wildcard matching */
            if(data->state.wildcardmatch) {
              struct WildcardData *wc = &data->wildcard;
              if(wc->state == CURLWC_DONE || wc->state == CURLWC_SKIP) {
                /* skip some states if it is important */
                multi_done(data, CURLE_OK, FALSE);


                multistate(data, CURLM_STATE_DONE);

                rc = CURLM_CALL_MULTI_PERFORM;
                break;
              }
            }
#endif
            /* DO was not completed in one function call, we must continue
               DOING... */







>
>
|
>







1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
#ifndef CURL_DISABLE_FTP
            /* some steps needed for wildcard matching */
            if(data->state.wildcardmatch) {
              struct WildcardData *wc = &data->wildcard;
              if(wc->state == CURLWC_DONE || wc->state == CURLWC_SKIP) {
                /* skip some states if it is important */
                multi_done(data, CURLE_OK, FALSE);

                /* if there's no connection left, skip the DONE state */
                multistate(data, data->conn ?
                           CURLM_STATE_DONE : CURLM_STATE_COMPLETED);
                rc = CURLM_CALL_MULTI_PERFORM;
                break;
              }
            }
#endif
            /* DO was not completed in one function call, we must continue
               DOING... */
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
           * 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;

          drc = Curl_retry_request(data->conn, &newurl);
          if(drc) {
            /* a failure here pretty much implies an out of memory */
            result = drc;
            stream_error = TRUE;
          }

          Curl_posttransfer(data);







|







1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
           * 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;

          drc = Curl_retry_request(data, &newurl);
          if(drc) {
            /* a failure here pretty much implies an out of memory */
            result = drc;
            stream_error = TRUE;
          }

          Curl_posttransfer(data);
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
        }
      }
      break;

    case CURLM_STATE_DOING:
      /* we continue DOING until the DO phase is complete */
      DEBUGASSERT(data->conn);
      result = protocol_doing(data->conn, &dophase_done);
      if(!result) {
        if(dophase_done) {
          /* after DO, go DO_DONE or DO_MORE */
          multistate(data, data->conn->bits.do_more?
                     CURLM_STATE_DO_MORE:
                     CURLM_STATE_DO_DONE);
          rc = CURLM_CALL_MULTI_PERFORM;







|







1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
        }
      }
      break;

    case CURLM_STATE_DOING:
      /* we continue DOING until the DO phase is complete */
      DEBUGASSERT(data->conn);
      result = protocol_doing(data, &dophase_done);
      if(!result) {
        if(dophase_done) {
          /* after DO, go DO_DONE or DO_MORE */
          multistate(data, data->conn->bits.do_more?
                     CURLM_STATE_DO_MORE:
                     CURLM_STATE_DO_DONE);
          rc = CURLM_CALL_MULTI_PERFORM;
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
      break;

    case CURLM_STATE_DO_MORE:
      /*
       * When we are connected, DO MORE and then go DO_DONE
       */
      DEBUGASSERT(data->conn);
      result = multi_do_more(data->conn, &control);

      if(!result) {
        if(control) {
          /* if positive, advance to DO_DONE
             if negative, go back to DOING */
          multistate(data, control == 1?
                     CURLM_STATE_DO_DONE:







|







2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
      break;

    case CURLM_STATE_DO_MORE:
      /*
       * When we are connected, DO MORE and then go DO_DONE
       */
      DEBUGASSERT(data->conn);
      result = multi_do_more(data, &control);

      if(!result) {
        if(control) {
          /* if positive, advance to DO_DONE
             if negative, go back to DOING */
          multistate(data, control == 1?
                     CURLM_STATE_DO_DONE:
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082








2083
2084
2085
2086
2087
2088
2089
      }
      rc = CURLM_CALL_MULTI_PERFORM;
      break;

    case CURLM_STATE_TOOFAST: /* limit-rate exceeded in either direction */
      DEBUGASSERT(data->conn);
      /* if both rates are within spec, resume transfer */
      if(Curl_pgrsUpdate(data->conn))
        result = CURLE_ABORTED_BY_CALLBACK;
      else
        result = Curl_speedcheck(data, *nowp);

      if(!result) {








        send_timeout_ms = 0;
        if(data->set.max_send_speed > 0)
          send_timeout_ms =
            Curl_pgrsLimitWaitTime(data->progress.uploaded,
                                   data->progress.ul_limit_size,
                                   data->set.max_send_speed,
                                   data->progress.ul_limit_start,







|




|
>
>
>
>
>
>
>
>







2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
      }
      rc = CURLM_CALL_MULTI_PERFORM;
      break;

    case CURLM_STATE_TOOFAST: /* limit-rate exceeded in either direction */
      DEBUGASSERT(data->conn);
      /* if both rates are within spec, resume transfer */
      if(Curl_pgrsUpdate(data))
        result = CURLE_ABORTED_BY_CALLBACK;
      else
        result = Curl_speedcheck(data, *nowp);

      if(result) {
        if(!(data->conn->handler->flags & PROTOPT_DUAL) &&
           result != CURLE_HTTP2_STREAM)
          streamclose(data->conn, "Transfer returned error");

        Curl_posttransfer(data);
        multi_done(data, result, TRUE);
      }
      else {
        send_timeout_ms = 0;
        if(data->set.max_send_speed > 0)
          send_timeout_ms =
            Curl_pgrsLimitWaitTime(data->progress.uploaded,
                                   data->progress.ul_limit_size,
                                   data->set.max_send_speed,
                                   data->progress.ul_limit_start,
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
      result = Curl_readwrite(data->conn, data, &done, &comeback);

      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->conn, &newurl);
        if(!ret)
          retry = (newurl)?TRUE:FALSE;
        else if(!result)
          result = ret;

        if(retry) {
          /* if we are to retry, set the result to OK and consider the
             request as done */
          result = CURLE_OK;
          done = TRUE;
        }
      }
      else if((CURLE_HTTP2_STREAM == result) &&
              Curl_h2_http_1_1_error(data->conn)) {
        CURLcode ret = Curl_retry_request(data->conn, &newurl);

        if(!ret) {
          infof(data, "Downgrades to HTTP/1.1!\n");
          data->set.httpversion = CURL_HTTP_VERSION_1_1;
          /* clear the error message bit too as we ignore the one we got */
          data->state.errorbuf = FALSE;
          if(!newurl)







|














|







2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
      result = Curl_readwrite(data->conn, data, &done, &comeback);

      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, &newurl);
        if(!ret)
          retry = (newurl)?TRUE:FALSE;
        else if(!result)
          result = ret;

        if(retry) {
          /* if we are to retry, set the result to OK and consider the
             request as done */
          result = CURLE_OK;
          done = TRUE;
        }
      }
      else if((CURLE_HTTP2_STREAM == result) &&
              Curl_h2_http_1_1_error(data->conn)) {
        CURLcode ret = Curl_retry_request(data, &newurl);

        if(!ret) {
          infof(data, "Downgrades to HTTP/1.1!\n");
          data->set.httpversion = CURL_HTTP_VERSION_1_1;
          /* clear the error message bit too as we ignore the one we got */
          data->state.errorbuf = FALSE;
          if(!newurl)
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213

2214
2215
2216
2217
2218
2219
2220
           result != CURLE_HTTP2_STREAM)
          streamclose(data->conn, "Transfer returned error");

        Curl_posttransfer(data);
        multi_done(data, result, TRUE);
      }
      else if(done) {
        followtype follow = FOLLOW_NONE;

        /* call this even if the readwrite function returned error */
        Curl_posttransfer(data);

        /* 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;







<







>







2202
2203
2204
2205
2206
2207
2208

2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
           result != CURLE_HTTP2_STREAM)
          streamclose(data->conn, "Transfer returned error");

        Curl_posttransfer(data);
        multi_done(data, result, TRUE);
      }
      else if(done) {


        /* call this even if the readwrite function returned error */
        Curl_posttransfer(data);

        /* 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) {
          followtype follow = FOLLOW_NONE;
          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;
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297

        /* post-transfer command */
        res = multi_done(data, result, FALSE);

        /* allow a previously set error code take precedence */
        if(!result)
          result = res;

        /*
         * If there are other handles on the connection, multi_done won't set
         * 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
         */
        Curl_detach_connnection(data);
      }

#ifndef CURL_DISABLE_FTP
      if(data->state.wildcardmatch) {
        if(data->wildcard.state != CURLWC_DONE) {
          /* if a wildcard is set and we are not ending -> lets start again
             with CURLM_STATE_INIT */







<
<
<
<
<
<
<
<







2279
2280
2281
2282
2283
2284
2285








2286
2287
2288
2289
2290
2291
2292

        /* post-transfer command */
        res = multi_done(data, result, FALSE);

        /* allow a previously set error code take precedence */
        if(!result)
          result = res;








      }

#ifndef CURL_DISABLE_FTP
      if(data->state.wildcardmatch) {
        if(data->wildcard.state != CURLWC_DONE) {
          /* if a wildcard is set and we are not ending -> lets start again
             with CURLM_STATE_INIT */
2353
2354
2355
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
          (void)Curl_posttransfer(data);
        }

        multistate(data, CURLM_STATE_COMPLETED);
        rc = CURLM_CALL_MULTI_PERFORM;
      }
      /* if there's still a connection to use, call the progress function */
      else if(data->conn && Curl_pgrsUpdate(data->conn)) {
        /* aborted due to progress callback return code must close the
           connection */
        result = CURLE_ABORTED_BY_CALLBACK;
        streamclose(data->conn, "Aborted by callback");

        /* if not yet in DONE state, go there, otherwise COMPLETED */
        multistate(data, (data->mstate < CURLM_STATE_DONE)?







|







2348
2349
2350
2351
2352
2353
2354
2355
2356
2357
2358
2359
2360
2361
2362
          (void)Curl_posttransfer(data);
        }

        multistate(data, CURLM_STATE_COMPLETED);
        rc = CURLM_CALL_MULTI_PERFORM;
      }
      /* if there's still a connection to use, call the progress function */
      else if(data->conn && Curl_pgrsUpdate(data)) {
        /* aborted due to progress callback return code must close the
           connection */
        result = CURLE_ABORTED_BY_CALLBACK;
        streamclose(data->conn, "Aborted by callback");

        /* if not yet in DONE state, go there, otherwise COMPLETED */
        multistate(data, (data->mstate < CURLM_STATE_DONE)?
2454
2455
2456
2457
2458
2459
2460
2461
2462
2463
2464
2465
2466
2467
2468
  struct Curl_easy *data;
  struct Curl_easy *nextdata;

  if(GOOD_MULTI_HANDLE(multi)) {
    if(multi->in_callback)
      return CURLM_RECURSIVE_API_CALL;

    multi->type = 0; /* not good anymore */

    /* Firsrt remove all remaining easy handles */
    data = multi->easyp;
    while(data) {
      nextdata = data->next;
      if(!data->state.done && data->conn)
        /* if DONE was never called for this handle */







|







2449
2450
2451
2452
2453
2454
2455
2456
2457
2458
2459
2460
2461
2462
2463
  struct Curl_easy *data;
  struct Curl_easy *nextdata;

  if(GOOD_MULTI_HANDLE(multi)) {
    if(multi->in_callback)
      return CURLM_RECURSIVE_API_CALL;

    multi->magic = 0; /* not good anymore */

    /* Firsrt remove all remaining easy handles */
    data = multi->easyp;
    while(data) {
      nextdata = data->next;
      if(!data->state.done && data->conn)
        /* if DONE was never called for this handle */
3325
3326
3327
3328
3329
3330
3331
3332
3333
3334

3335
3336

3337
3338
3339
3340
3341
3342
3343
3344
3345
3346
3347
3348
  return multi ? multi->max_total_connections : 0;
}

/*
 * When information about a connection has appeared, call this!
 */

void Curl_multiuse_state(struct connectdata *conn,
                         int bundlestate) /* use BUNDLE_* defines */
{

  DEBUGASSERT(conn);
  DEBUGASSERT(conn->bundle);

  DEBUGASSERT(conn->data);
  DEBUGASSERT(conn->data->multi);

  conn->bundle->multiuse = bundlestate;
  process_pending_handles(conn->data->multi);
}

static void process_pending_handles(struct Curl_multi *multi)
{
  struct Curl_llist_element *e = multi->pending.head;
  if(e) {
    struct Curl_easy *data = e->ptr;







|


>
|
|
>
|
|


|







3320
3321
3322
3323
3324
3325
3326
3327
3328
3329
3330
3331
3332
3333
3334
3335
3336
3337
3338
3339
3340
3341
3342
3343
3344
3345
  return multi ? multi->max_total_connections : 0;
}

/*
 * When information about a connection has appeared, call this!
 */

void Curl_multiuse_state(struct Curl_easy *data,
                         int bundlestate) /* use BUNDLE_* defines */
{
  struct connectdata *conn;
  DEBUGASSERT(data);
  DEBUGASSERT(data->multi);
  conn = data->conn;
  DEBUGASSERT(conn);
  DEBUGASSERT(conn->bundle);

  conn->bundle->multiuse = bundlestate;
  process_pending_handles(data->multi);
}

static void process_pending_handles(struct Curl_multi *multi)
{
  struct Curl_llist_element *e = multi->pending.head;
  if(e) {
    struct Curl_easy *data = e->ptr;
Changes to jni/curl/lib/multihandle.h.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24


25
26
27


28
29
30
31
32
33
34
#ifndef HEADER_CURL_MULTIHANDLE_H
#define HEADER_CURL_MULTIHANDLE_H
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2020, 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 https://curl.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 "conncache.h"
#include "psl.h"
#include "socketpair.h"



struct Curl_message {
  struct Curl_llist_element list;
  /* the 'CURLMsg' is the part that is visible to the external user */
  struct CURLMsg extmsg;
};










|














>
>



>
>







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
#ifndef HEADER_CURL_MULTIHANDLE_H
#define HEADER_CURL_MULTIHANDLE_H
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2021, 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 https://curl.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 "llist.h"
#include "hash.h"
#include "conncache.h"
#include "psl.h"
#include "socketpair.h"

struct connectdata;

struct Curl_message {
  struct Curl_llist_element list;
  /* the 'CURLMsg' is the part that is visible to the external user */
  struct CURLMsg extmsg;
};

75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
/* value for MAXIMUM CONCURRENT STREAMS upper limit */
#define INITIAL_MAX_CONCURRENT_STREAMS ((1U << 31) - 1)

/* 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 list with easy handles */
  struct Curl_easy *easyp;
  struct Curl_easy *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







|







79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
/* value for MAXIMUM CONCURRENT STREAMS upper limit */
#define INITIAL_MAX_CONCURRENT_STREAMS ((1U << 31) - 1)

/* 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. */
  unsigned int magic;

  /* We have a doubly-linked list with easy handles */
  struct Curl_easy *easyp;
  struct Curl_easy *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
Changes to jni/curl/lib/multiif.h.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#ifndef HEADER_CURL_MULTIIF_H
#define HEADER_CURL_MULTIIF_H
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2020, 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 https://curl.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









|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#ifndef HEADER_CURL_MULTIIF_H
#define HEADER_CURL_MULTIIF_H
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2021, 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 https://curl.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
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79

/* Return the value of the CURLMOPT_MAX_HOST_CONNECTIONS option */
size_t Curl_multi_max_host_connections(struct Curl_multi *multi);

/* Return the value of the CURLMOPT_MAX_TOTAL_CONNECTIONS option */
size_t Curl_multi_max_total_connections(struct Curl_multi *multi);

void Curl_multiuse_state(struct connectdata *conn,
                         int bundlestate); /* use BUNDLE_* defines */

/*
 * 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







|







65
66
67
68
69
70
71
72
73
74
75
76
77
78
79

/* Return the value of the CURLMOPT_MAX_HOST_CONNECTIONS option */
size_t Curl_multi_max_host_connections(struct Curl_multi *multi);

/* Return the value of the CURLMOPT_MAX_TOTAL_CONNECTIONS option */
size_t Curl_multi_max_total_connections(struct Curl_multi *multi);

void Curl_multiuse_state(struct Curl_easy *data,
                         int bundlestate); /* use BUNDLE_* defines */

/*
 * 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
Changes to jni/curl/lib/openldap.c.
1
2
3
4
5
6
7

8
9
10
11
12
13
14
15
16
/***************************************************************************
 *                      _   _ ____  _
 *  Project         ___| | | |  _ \| |
 *                 / __| | | | |_) | |
 *                | (__| |_| |  _ <| |___
 *                 \___|\___/|_| \_\_____|
 *

 * Copyright (C) 2010, Howard Chu, <hyc@openldap.org>
 * Copyright (C) 2011 - 2020, 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 https://curl.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







>

<







1
2
3
4
5
6
7
8
9

10
11
12
13
14
15
16
/***************************************************************************
 *                      _   _ ____  _
 *  Project         ___| | | |  _ \| |
 *                 / __| | | | |_) | |
 *                | (__| |_| |  _ <| |___
 *                 \___|\___/|_| \_\_____|
 *
 * Copyright (C) 2011 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
 * Copyright (C) 2010, Howard Chu, <hyc@openldap.org>

 *
 * 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 https://curl.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
72
73
74
75
76
77
78
79

80
81
82
83
84

85
86
87
88
89
90
91

#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.
 */








|
>
|
|
|
|
|
>







72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93

#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 Curl_easy *data,
                                      struct connectdata *conn);
static CURLcode ldap_do(struct Curl_easy *data, bool *done);
static CURLcode ldap_done(struct Curl_easy *data, CURLcode, bool);
static CURLcode ldap_connect(struct Curl_easy *data, bool *done);
static CURLcode ldap_connecting(struct Curl_easy *data, bool *done);
static CURLcode ldap_disconnect(struct Curl_easy *data,
                                struct connectdata *conn, bool dead);

static Curl_recv ldap_recv;

/*
 * LDAP protocol handler.
 */

165
166
167
168
169
170
171
172

173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209

210
211
212
213
214
215
216
217
218
};

struct ldapreqinfo {
  int msgid;
  int nument;
};

static CURLcode ldap_setup_connection(struct connectdata *conn)

{
  struct ldapconninfo *li;
  LDAPURLDesc *lud;
  struct Curl_easy *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(struct ldapconninfo));
  if(!li)
    return CURLE_OUT_OF_MEMORY;
  li->proto = proto;
  conn->proto.ldapc = li;
  connkeep(conn, "OpenLDAP default");
  return CURLE_OK;
}

#ifdef USE_SSL
static Sockbuf_IO ldapsb_tls;
#endif

static CURLcode ldap_connect(struct connectdata *conn, bool *done)
{

  struct ldapconninfo *li = conn->proto.ldapc;
  struct Curl_easy *data = conn->data;
  int rc, proto = LDAP_VERSION3;
  char hosturl[1024];
  char *ptr;

  (void)done;

  strcpy(hosturl, "ldap");







|
>



<












|


















|

>

<







167
168
169
170
171
172
173
174
175
176
177
178

179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213

214
215
216
217
218
219
220
};

struct ldapreqinfo {
  int msgid;
  int nument;
};

static CURLcode ldap_setup_connection(struct Curl_easy *data,
                                      struct connectdata *conn)
{
  struct ldapconninfo *li;
  LDAPURLDesc *lud;

  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(data, "LDAP local: %s", msg);
    return status;
  }
  proto = ldap_pvt_url_scheme2proto(lud->lud_scheme);
  ldap_free_urldesc(lud);

  li = calloc(1, sizeof(struct ldapconninfo));
  if(!li)
    return CURLE_OUT_OF_MEMORY;
  li->proto = proto;
  conn->proto.ldapc = li;
  connkeep(conn, "OpenLDAP default");
  return CURLE_OK;
}

#ifdef USE_SSL
static Sockbuf_IO ldapsb_tls;
#endif

static CURLcode ldap_connect(struct Curl_easy *data, bool *done)
{
  struct connectdata *conn = data->conn;
  struct ldapconninfo *li = conn->proto.ldapc;

  int rc, proto = LDAP_VERSION3;
  char hosturl[1024];
  char *ptr;

  (void)done;

  strcpy(hosturl, "ldap");
239
240
241
242
243
244
245
246

247
248
249
250
251
252
253
254
255
256

257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
  }

  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)
{

  struct ldapconninfo *li = conn->proto.ldapc;
  struct Curl_easy *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) {







|
>








|

>

<









|







241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261

262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
  }

  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(data, conn,
                                          FIRSTSOCKET, &li->ssldone);
    if(result)
      return result;
  }
#endif

  return CURLE_OK;
}

static CURLcode ldap_connecting(struct Curl_easy *data, bool *done)
{
  struct connectdata *conn = data->conn;
  struct ldapconninfo *li = conn->proto.ldapc;

  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(data, conn, FIRSTSOCKET,
                                                     &li->ssldone);
      if(result || !li->ssldone)
        return result;
    }

    /* Have we installed the libcurl SSL handlers into the sockbuf yet? */
    if(!li->sslinst) {
353
354
355
356
357
358
359
360

361
362
363

364
365
366
367
368
369
370
371
372
373
374
375
376
377

378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
    ldap_memfree(info);
  conn->recv[FIRSTSOCKET] = ldap_recv;
  *done = TRUE;

  return CURLE_OK;
}

static CURLcode ldap_disconnect(struct connectdata *conn, bool dead_connection)

{
  struct ldapconninfo *li = conn->proto.ldapc;
  (void) dead_connection;


  if(li) {
    if(li->ld) {
      ldap_unbind_ext(li->ld, NULL, NULL);
      li->ld = NULL;
    }
    conn->proto.ldapc = NULL;
    free(li);
  }
  return CURLE_OK;
}

static CURLcode ldap_do(struct connectdata *conn, bool *done)
{

  struct ldapconninfo *li = conn->proto.ldapc;
  struct ldapreqinfo *lr;
  CURLcode status = CURLE_OK;
  int rc = 0;
  LDAPURLDesc *ludp = NULL;
  int msgid;
  struct Curl_easy *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);







|
>



>












|

>






<














|







356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389

390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
    ldap_memfree(info);
  conn->recv[FIRSTSOCKET] = ldap_recv;
  *done = TRUE;

  return CURLE_OK;
}

static CURLcode ldap_disconnect(struct Curl_easy *data,
                                struct connectdata *conn, bool dead_connection)
{
  struct ldapconninfo *li = conn->proto.ldapc;
  (void) dead_connection;
  (void) data;

  if(li) {
    if(li->ld) {
      ldap_unbind_ext(li->ld, NULL, NULL);
      li->ld = NULL;
    }
    conn->proto.ldapc = NULL;
    free(li);
  }
  return CURLE_OK;
}

static CURLcode ldap_do(struct Curl_easy *data, bool *done)
{
  struct connectdata *conn = data->conn;
  struct ldapconninfo *li = conn->proto.ldapc;
  struct ldapreqinfo *lr;
  CURLcode status = CURLE_OK;
  int rc = 0;
  LDAPURLDesc *ludp = NULL;
  int msgid;


  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(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);
414
415
416
417
418
419
420
421
422
423

424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445

446
447
448
449
450
451
452
453
454
  lr->msgid = msgid;
  data->req.p.ldap = lr;
  Curl_setup_transfer(data, FIRSTSOCKET, -1, FALSE, -1);
  *done = TRUE;
  return CURLE_OK;
}

static CURLcode ldap_done(struct connectdata *conn, CURLcode res,
                          bool premature)
{

  struct ldapreqinfo *lr = conn->data->req.p.ldap;

  (void)res;
  (void)premature;

  if(lr) {
    /* if there was a search in progress, abandon it */
    if(lr->msgid) {
      struct ldapconninfo *li = conn->proto.ldapc;
      ldap_abandon_ext(li->ld, lr->msgid, NULL, NULL);
      lr->msgid = 0;
    }
    conn->data->req.p.ldap = NULL;
    free(lr);
  }

  return CURLE_OK;
}

static ssize_t ldap_recv(struct connectdata *conn, int sockindex, char *buf,
                         size_t len, CURLcode *err)
{

  struct ldapconninfo *li = conn->proto.ldapc;
  struct Curl_easy *data = conn->data;
  struct ldapreqinfo *lr = data->req.p.ldap;
  int rc, ret;
  LDAPMessage *msg = NULL;
  LDAPMessage *ent;
  BerElement *ber = NULL;
  struct timeval tv = {0, 1};








|


>
|











|






|


>

<







419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453

454
455
456
457
458
459
460
  lr->msgid = msgid;
  data->req.p.ldap = lr;
  Curl_setup_transfer(data, FIRSTSOCKET, -1, FALSE, -1);
  *done = TRUE;
  return CURLE_OK;
}

static CURLcode ldap_done(struct Curl_easy *data, CURLcode res,
                          bool premature)
{
  struct connectdata *conn = data->conn;
  struct ldapreqinfo *lr = data->req.p.ldap;

  (void)res;
  (void)premature;

  if(lr) {
    /* if there was a search in progress, abandon it */
    if(lr->msgid) {
      struct ldapconninfo *li = conn->proto.ldapc;
      ldap_abandon_ext(li->ld, lr->msgid, NULL, NULL);
      lr->msgid = 0;
    }
    data->req.p.ldap = NULL;
    free(lr);
  }

  return CURLE_OK;
}

static ssize_t ldap_recv(struct Curl_easy *data, int sockindex, char *buf,
                         size_t len, CURLcode *err)
{
  struct connectdata *conn = data->conn;
  struct ldapconninfo *li = conn->proto.ldapc;

  struct ldapreqinfo *lr = data->req.p.ldap;
  int rc, ret;
  LDAPMessage *msg = NULL;
  LDAPMessage *ent;
  BerElement *ber = NULL;
  struct timeval tv = {0, 1};

508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591

    lr->nument++;
    rc = ldap_get_dn_ber(li->ld, ent, &ber, &bv);
    if(rc < 0) {
      *err = CURLE_RECV_ERROR;
      return -1;
    }
    writeerr = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)"DN: ", 4);
    if(writeerr) {
      *err = writeerr;
      return -1;
    }

    writeerr = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)bv.bv_val,
                                 bv.bv_len);
    if(writeerr) {
      *err = writeerr;
      return -1;
    }

    writeerr = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)"\n", 1);
    if(writeerr) {
      *err = writeerr;
      return -1;
    }
    data->req.bytecount += bv.bv_len + 5;

    for(rc = ldap_get_attribute_ber(li->ld, ent, ber, &bv, &bvals);
        rc == LDAP_SUCCESS;
        rc = ldap_get_attribute_ber(li->ld, ent, ber, &bv, &bvals)) {
      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;

      if(bvals == NULL) {
        writeerr = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)"\t", 1);
        if(writeerr) {
          *err = writeerr;
          return -1;
        }
        writeerr = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)bv.bv_val,
                                     bv.bv_len);
        if(writeerr) {
          *err = writeerr;
          return -1;
        }
        writeerr = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)":\n", 2);
        if(writeerr) {
          *err = writeerr;
          return -1;
        }
        data->req.bytecount += bv.bv_len + 3;
        continue;
      }

      for(i = 0; bvals[i].bv_val != NULL; i++) {
        int binval = 0;
        writeerr = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)"\t", 1);
        if(writeerr) {
          *err = writeerr;
          return -1;
        }

        writeerr = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)bv.bv_val,
                                     bv.bv_len);
        if(writeerr) {
          *err = writeerr;
          return -1;
        }

        writeerr = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)":", 1);
        if(writeerr) {
          *err = writeerr;
          return -1;
        }
        data->req.bytecount += bv.bv_len + 2;

        if(!binary) {







|





|






|




















|




|





|










|





|






|







514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597

    lr->nument++;
    rc = ldap_get_dn_ber(li->ld, ent, &ber, &bv);
    if(rc < 0) {
      *err = CURLE_RECV_ERROR;
      return -1;
    }
    writeerr = Curl_client_write(data, CLIENTWRITE_BODY, (char *)"DN: ", 4);
    if(writeerr) {
      *err = writeerr;
      return -1;
    }

    writeerr = Curl_client_write(data, CLIENTWRITE_BODY, (char *)bv.bv_val,
                                 bv.bv_len);
    if(writeerr) {
      *err = writeerr;
      return -1;
    }

    writeerr = Curl_client_write(data, CLIENTWRITE_BODY, (char *)"\n", 1);
    if(writeerr) {
      *err = writeerr;
      return -1;
    }
    data->req.bytecount += bv.bv_len + 5;

    for(rc = ldap_get_attribute_ber(li->ld, ent, ber, &bv, &bvals);
        rc == LDAP_SUCCESS;
        rc = ldap_get_attribute_ber(li->ld, ent, ber, &bv, &bvals)) {
      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;

      if(bvals == NULL) {
        writeerr = Curl_client_write(data, CLIENTWRITE_BODY, (char *)"\t", 1);
        if(writeerr) {
          *err = writeerr;
          return -1;
        }
        writeerr = Curl_client_write(data, CLIENTWRITE_BODY, (char *)bv.bv_val,
                                     bv.bv_len);
        if(writeerr) {
          *err = writeerr;
          return -1;
        }
        writeerr = Curl_client_write(data, CLIENTWRITE_BODY, (char *)":\n", 2);
        if(writeerr) {
          *err = writeerr;
          return -1;
        }
        data->req.bytecount += bv.bv_len + 3;
        continue;
      }

      for(i = 0; bvals[i].bv_val != NULL; i++) {
        int binval = 0;
        writeerr = Curl_client_write(data, CLIENTWRITE_BODY, (char *)"\t", 1);
        if(writeerr) {
          *err = writeerr;
          return -1;
        }

        writeerr = Curl_client_write(data, CLIENTWRITE_BODY, (char *)bv.bv_val,
                                     bv.bv_len);
        if(writeerr) {
          *err = writeerr;
          return -1;
        }

        writeerr = Curl_client_write(data, CLIENTWRITE_BODY, (char *)":", 1);
        if(writeerr) {
          *err = writeerr;
          return -1;
        }
        data->req.bytecount += bv.bv_len + 2;

        if(!binary) {
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
          if(error) {
            ber_memfree(bvals);
            ber_free(ber, 0);
            ldap_msgfree(msg);
            *err = error;
            return -1;
          }
          writeerr = Curl_client_write(conn, CLIENTWRITE_BODY,
                                       (char *)": ", 2);
          if(writeerr) {
            *err = writeerr;
            return -1;
          }

          data->req.bytecount += 2;
          if(val_b64_sz > 0) {
            writeerr = Curl_client_write(conn, CLIENTWRITE_BODY, val_b64,
                                         val_b64_sz);
            if(writeerr) {
              *err = writeerr;
              return -1;
            }
            free(val_b64);
            data->req.bytecount += val_b64_sz;
          }
        }
        else {
          writeerr = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)" ", 1);
          if(writeerr) {
            *err = writeerr;
            return -1;
          }

          writeerr = Curl_client_write(conn, CLIENTWRITE_BODY, bvals[i].bv_val,
                                       bvals[i].bv_len);
          if(writeerr) {
            *err = writeerr;
            return -1;
          }

          data->req.bytecount += bvals[i].bv_len + 1;
        }
        writeerr = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)"\n", 0);
        if(writeerr) {
          *err = writeerr;
          return -1;
        }

        data->req.bytecount++;
      }
      ber_memfree(bvals);
      writeerr = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)"\n", 0);
      if(writeerr) {
        *err = writeerr;
        return -1;
      }
      data->req.bytecount++;
    }
    writeerr = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)"\n", 0);
    if(writeerr) {
      *err = writeerr;
      return -1;
    }
    data->req.bytecount++;
    ber_free(ber, 0);
  }







|








|










|





|








|








|






|







621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
          if(error) {
            ber_memfree(bvals);
            ber_free(ber, 0);
            ldap_msgfree(msg);
            *err = error;
            return -1;
          }
          writeerr = Curl_client_write(data, CLIENTWRITE_BODY,
                                       (char *)": ", 2);
          if(writeerr) {
            *err = writeerr;
            return -1;
          }

          data->req.bytecount += 2;
          if(val_b64_sz > 0) {
            writeerr = Curl_client_write(data, CLIENTWRITE_BODY, val_b64,
                                         val_b64_sz);
            if(writeerr) {
              *err = writeerr;
              return -1;
            }
            free(val_b64);
            data->req.bytecount += val_b64_sz;
          }
        }
        else {
          writeerr = Curl_client_write(data, CLIENTWRITE_BODY, (char *)" ", 1);
          if(writeerr) {
            *err = writeerr;
            return -1;
          }

          writeerr = Curl_client_write(data, CLIENTWRITE_BODY, bvals[i].bv_val,
                                       bvals[i].bv_len);
          if(writeerr) {
            *err = writeerr;
            return -1;
          }

          data->req.bytecount += bvals[i].bv_len + 1;
        }
        writeerr = Curl_client_write(data, CLIENTWRITE_BODY, (char *)"\n", 0);
        if(writeerr) {
          *err = writeerr;
          return -1;
        }

        data->req.bytecount++;
      }
      ber_memfree(bvals);
      writeerr = Curl_client_write(data, CLIENTWRITE_BODY, (char *)"\n", 0);
      if(writeerr) {
        *err = writeerr;
        return -1;
      }
      data->req.bytecount++;
    }
    writeerr = Curl_client_write(data, CLIENTWRITE_BODY, (char *)"\n", 0);
    if(writeerr) {
      *err = writeerr;
      return -1;
    }
    data->req.bytecount++;
    ber_free(ber, 0);
  }
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
ldapsb_tls_read(Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len)
{
  struct connectdata *conn = sbiod->sbiod_pvt;
  struct ldapconninfo *li = conn->proto.ldapc;
  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;
  struct ldapconninfo *li = conn->proto.ldapc;
  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 =







|














|







726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
ldapsb_tls_read(Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len)
{
  struct connectdata *conn = sbiod->sbiod_pvt;
  struct ldapconninfo *li = conn->proto.ldapc;
  ber_slen_t ret;
  CURLcode err = CURLE_RECV_ERROR;

  ret = (li->recv)(conn->data, 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;
  struct ldapconninfo *li = conn->proto.ldapc;
  ber_slen_t ret;
  CURLcode err = CURLE_SEND_ERROR;

  ret = (li->send)(conn->data, FIRSTSOCKET, buf, len, &err);
  if(ret < 0 && err == CURLE_AGAIN) {
    SET_SOCKERRNO(EWOULDBLOCK);
  }
  return ret;
}

static Sockbuf_IO ldapsb_tls =
Changes to jni/curl/lib/pingpong.c.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2020, 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 https://curl.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







|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2021, 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 https://curl.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
40
41
42
43
44
45
46
47

48
49
50
51
52
53
54
55
56
57
#include "curl_memory.h"
#include "memdebug.h"

#ifdef USE_PINGPONG

/* Returns timeout in ms. 0 or negative number means the timeout has already
   triggered */
timediff_t Curl_pp_state_timeout(struct pingpong *pp, bool disconnecting)

{
  struct connectdata *conn = pp->conn;
  struct Curl_easy *data = conn->data;
  timediff_t timeout_ms; /* in milliseconds */
  timediff_t 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







|
>

|
<







40
41
42
43
44
45
46
47
48
49
50

51
52
53
54
55
56
57
#include "curl_memory.h"
#include "memdebug.h"

#ifdef USE_PINGPONG

/* Returns timeout in ms. 0 or negative number means the timeout has already
   triggered */
timediff_t Curl_pp_state_timeout(struct Curl_easy *data,
                                 struct pingpong *pp, bool disconnecting)
{
  struct connectdata *conn = data->conn;

  timediff_t timeout_ms; /* in milliseconds */
  timediff_t 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
73
74
75
76
77
78
79
80

81
82
83
84
85
86
87
88
89
90
91
92
93
94
95

  return timeout_ms;
}

/*
 * Curl_pp_statemach()
 */
CURLcode Curl_pp_statemach(struct pingpong *pp, bool block,

                           bool disconnecting)
{
  struct connectdata *conn = pp->conn;
  curl_socket_t sock = conn->sock[FIRSTSOCKET];
  int rc;
  timediff_t interval_ms;
  timediff_t timeout_ms = Curl_pp_state_timeout(pp, disconnecting);
  struct Curl_easy *data = conn->data;
  CURLcode result = CURLE_OK;

  if(timeout_ms <= 0) {
    failf(data, "server response timeout");
    return CURLE_OPERATION_TIMEDOUT; /* already too little time */
  }








|
>


|



|
<







73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88

89
90
91
92
93
94
95

  return timeout_ms;
}

/*
 * Curl_pp_statemach()
 */
CURLcode Curl_pp_statemach(struct Curl_easy *data,
                           struct pingpong *pp, bool block,
                           bool disconnecting)
{
  struct connectdata *conn = data->conn;
  curl_socket_t sock = conn->sock[FIRSTSOCKET];
  int rc;
  timediff_t interval_ms;
  timediff_t timeout_ms = Curl_pp_state_timeout(data, pp, disconnecting);

  CURLcode result = CURLE_OK;

  if(timeout_ms <= 0) {
    failf(data, "server response timeout");
    return CURLE_OPERATION_TIMEDOUT; /* already too little time */
  }

113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165

166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
    rc = Curl_socket_check(pp->sendleft?CURL_SOCKET_BAD:sock, /* reading */
                           CURL_SOCKET_BAD,
                           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_now());

    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 */
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_now(); /* start response time-out now! */
}

/* setup for the coming transfer */
void Curl_pp_setup(struct pingpong *pp)
{
  Curl_dyn_init(&pp->sendbuf, DYN_PINGPPONG_CMD);
}

/***********************************************************************
 *
 * Curl_pp_vsendf()
 *
 * Send the formatted 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
 */
CURLcode Curl_pp_vsendf(struct pingpong *pp,

                        const char *fmt,
                        va_list args)
{
  ssize_t bytes_written = 0;
  size_t write_len;
  char *s;
  CURLcode result;
  struct connectdata *conn = pp->conn;
  struct Curl_easy *data;

#ifdef HAVE_GSSAPI
  enum protection_level data_sec;
#endif

  DEBUGASSERT(pp->sendleft == 0);
  DEBUGASSERT(pp->sendsize == 0);
  DEBUGASSERT(pp->sendthis == NULL);

  if(!conn)
    /* can't send without a connection! */
    return CURLE_SEND_ERROR;
  data = conn->data;

  Curl_dyn_reset(&pp->sendbuf);
  result = Curl_dyn_vaddf(&pp->sendbuf, fmt, args);
  if(result)
    return result;

  /* append CRLF */
  result = Curl_dyn_addn(&pp->sendbuf, "\r\n", 2);
  if(result)
    return result;

  write_len = Curl_dyn_len(&pp->sendbuf);
  s = Curl_dyn_ptr(&pp->sendbuf);
  Curl_pp_init(pp);

  result = Curl_convert_to_network(data, s, write_len);
  /* Curl_convert_to_network calls failf if unsuccessful */
  if(result)
    return result;

#ifdef HAVE_GSSAPI
  conn->data_prot = PROT_CMD;
#endif
  result = Curl_write(conn, conn->sock[FIRSTSOCKET], s, write_len,
                      &bytes_written);
  if(result)
    return result;
#ifdef HAVE_GSSAPI
  data_sec = conn->data_prot;
  DEBUGASSERT(data_sec > PROT_NONE && data_sec < PROT_LAST);
  conn->data_prot = data_sec;







|













|





|

|

|




















|
>







|
<












<













|









|







113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174

175
176
177
178
179
180
181
182
183
184
185
186

187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
    rc = Curl_socket_check(pp->sendleft?CURL_SOCKET_BAD:sock, /* reading */
                           CURL_SOCKET_BAD,
                           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(data))
      result = CURLE_ABORTED_BY_CALLBACK;
    else
      result = Curl_speedcheck(data, Curl_now());

    if(result)
      return result;
  }

  if(rc == -1) {
    failf(data, "select/poll error");
    result = CURLE_OUT_OF_MEMORY;
  }
  else if(rc)
    result = pp->statemachine(data, data->conn);

  return result;
}

/* initialize stuff to prepare for reading a fresh new response */
void Curl_pp_init(struct Curl_easy *data, struct pingpong *pp)
{
  DEBUGASSERT(data);
  pp->nread_resp = 0;
  pp->linestart_resp = data->state.buffer;
  pp->pending_resp = TRUE;
  pp->response = Curl_now(); /* start response time-out now! */
}

/* setup for the coming transfer */
void Curl_pp_setup(struct pingpong *pp)
{
  Curl_dyn_init(&pp->sendbuf, DYN_PINGPPONG_CMD);
}

/***********************************************************************
 *
 * Curl_pp_vsendf()
 *
 * Send the formatted 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
 */
CURLcode Curl_pp_vsendf(struct Curl_easy *data,
                        struct pingpong *pp,
                        const char *fmt,
                        va_list args)
{
  ssize_t bytes_written = 0;
  size_t write_len;
  char *s;
  CURLcode result;
  struct connectdata *conn = data->conn;


#ifdef HAVE_GSSAPI
  enum protection_level data_sec;
#endif

  DEBUGASSERT(pp->sendleft == 0);
  DEBUGASSERT(pp->sendsize == 0);
  DEBUGASSERT(pp->sendthis == NULL);

  if(!conn)
    /* can't send without a connection! */
    return CURLE_SEND_ERROR;


  Curl_dyn_reset(&pp->sendbuf);
  result = Curl_dyn_vaddf(&pp->sendbuf, fmt, args);
  if(result)
    return result;

  /* append CRLF */
  result = Curl_dyn_addn(&pp->sendbuf, "\r\n", 2);
  if(result)
    return result;

  write_len = Curl_dyn_len(&pp->sendbuf);
  s = Curl_dyn_ptr(&pp->sendbuf);
  Curl_pp_init(data, pp);

  result = Curl_convert_to_network(data, s, write_len);
  /* Curl_convert_to_network calls failf if unsuccessful */
  if(result)
    return result;

#ifdef HAVE_GSSAPI
  conn->data_prot = PROT_CMD;
#endif
  result = Curl_write(data, conn->sock[FIRSTSOCKET], s, write_len,
                      &bytes_written);
  if(result)
    return result;
#ifdef HAVE_GSSAPI
  data_sec = conn->data_prot;
  DEBUGASSERT(data_sec > PROT_NONE && data_sec < PROT_LAST);
  conn->data_prot = data_sec;
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268

269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
 *
 * Send the formatted 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
 */
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 Curl_easy *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;







|






|











|
>








|
<







241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277

278
279
280
281
282
283
284
 *
 * Send the formatted 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
 */
CURLcode Curl_pp_sendf(struct Curl_easy *data, struct pingpong *pp,
                       const char *fmt, ...)
{
  CURLcode result;
  va_list ap;
  va_start(ap, fmt);

  result = Curl_pp_vsendf(data, pp, fmt, ap);

  va_end(ap);

  return result;
}

/*
 * Curl_pp_readresp()
 *
 * Reads a piece of a server response.
 */
CURLcode Curl_pp_readresp(struct Curl_easy *data,
                          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 = data->conn;

  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;
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
    else {
#ifdef HAVE_GSSAPI
      enum protection_level prot = conn->data_prot;
      conn->data_prot = PROT_CLEAR;
#endif
      DEBUGASSERT((ptr + data->set.buffer_size - pp->nread_resp) <=
                  (buf + data->set.buffer_size + 1));
      result = Curl_read(conn, sockfd, ptr,
                         data->set.buffer_size - pp->nread_resp,
                         &gotbytes);
#ifdef HAVE_GSSAPI
      DEBUGASSERT(prot  > PROT_NONE && prot < PROT_LAST);
      conn->data_prot = prot;
#endif
      if(result == CURLE_AGAIN)







|







310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
    else {
#ifdef HAVE_GSSAPI
      enum protection_level prot = conn->data_prot;
      conn->data_prot = PROT_CLEAR;
#endif
      DEBUGASSERT((ptr + data->set.buffer_size - pp->nread_resp) <=
                  (buf + data->set.buffer_size + 1));
      result = Curl_read(data, sockfd, ptr,
                         data->set.buffer_size - pp->nread_resp,
                         &gotbytes);
#ifdef HAVE_GSSAPI
      DEBUGASSERT(prot  > PROT_NONE && prot < PROT_LAST);
      conn->data_prot = prot;
#endif
      if(result == CURLE_AGAIN)
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
                       pp->linestart_resp, (size_t)perline);

          /*
           * 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 null-terminate, for old times sake */
            size_t n = ptr - pp->linestart_resp;
            memmove(buf, pp->linestart_resp, n);
            buf[n] = 0; /* null-terminate */
            keepon = FALSE;
            pp->linestart_resp = ptr + 1; /* advance pointer */







|




|







366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
                       pp->linestart_resp, (size_t)perline);

          /*
           * 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(data, CLIENTWRITE_HEADER,
                                     pp->linestart_resp, perline);
          if(result)
            return result;

          if(pp->endofresp(data, 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 null-terminate, for old times sake */
            size_t n = ptr - pp->linestart_resp;
            memmove(buf, pp->linestart_resp, n);
            buf[n] = 0; /* null-terminate */
            keepon = FALSE;
            pp->linestart_resp = ptr + 1; /* advance pointer */
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474

475
476
477
478
479
480
481
482
483
484
485
486
487
  } /* while there's buffer left and loop is requested */

  pp->pending_resp = FALSE;

  return result;
}

int Curl_pp_getsock(struct pingpong *pp,
                    curl_socket_t *socks)
{
  struct connectdata *conn = pp->conn;
  socks[0] = conn->sock[FIRSTSOCKET];

  if(pp->sendleft) {
    /* write mode */
    return GETSOCK_WRITESOCK(0);
  }

  /* read mode */
  return GETSOCK_READSOCK(0);
}

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;







|
|

|











|
>


|


|







451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
  } /* while there's buffer left and loop is requested */

  pp->pending_resp = FALSE;

  return result;
}

int Curl_pp_getsock(struct Curl_easy *data,
                    struct pingpong *pp, curl_socket_t *socks)
{
  struct connectdata *conn = data->conn;
  socks[0] = conn->sock[FIRSTSOCKET];

  if(pp->sendleft) {
    /* write mode */
    return GETSOCK_WRITESOCK(0);
  }

  /* read mode */
  return GETSOCK_READSOCK(0);
}

CURLcode Curl_pp_flushsend(struct Curl_easy *data,
                           struct pingpong *pp)
{
  /* we have a piece of a command still left to send */
  struct connectdata *conn = data->conn;
  ssize_t written;
  curl_socket_t sock = conn->sock[FIRSTSOCKET];
  CURLcode result = Curl_write(data, 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;
Changes to jni/curl/lib/pingpong.h.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#ifndef HEADER_CURL_PINGPONG_H
#define HEADER_CURL_PINGPONG_H
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2020, 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 https://curl.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









|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#ifndef HEADER_CURL_PINGPONG_H
#define HEADER_CURL_PINGPONG_H
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2021, 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 https://curl.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
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76







77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95

96
97
98
99
100
101
102
103
104
105
106
107
108

109
110
111
112
113
114
115
116
117
118
119
120
121

122
123
124
125
126
127
128
129
130

131
132
133
134
135
136

137
138
139
140

141
142
143
144
145
146
147
148
149
150
151
152
153
                     server */
  size_t sendleft; /* number of bytes left to send from the sendthis buffer */
  size_t sendsize; /* total size of the sendthis buffer */
  struct curltime response; /* set to Curl_now() when a command has been sent
                               off, used to time-out response reading */
  timediff_t 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 */
  struct dynbuf sendbuf;

  /* 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.
 */
CURLcode Curl_pp_statemach(struct pingpong *pp, bool block,
                           bool disconnecting);

/* initialize stuff to prepare for reading a fresh new response */
void Curl_pp_init(struct pingpong *pp);

/* setup for the transfer */
void Curl_pp_setup(struct pingpong *pp);

/* Returns timeout in ms. 0 or negative number means the timeout has already
   triggered */
timediff_t Curl_pp_state_timeout(struct pingpong *pp, bool disconnecting);



/***********************************************************************
 *
 * Curl_pp_sendf()
 *
 * Send the formatted 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
 */
CURLcode Curl_pp_sendf(struct pingpong *pp,

                       const char *fmt, ...);

/***********************************************************************
 *
 * Curl_pp_vsendf()
 *
 * Send the formatted 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
 */
CURLcode Curl_pp_vsendf(struct pingpong *pp,

                        const char *fmt,
                        va_list args);

/*
 * 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 */


CURLcode Curl_pp_flushsend(struct pingpong *pp);


/* call this when a pingpong connection is disconnected */
CURLcode Curl_pp_disconnect(struct pingpong *pp);


int Curl_pp_getsock(struct pingpong *pp, curl_socket_t *socks);


/***********************************************************************
 *
 * Curl_pp_moredata()
 *
 * Returns whether there are still more data in the cache and so a call
 * to Curl_pp_readresp() will not block.
 */
bool Curl_pp_moredata(struct pingpong *pp);

#endif /* HEADER_CURL_PINGPONG_H */







<
<





<
|
|
|

>
>
>
>
>
>
>







|
|


|






|
>












|
>












|
>








|
>





|
>




>
|












58
59
60
61
62
63
64


65
66
67
68
69

70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
                     server */
  size_t sendleft; /* number of bytes left to send from the sendthis buffer */
  size_t sendsize; /* total size of the sendthis buffer */
  struct curltime response; /* set to Curl_now() when a command has been sent
                               off, used to time-out response reading */
  timediff_t response_time; /* When no timeout is given, this is the amount of
                               milliseconds we await for a server response. */


  struct dynbuf sendbuf;

  /* Function pointers the protocols MUST implement and provide for the
     pingpong layer to function */


  CURLcode (*statemachine)(struct Curl_easy *data, struct connectdata *conn);
  bool (*endofresp)(struct Curl_easy *data, struct connectdata *conn,
                    char *ptr, size_t len, int *code);
};

#define PINGPONG_SETUP(pp,s,e)                   \
  do {                                           \
    pp->response_time = RESP_TIMEOUT;            \
    pp->statemachine = s;                        \
    pp->endofresp = e;                           \
  } while(0)

/*
 * Curl_pp_statemach()
 *
 * called repeatedly until done. Set 'wait' to make it wait a while on the
 * socket if there's no traffic.
 */
CURLcode Curl_pp_statemach(struct Curl_easy *data, struct pingpong *pp,
                           bool block, bool disconnecting);

/* initialize stuff to prepare for reading a fresh new response */
void Curl_pp_init(struct Curl_easy *data, struct pingpong *pp);

/* setup for the transfer */
void Curl_pp_setup(struct pingpong *pp);

/* Returns timeout in ms. 0 or negative number means the timeout has already
   triggered */
timediff_t Curl_pp_state_timeout(struct Curl_easy *data,
                                 struct pingpong *pp, bool disconnecting);


/***********************************************************************
 *
 * Curl_pp_sendf()
 *
 * Send the formatted 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
 */
CURLcode Curl_pp_sendf(struct Curl_easy *data,
                       struct pingpong *pp,
                       const char *fmt, ...);

/***********************************************************************
 *
 * Curl_pp_vsendf()
 *
 * Send the formatted 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
 */
CURLcode Curl_pp_vsendf(struct Curl_easy *data,
                        struct pingpong *pp,
                        const char *fmt,
                        va_list args);

/*
 * Curl_pp_readresp()
 *
 * Reads a piece of a server response.
 */
CURLcode Curl_pp_readresp(struct Curl_easy *data,
                          curl_socket_t sockfd,
                          struct pingpong *pp,
                          int *code, /* return the server code if done */
                          size_t *size); /* size of the response */


CURLcode Curl_pp_flushsend(struct Curl_easy *data,
                           struct pingpong *pp);

/* call this when a pingpong connection is disconnected */
CURLcode Curl_pp_disconnect(struct pingpong *pp);

int Curl_pp_getsock(struct Curl_easy *data, struct pingpong *pp,
                    curl_socket_t *socks);


/***********************************************************************
 *
 * Curl_pp_moredata()
 *
 * Returns whether there are still more data in the cache and so a call
 * to Curl_pp_readresp() will not block.
 */
bool Curl_pp_moredata(struct pingpong *pp);

#endif /* HEADER_CURL_PINGPONG_H */
Changes to jni/curl/lib/pop3.c.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2020, 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 https://curl.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







|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2021, 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 https://curl.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
84
85
86
87
88
89
90
91
92
93
94
95
96

97

98
99
100

101
102
103
104

105
106

107
108
109
110
111
112
113
#include "warnless.h"
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
#include "curl_memory.h"
#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);
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 = {







|
|
|

|
|
>
|
>
|
|
|
>

|
|
|
>

|
>







84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
#include "warnless.h"
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
#include "curl_memory.h"
#include "memdebug.h"

/* Local API functions */
static CURLcode pop3_regular_transfer(struct Curl_easy *data, bool *done);
static CURLcode pop3_do(struct Curl_easy *data, bool *done);
static CURLcode pop3_done(struct Curl_easy *data, CURLcode status,
                          bool premature);
static CURLcode pop3_connect(struct Curl_easy *data, bool *done);
static CURLcode pop3_disconnect(struct Curl_easy *data,
                                struct connectdata *conn, bool dead);
static CURLcode pop3_multi_statemach(struct Curl_easy *data, bool *done);
static int pop3_getsock(struct Curl_easy *data,
                        struct connectdata *conn, curl_socket_t *socks);
static CURLcode pop3_doing(struct Curl_easy *data, bool *dophase_done);
static CURLcode pop3_setup_connection(struct Curl_easy *data,
                                      struct connectdata *conn);
static CURLcode pop3_parse_url_options(struct connectdata *conn);
static CURLcode pop3_parse_url_path(struct Curl_easy *data);
static CURLcode pop3_parse_custom_request(struct Curl_easy *data);
static CURLcode pop3_perform_auth(struct Curl_easy *data,
                                  struct connectdata *conn, const char *mech,
                                  const char *initresp);
static CURLcode pop3_continue_auth(struct Curl_easy *data,
                                   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 = {
191
192
193
194
195
196
197
198
199
200
201

202
203
204
205
206
207
208
 * 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;
  }







|
|


>







196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
 * 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 Curl_easy *data, struct connectdata *conn,
                           char *line, size_t len, int *resp)
{
  struct pop3_conn *pop3c = &conn->proto.pop3c;
  (void)data;

  /* Do we have an error response? */
  if(len >= 4 && !memcmp("-ERR", line, 4)) {
    *resp = '-';

    return TRUE;
  }
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317

318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341

342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358

359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384

385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412

413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431

/***********************************************************************
 *
 * 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)

{
  /* Send the STLS command */
  CURLcode 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)

{
  /* Start the SSL connection */
  struct pop3_conn *pop3c = &conn->proto.pop3c;
  CURLcode 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;
  struct 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)







|

|


















|













|
>









|


|










|
>


|


|










|
>



|




|



|












|
>






|





|


|











|
>











|







281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442

/***********************************************************************
 *
 * state()
 *
 * This is the ONLY way to change POP3 state!
 */
static void state(struct Curl_easy *data, pop3state newstate)
{
  struct pop3_conn *pop3c = &data->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(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 Curl_easy *data,
                                  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(data, &pop3c->pp, "%s", "CAPA");

  if(!result)
    state(data, POP3_CAPA);

  return result;
}

/***********************************************************************
 *
 * pop3_perform_starttls()
 *
 * Sends the STLS command to start the upgrade to TLS.
 */
static CURLcode pop3_perform_starttls(struct Curl_easy *data,
                                      struct connectdata *conn)
{
  /* Send the STLS command */
  CURLcode result = Curl_pp_sendf(data, &conn->proto.pop3c.pp, "%s", "STLS");

  if(!result)
    state(data, POP3_STARTTLS);

  return result;
}

/***********************************************************************
 *
 * pop3_perform_upgrade_tls()
 *
 * Performs the upgrade to TLS.
 */
static CURLcode pop3_perform_upgrade_tls(struct Curl_easy *data,
                                         struct connectdata *conn)
{
  /* Start the SSL connection */
  struct pop3_conn *pop3c = &conn->proto.pop3c;
  CURLcode result = Curl_ssl_connect_nonblocking(data, conn, FIRSTSOCKET,
                                                 &pop3c->ssldone);

  if(!result) {
    if(pop3c->state != POP3_UPGRADETLS)
      state(data, POP3_UPGRADETLS);

    if(pop3c->ssldone) {
      pop3_to_pop3s(conn);
      result = pop3_perform_capa(data, conn);
    }
  }

  return result;
}

/***********************************************************************
 *
 * pop3_perform_user()
 *
 * Sends a clear text USER command to authenticate with.
 */
static CURLcode pop3_perform_user(struct Curl_easy *data,
                                  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(data, POP3_STOP);

    return result;
  }

  /* Send the USER command */
  result = Curl_pp_sendf(data, &conn->proto.pop3c.pp, "USER %s",
                         conn->user ? conn->user : "");
  if(!result)
    state(data, 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 Curl_easy *data,
                                  struct connectdata *conn)
{
  CURLcode result = CURLE_OK;
  struct pop3_conn *pop3c = &conn->proto.pop3c;
  size_t i;
  struct 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(data, POP3_STOP);

    return result;
  }

  /* Create the digest */
  ctxt = Curl_MD5_init(Curl_DIGEST_MD5);
  if(!ctxt)
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463

464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488

489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504

505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592

593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
  /* 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++)
    msnprintf(&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 Curl_easy *data = conn->data;
  struct POP3 *pop3 = data->req.p.pop3;
  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)

{
  /* Send the QUIT command */
  CURLcode 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 Curl_easy *data = conn->data;
  struct pop3_conn *pop3c = &conn->proto.pop3c;
  const char *line = data->state.buffer;
  size_t len = strlen(line);

  (void)instate; /* no use for this yet */

  if(pop3code != '+') {







|


|












|
>








|



|











|
>




|










|
>








|





|



|






|




|


|













|


|




|











|



|




|










|
>


|


|





|




|







451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
  /* 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++)
    msnprintf(&secret[2 * i], 3, "%02x", digest[i]);

  result = Curl_pp_sendf(data, &pop3c->pp, "APOP %s %s", conn->user, secret);

  if(!result)
    state(data, 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 Curl_easy *data,
                                  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(data, &pop3c->pp, "AUTH %s %s", mech, initresp);
  }
  else {
    /* Send the AUTH command */
    result = Curl_pp_sendf(data, &pop3c->pp, "AUTH %s", mech);
  }

  return result;
}

/***********************************************************************
 *
 * pop3_continue_auth()
 *
 * Sends SASL continuation data or cancellation.
 */
static CURLcode pop3_continue_auth(struct Curl_easy *data,
                                   struct connectdata *conn,
                                   const char *resp)
{
  struct pop3_conn *pop3c = &conn->proto.pop3c;

  return Curl_pp_sendf(data, &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 Curl_easy *data,
                                            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(data, POP3_STOP);
    return result;
  }

  if(pop3c->authtypes & pop3c->preftype & POP3_TYPE_SASL) {
    /* Calculate the SASL login details */
    result = Curl_sasl_start(&pop3c->sasl, data, conn, FALSE, &progress);

    if(!result)
      if(progress == SASL_INPROGRESS)
        state(data, 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(data, conn);
    else
#endif
    if(pop3c->authtypes & pop3c->preftype & POP3_TYPE_CLEARTEXT)
      /* Perform clear text authentication */
      result = pop3_perform_user(data, conn);
    else {
      /* Other mechanisms not supported */
      infof(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 Curl_easy *data)
{
  CURLcode result = CURLE_OK;
  struct connectdata *conn = data->conn;
  struct POP3 *pop3 = data->req.p.pop3;
  const char *command = NULL;

  /* Calculate the default command */
  if(pop3->id[0] == '\0' || 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(data, &conn->proto.pop3c.pp, "%s %s",
                           (pop3->custom && pop3->custom[0] != '\0' ?
                            pop3->custom : command), pop3->id);
  else
    result = Curl_pp_sendf(data, &conn->proto.pop3c.pp, "%s",
                           (pop3->custom && pop3->custom[0] != '\0' ?
                            pop3->custom : command));

  if(!result)
    state(data, POP3_COMMAND);

  return result;
}

/***********************************************************************
 *
 * pop3_perform_quit()
 *
 * Performs the quit action prior to sclose() be called.
 */
static CURLcode pop3_perform_quit(struct Curl_easy *data,
                                  struct connectdata *conn)
{
  /* Send the QUIT command */
  CURLcode result = Curl_pp_sendf(data, &conn->proto.pop3c.pp, "%s", "QUIT");

  if(!result)
    state(data, POP3_QUIT);

  return result;
}

/* For the initial server greeting */
static CURLcode pop3_state_servergreet_resp(struct Curl_easy *data,
                                            int pop3code,
                                            pop3state instate)
{
  CURLcode result = CURLE_OK;
  struct connectdata *conn = data->conn;
  struct pop3_conn *pop3c = &conn->proto.pop3c;
  const char *line = data->state.buffer;
  size_t len = strlen(line);

  (void)instate; /* no use for this yet */

  if(pop3code != '+') {
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
            /* 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 Curl_easy *data = conn->data;
  struct pop3_conn *pop3c = &conn->proto.pop3c;
  const char *line = data->state.buffer;
  size_t len = strlen(line);

  (void)instate; /* no use for this yet */

  /* Do we have a untagged continuation response? */







|






|



|







665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
            /* Store the APOP capability */
            pop3c->authtypes |= POP3_TYPE_APOP;
          break;
        }
      }
    }

    result = pop3_perform_capa(data, conn);
  }

  return result;
}

/* For CAPA responses */
static CURLcode pop3_state_capa_resp(struct Curl_easy *data, int pop3code,
                                     pop3state instate)
{
  CURLcode result = CURLE_OK;
  struct connectdata *conn = data->conn;
  struct pop3_conn *pop3c = &conn->proto.pop3c;
  const char *line = data->state.buffer;
  size_t len = strlen(line);

  (void)instate; /* no use for this yet */

  /* Do we have a untagged continuation response? */
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754

755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
    }
  }
  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 Curl_easy *data = conn->data;

  (void)instate; /* no use for this yet */

  if(pop3code != '+') {
    if(data->set.use_ssl != CURLUSESSL_TRY) {
      failf(data, "STARTTLS denied");
      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 Curl_easy *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 Curl_easy *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 Curl_easy *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 Curl_easy *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 Curl_easy *data = conn->data;
  struct POP3 *pop3 = data->req.p.pop3;
  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. */







|


|






|





|






|
>




<
<








|


|





|




|





|



|





|




|














|



<
<








|






|



<
|








|


|





|



<
<








|





|




|







|







739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774


775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836


837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855

856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877


878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
    }
  }
  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(data, conn);
      else if(data->set.use_ssl == CURLUSESSL_TRY)
        /* Fallback and carry on with authentication */
        result = pop3_perform_authentication(data, conn);
      else {
        failf(data, "STLS not supported.");
        result = CURLE_USE_SSL_FAILED;
      }
    }
    else
      result = pop3_perform_authentication(data, conn);
  }
  else {
    /* Clear text is supported when CAPA isn't recognised */
    pop3c->authtypes |= POP3_TYPE_CLEARTEXT;

    result = pop3_perform_authentication(data, conn);
  }

  return result;
}

/* For STARTTLS responses */
static CURLcode pop3_state_starttls_resp(struct Curl_easy *data,
                                         struct connectdata *conn,
                                         int pop3code,
                                         pop3state instate)
{
  CURLcode result = CURLE_OK;


  (void)instate; /* no use for this yet */

  if(pop3code != '+') {
    if(data->set.use_ssl != CURLUSESSL_TRY) {
      failf(data, "STARTTLS denied");
      result = CURLE_USE_SSL_FAILED;
    }
    else
      result = pop3_perform_authentication(data, conn);
  }
  else
    result = pop3_perform_upgrade_tls(data, conn);

  return result;
}

/* For SASL authentication responses */
static CURLcode pop3_state_auth_resp(struct Curl_easy *data,
                                     int pop3code,
                                     pop3state instate)
{
  CURLcode result = CURLE_OK;
  struct connectdata *conn = data->conn;
  struct pop3_conn *pop3c = &conn->proto.pop3c;
  saslprogress progress;

  (void)instate; /* no use for this yet */

  result = Curl_sasl_continue(&pop3c->sasl, data, conn, pop3code, &progress);
  if(!result)
    switch(progress) {
    case SASL_DONE:
      state(data, 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(data, conn);
      else
#endif
      if(pop3c->authtypes & pop3c->preftype & POP3_TYPE_CLEARTEXT)
        /* Perform clear text authentication */
        result = pop3_perform_user(data, 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 Curl_easy *data, int pop3code,
                                     pop3state instate)
{
  CURLcode result = CURLE_OK;


  (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(data, POP3_STOP);

  return result;
}
#endif

/* For USER responses */
static CURLcode pop3_state_user_resp(struct Curl_easy *data, int pop3code,
                                     pop3state instate)
{
  CURLcode result = CURLE_OK;

  struct connectdata *conn = data->conn;
  (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(data, &conn->proto.pop3c.pp, "PASS %s",
                           conn->passwd ? conn->passwd : "");
  if(!result)
    state(data, POP3_PASS);

  return result;
}

/* For PASS responses */
static CURLcode pop3_state_pass_resp(struct Curl_easy *data, int pop3code,
                                     pop3state instate)
{
  CURLcode result = CURLE_OK;


  (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(data, POP3_STOP);

  return result;
}

/* For command responses */
static CURLcode pop3_state_command_resp(struct Curl_easy *data,
                                        int pop3code,
                                        pop3state instate)
{
  CURLcode result = CURLE_OK;
  struct connectdata *conn = data->conn;
  struct POP3 *pop3 = data->req.p.pop3;
  struct pop3_conn *pop3c = &conn->proto.pop3c;
  struct pingpong *pp = &pop3c->pp;

  (void)instate; /* no use for this yet */

  if(pop3code != '+') {
    state(data, 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. */
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939

940
941
942
943
944
945
946

947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016

1017
1018
1019
1020

1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031

1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058

1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076

1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159

1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224

1225
1226

1227
1228
1229
1230
1231
1232
1233
1234
1235
1236

1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310

1311
1312
1313
1314
1315
1316
1317
1318
1319
1320

    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, FALSE);
  *done = (pop3c->state == POP3_STOP) ? TRUE : FALSE;

  return result;
}

static CURLcode pop3_block_statemach(struct connectdata *conn,

                                     bool disconnecting)
{
  CURLcode result = CURLE_OK;
  struct pop3_conn *pop3c = &conn->proto.pop3c;

  while(pop3c->state != POP3_STOP && !result)
    result = Curl_pp_statemach(&pop3c->pp, TRUE, disconnecting);

  return result;
}

/* Allocate and initialize the POP3 struct for the current Curl_easy if
   required */
static CURLcode pop3_init(struct connectdata *conn)
{
  CURLcode result = CURLE_OK;
  struct Curl_easy *data = conn->data;
  struct POP3 *pop3;

  pop3 = data->req.p.pop3 = 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)
{
  return Curl_pp_getsock(&conn->proto.pop3c.pp, socks);
}

/***********************************************************************
 *
 * 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_setup(pp);
  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 Curl_easy *data = conn->data;
  struct POP3 *pop3 = data->req.p.pop3;

  (void)premature;

  if(!pop3)
    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.p.pop3;

  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, TRUE); /* 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 Curl_easy *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)

{
  /* Initialise the POP3 layer */
  CURLcode result = pop3_init(conn);
  if(result)
    return result;

  /* Clear the TLS upgraded flag */
  conn->bits.tls_upgraded = FALSE;

  return CURLE_OK;







|













|




|
>







>



|



|



|
|
|







|



|



|



|




|




|



|



|






|








|


>



|
>




|





|
>






|






|


<










>
|

|












|


>








<
<
|
<
<







|







|

|













|



<








|




















|




>
|

|

|







|




|
<



|













|


<



|




|



|











|
>


>





<
<
|
|
|
>














|

|






|

|


|

|

|














|




<











|



|




|
>


|







922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061

1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099


1100


1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135

1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188

1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208

1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242


1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298

1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330

    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(data, 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(data, POP3_STOP);

  return result;
}

static CURLcode pop3_statemachine(struct Curl_easy *data,
                                  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;
  (void)data;

  /* Busy upgrading the connection; right now all I/O is SSL/TLS, not POP3 */
  if(pop3c->state == POP3_UPGRADETLS)
    return pop3_perform_upgrade_tls(data, conn);

  /* Flush any data that needs to be sent */
  if(pp->sendleft)
    return Curl_pp_flushsend(data, pp);

 do {
    /* Read the response from the server */
   result = Curl_pp_readresp(data, 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(data, pop3code, pop3c->state);
      break;

    case POP3_CAPA:
      result = pop3_state_capa_resp(data, pop3code, pop3c->state);
      break;

    case POP3_STARTTLS:
      result = pop3_state_starttls_resp(data, conn, pop3code, pop3c->state);
      break;

    case POP3_AUTH:
      result = pop3_state_auth_resp(data, pop3code, pop3c->state);
      break;

#ifndef CURL_DISABLE_CRYPTO_AUTH
    case POP3_APOP:
      result = pop3_state_apop_resp(data, pop3code, pop3c->state);
      break;
#endif

    case POP3_USER:
      result = pop3_state_user_resp(data, pop3code, pop3c->state);
      break;

    case POP3_PASS:
      result = pop3_state_pass_resp(data, pop3code, pop3c->state);
      break;

    case POP3_COMMAND:
      result = pop3_state_command_resp(data, pop3code, pop3c->state);
      break;

    case POP3_QUIT:
      /* fallthrough, just stop! */
    default:
      /* internal error */
      state(data, 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 Curl_easy *data, bool *done)
{
  CURLcode result = CURLE_OK;
  struct connectdata *conn = data->conn;
  struct pop3_conn *pop3c = &conn->proto.pop3c;

  if((conn->handler->flags & PROTOPT_SSL) && !pop3c->ssldone) {
    result = Curl_ssl_connect_nonblocking(data, conn,
                                          FIRSTSOCKET, &pop3c->ssldone);
    if(result || !pop3c->ssldone)
      return result;
  }

  result = Curl_pp_statemach(data, &pop3c->pp, FALSE, FALSE);
  *done = (pop3c->state == POP3_STOP) ? TRUE : FALSE;

  return result;
}

static CURLcode pop3_block_statemach(struct Curl_easy *data,
                                     struct connectdata *conn,
                                     bool disconnecting)
{
  CURLcode result = CURLE_OK;
  struct pop3_conn *pop3c = &conn->proto.pop3c;

  while(pop3c->state != POP3_STOP && !result)
    result = Curl_pp_statemach(data, &pop3c->pp, TRUE, disconnecting);

  return result;
}

/* Allocate and initialize the POP3 struct for the current Curl_easy if
   required */
static CURLcode pop3_init(struct Curl_easy *data)
{
  CURLcode result = CURLE_OK;

  struct POP3 *pop3;

  pop3 = data->req.p.pop3 = 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 Curl_easy *data,
                        struct connectdata *conn, curl_socket_t *socks)
{
  return Curl_pp_getsock(data, &conn->proto.pop3c.pp, socks);
}

/***********************************************************************
 *
 * 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 Curl_easy *data, bool *done)
{
  CURLcode result = CURLE_OK;
  struct connectdata *conn = data->conn;
  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");



  PINGPONG_SETUP(pp, pop3_statemachine, pop3_endofresp);



  /* 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_setup(pp);
  Curl_pp_init(data, pp);

  /* Parse the URL options */
  result = pop3_parse_url_options(conn);
  if(result)
    return result;

  /* Start off waiting for the server greeting response */
  state(data, POP3_SERVERGREET);

  result = pop3_multi_statemach(data, 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 Curl_easy *data, CURLcode status,
                          bool premature)
{
  CURLcode result = CURLE_OK;

  struct POP3 *pop3 = data->req.p.pop3;

  (void)premature;

  if(!pop3)
    return CURLE_OK;

  if(status) {
    connclose(data->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 Curl_easy *data, bool *connected,
                             bool *dophase_done)
{
  /* This is POP3 and no proxy */
  CURLcode result = CURLE_OK;
  struct connectdata *conn = data->conn;
  struct POP3 *pop3 = data->req.p.pop3;

  DEBUGF(infof(data, "DO phase starts\n"));

  if(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(data);
  if(result)
    return result;

  /* Run the state-machine */
  result = pop3_multi_statemach(data, dophase_done);

  *connected = conn->bits.tcpconnect[FIRSTSOCKET];

  if(*dophase_done)
    DEBUGF(infof(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 Curl_easy *data, bool *done)
{
  CURLcode result = CURLE_OK;

  *done = FALSE; /* default to false */

  /* Parse the URL path */
  result = pop3_parse_url_path(data);
  if(result)
    return result;

  /* Parse the custom request */
  result = pop3_parse_custom_request(data);
  if(result)
    return result;

  result = pop3_regular_transfer(data, done);

  return result;
}

/***********************************************************************
 *
 * pop3_disconnect()
 *
 * Disconnect from an POP3 server. Cleanup protocol-specific per-connection
 * resources. BLOCKING.
 */
static CURLcode pop3_disconnect(struct Curl_easy *data,
                                struct connectdata *conn, bool dead_connection)
{
  struct pop3_conn *pop3c = &conn->proto.pop3c;
  (void)data;

  /* 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. */



  if(!dead_connection && conn->bits.protoconnstart) {
    if(!pop3_perform_quit(data, conn))
      (void)pop3_block_statemach(data, conn, TRUE); /* 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 Curl_easy *data, bool connected)
{
  (void)data;
  (void)connected;

  return CURLE_OK;
}

/* Called from multi.c while DOing */
static CURLcode pop3_doing(struct Curl_easy *data, bool *dophase_done)
{
  CURLcode result = pop3_multi_statemach(data, dophase_done);

  if(result)
    DEBUGF(infof(data, "DO phase failed\n"));
  else if(*dophase_done) {
    result = pop3_dophase_done(data, FALSE /* not connected */);

    DEBUGF(infof(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 Curl_easy *data,
                                      bool *dophase_done)
{
  CURLcode result = CURLE_OK;
  bool connected = FALSE;


  /* 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(data, &connected, dophase_done);

  /* Perform post DO phase operations if necessary */
  if(!result && *dophase_done)
    result = pop3_dophase_done(data, connected);

  return result;
}

static CURLcode pop3_setup_connection(struct Curl_easy *data,
                                      struct connectdata *conn)
{
  /* Initialise the POP3 layer */
  CURLcode result = pop3_init(data);
  if(result)
    return result;

  /* Clear the TLS upgraded flag */
  conn->bits.tls_upgraded = FALSE;

  return CURLE_OK;
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460

/***********************************************************************
 *
 * 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 Curl_easy *data = conn->data;
  struct POP3 *pop3 = data->req.p.pop3;
  const char *path = &data->state.up.path[1]; /* skip leading path */

  /* URL decode the path for the message ID */
  return Curl_urldecode(data, path, 0, &pop3->id, NULL, REJECT_CTRL);
}

/***********************************************************************
 *
 * pop3_parse_custom_request()
 *
 * Parse the custom request.
 */
static CURLcode pop3_parse_custom_request(struct connectdata *conn)
{
  CURLcode result = CURLE_OK;
  struct Curl_easy *data = conn->data;
  struct POP3 *pop3 = data->req.p.pop3;
  const char *custom = data->set.str[STRING_CUSTOMREQUEST];

  /* URL decode the custom request */
  if(custom)
    result = Curl_urldecode(data, custom, 0, &pop3->custom, NULL, REJECT_CTRL);

  return result;
}

/***********************************************************************
 *
 * Curl_pop3_write()
 *
 * This function scans the body after the end-of-body and writes everything
 * until the end is found.
 */
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 Curl_easy *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;
        }







|


<













|


<

















|



<

|




















|







1391
1392
1393
1394
1395
1396
1397
1398
1399
1400

1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416

1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437

1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467

/***********************************************************************
 *
 * pop3_parse_url_path()
 *
 * Parse the URL path into separate path components.
 */
static CURLcode pop3_parse_url_path(struct Curl_easy *data)
{
  /* The POP3 struct is already initialised in pop3_connect() */

  struct POP3 *pop3 = data->req.p.pop3;
  const char *path = &data->state.up.path[1]; /* skip leading path */

  /* URL decode the path for the message ID */
  return Curl_urldecode(data, path, 0, &pop3->id, NULL, REJECT_CTRL);
}

/***********************************************************************
 *
 * pop3_parse_custom_request()
 *
 * Parse the custom request.
 */
static CURLcode pop3_parse_custom_request(struct Curl_easy *data)
{
  CURLcode result = CURLE_OK;

  struct POP3 *pop3 = data->req.p.pop3;
  const char *custom = data->set.str[STRING_CUSTOMREQUEST];

  /* URL decode the custom request */
  if(custom)
    result = Curl_urldecode(data, custom, 0, &pop3->custom, NULL, REJECT_CTRL);

  return result;
}

/***********************************************************************
 *
 * Curl_pop3_write()
 *
 * This function scans the body after the end-of-body and writes everything
 * until the end is found.
 */
CURLcode Curl_pop3_write(struct Curl_easy *data, char *str, size_t nread)
{
  /* This code could be made into a special function in the handler struct */
  CURLcode result = CURLE_OK;

  struct SingleRequest *k = &data->req;
  struct connectdata *conn = data->conn;
  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(data, CLIENTWRITE_BODY, &str[last],
                                     i - last);

          if(result)
            return result;

          last = i;
        }
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
        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 */







|















|












|







1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
        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(data, 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(data, 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(data, CLIENTWRITE_BODY, &str[last],
                               nread - last);
  }

  return result;
}

#endif /* CURL_DISABLE_POP3 */
Changes to jni/curl/lib/pop3.h.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#ifndef HEADER_CURL_POP3_H
#define HEADER_CURL_POP3_H
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 2009 - 2020, 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 https://curl.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









|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#ifndef HEADER_CURL_POP3_H
#define HEADER_CURL_POP3_H
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 2009 - 2021, 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 https://curl.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
57
58
59
60
61
62
63

64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95

/* 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 */
CURLcode Curl_pop3_write(struct connectdata *conn, char *str, size_t nread);

#endif /* HEADER_CURL_POP3_H */







>








<




















|


57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72

73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95

/* 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? */
  bool tls_supported;     /* StartTLS capability supported by server */
  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 */

};

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 */
CURLcode Curl_pop3_write(struct Curl_easy *data, char *str, size_t nread);

#endif /* HEADER_CURL_POP3_H */
Changes to jni/curl/lib/progress.c.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2020, 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 https://curl.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







|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2021, 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 https://curl.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
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
   pgrsSetDownloadCounter() - amount of data currently downloaded
   pgrsSetUploadCounter() - amount of data currently uploaded
   pgrsUpdate() - show progress
   pgrsDone() - transfer complete

*/

int Curl_pgrsDone(struct connectdata *conn)
{
  int rc;
  struct Curl_easy *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 */







|


<

|







133
134
135
136
137
138
139
140
141
142

143
144
145
146
147
148
149
150
151
   pgrsSetDownloadCounter() - amount of data currently downloaded
   pgrsSetUploadCounter() - amount of data currently uploaded
   pgrsUpdate() - show progress
   pgrsDone() - transfer complete

*/

int Curl_pgrsDone(struct Curl_easy *data)
{
  int rc;

  data->progress.lastshow = 0;
  rc = Curl_pgrsUpdate(data); /* 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 */
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
  else {
    data->progress.size_ul = 0;
    data->progress.flags &= ~PGRS_UL_SIZE_KNOWN;
  }
}

/* returns TRUE if it's time to show the progress meter */
static bool progress_calc(struct connectdata *conn, struct curltime now)
{
  curl_off_t timespent;
  curl_off_t timespent_ms; /* milliseconds */
  struct Curl_easy *data = conn->data;
  curl_off_t dl = data->progress.downloaded;
  curl_off_t ul = data->progress.uploaded;
  bool timetoshow = FALSE;

  /* The time spent so far (from the start) */
  data->progress.timespent = Curl_timediff_us(now, data->progress.start);
  timespent = (curl_off_t)data->progress.timespent/1000000; /* seconds */







|



<







366
367
368
369
370
371
372
373
374
375
376

377
378
379
380
381
382
383
  else {
    data->progress.size_ul = 0;
    data->progress.flags &= ~PGRS_UL_SIZE_KNOWN;
  }
}

/* returns TRUE if it's time to show the progress meter */
static bool progress_calc(struct Curl_easy *data, struct curltime now)
{
  curl_off_t timespent;
  curl_off_t timespent_ms; /* milliseconds */

  curl_off_t dl = data->progress.downloaded;
  curl_off_t ul = data->progress.uploaded;
  bool timetoshow = FALSE;

  /* The time spent so far (from the start) */
  data->progress.timespent = Curl_timediff_us(now, data->progress.start);
  timespent = (curl_off_t)data->progress.timespent/1000000; /* seconds */
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
        data->progress.ulspeed + data->progress.dlspeed;

  } /* Calculations end */
  return timetoshow;
}

#ifndef CURL_DISABLE_PROGRESS_METER
static void progress_meter(struct connectdata *conn)
{
  struct Curl_easy *data = conn->data;
  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;
  char time_left[10];







|

<







459
460
461
462
463
464
465
466
467

468
469
470
471
472
473
474
        data->progress.ulspeed + data->progress.dlspeed;

  } /* Calculations end */
  return timetoshow;
}

#ifndef CURL_DISABLE_PROGRESS_METER
static void progress_meter(struct Curl_easy *data)
{

  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;
  char time_left[10];
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
#endif


/*
 * Curl_pgrsUpdate() returns 0 for success or the value returned by the
 * progress callback!
 */
int Curl_pgrsUpdate(struct connectdata *conn)
{
  struct Curl_easy *data = conn->data;
  struct curltime now = Curl_now(); /* what time is it */
  bool showprogress = progress_calc(conn, now);
  if(!(data->progress.flags & PGRS_HIDE)) {
    if(data->set.fxferinfo) {
      int result;
      /* There's a callback set, call that */
      Curl_set_in_callback(data, true);
      result = data->set.fxferinfo(data->set.progress_client,
                                   data->progress.size_dl,







|

<

|







574
575
576
577
578
579
580
581
582

583
584
585
586
587
588
589
590
591
#endif


/*
 * Curl_pgrsUpdate() returns 0 for success or the value returned by the
 * progress callback!
 */
int Curl_pgrsUpdate(struct Curl_easy *data)
{

  struct curltime now = Curl_now(); /* what time is it */
  bool showprogress = progress_calc(data, now);
  if(!(data->progress.flags & PGRS_HIDE)) {
    if(data->set.fxferinfo) {
      int result;
      /* There's a callback set, call that */
      Curl_set_in_callback(data, true);
      result = data->set.fxferinfo(data->set.progress_client,
                                   data->progress.size_dl,
617
618
619
620
621
622
623
624
625
626
627
628
        if(result)
          failf(data, "Callback aborted");
        return result;
      }
    }

    if(showprogress)
      progress_meter(conn);
  }

  return 0;
}







|




613
614
615
616
617
618
619
620
621
622
623
624
        if(result)
          failf(data, "Callback aborted");
        return result;
      }
    }

    if(showprogress)
      progress_meter(data);
  }

  return 0;
}
Changes to jni/curl/lib/progress.h.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#ifndef HEADER_CURL_PROGRESS_H
#define HEADER_CURL_PROGRESS_H
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2020, 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 https://curl.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









|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#ifndef HEADER_CURL_PROGRESS_H
#define HEADER_CURL_PROGRESS_H
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2021, 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 https://curl.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
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
  TIMER_STARTTRANSFER,
  TIMER_POSTRANSFER,
  TIMER_STARTACCEPT,
  TIMER_REDIRECT,
  TIMER_LAST /* must be last */
} timerid;

int Curl_pgrsDone(struct connectdata *);
void Curl_pgrsStartNow(struct Curl_easy *data);
void Curl_pgrsSetDownloadSize(struct Curl_easy *data, curl_off_t size);
void Curl_pgrsSetUploadSize(struct Curl_easy *data, curl_off_t size);
void Curl_pgrsSetDownloadCounter(struct Curl_easy *data, curl_off_t size);
void Curl_pgrsSetUploadCounter(struct Curl_easy *data, curl_off_t size);
void Curl_ratelimit(struct Curl_easy *data, struct curltime now);
int Curl_pgrsUpdate(struct connectdata *);
void Curl_pgrsResetTransferSizes(struct Curl_easy *data);
struct curltime Curl_pgrsTime(struct Curl_easy *data, timerid timer);
timediff_t Curl_pgrsLimitWaitTime(curl_off_t cursize,
                                  curl_off_t startsize,
                                  curl_off_t limit,
                                  struct curltime start,
                                  struct curltime now);







|






|







36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
  TIMER_STARTTRANSFER,
  TIMER_POSTRANSFER,
  TIMER_STARTACCEPT,
  TIMER_REDIRECT,
  TIMER_LAST /* must be last */
} timerid;

int Curl_pgrsDone(struct Curl_easy *data);
void Curl_pgrsStartNow(struct Curl_easy *data);
void Curl_pgrsSetDownloadSize(struct Curl_easy *data, curl_off_t size);
void Curl_pgrsSetUploadSize(struct Curl_easy *data, curl_off_t size);
void Curl_pgrsSetDownloadCounter(struct Curl_easy *data, curl_off_t size);
void Curl_pgrsSetUploadCounter(struct Curl_easy *data, curl_off_t size);
void Curl_ratelimit(struct Curl_easy *data, struct curltime now);
int Curl_pgrsUpdate(struct Curl_easy *data);
void Curl_pgrsResetTransferSizes(struct Curl_easy *data);
struct curltime Curl_pgrsTime(struct Curl_easy *data, timerid timer);
timediff_t Curl_pgrsLimitWaitTime(curl_off_t cursize,
                                  curl_off_t startsize,
                                  curl_off_t limit,
                                  struct curltime start,
                                  struct curltime now);
Changes to jni/curl/lib/quic.h.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#ifndef HEADER_CURL_QUIC_H
#define HEADER_CURL_QUIC_H
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2020, 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 https://curl.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









|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#ifndef HEADER_CURL_QUIC_H
#define HEADER_CURL_QUIC_H
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2021, 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 https://curl.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
31
32
33
34
35
36
37
38

39
40
41
42
43

44
45
46
47
48
49
50

51
52
53
54
55
56
57
58
59
#ifdef USE_QUICHE
#include "vquic/quiche.h"
#endif

#include "urldata.h"

/* functions provided by the specific backends */
CURLcode Curl_quic_connect(struct connectdata *conn,

                           curl_socket_t sockfd,
                           int sockindex,
                           const struct sockaddr *addr,
                           socklen_t addrlen);
CURLcode Curl_quic_is_connected(struct connectdata *conn,

                                int sockindex,
                                bool *connected);
int Curl_quic_ver(char *p, size_t len);
CURLcode Curl_quic_done_sending(struct connectdata *conn);
void Curl_quic_done(struct Curl_easy *data, bool premature);
bool Curl_quic_data_pending(const struct Curl_easy *data);
void Curl_quic_disconnect(struct connectdata *conn, int tempindex);


#else /* ENABLE_QUIC */
#define Curl_quic_done_sending(x)
#define Curl_quic_done(x,y)
#define Curl_quic_data_pending(x)
#define Curl_quic_disconnect(x,y)
#endif /* !ENABLE_QUIC */

#endif /* HEADER_CURL_QUIC_H */







|
>




|
>



|


|
>





|



31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
#ifdef USE_QUICHE
#include "vquic/quiche.h"
#endif

#include "urldata.h"

/* functions provided by the specific backends */
CURLcode Curl_quic_connect(struct Curl_easy *data,
                           struct connectdata *conn,
                           curl_socket_t sockfd,
                           int sockindex,
                           const struct sockaddr *addr,
                           socklen_t addrlen);
CURLcode Curl_quic_is_connected(struct Curl_easy *data,
                                struct connectdata *conn,
                                int sockindex,
                                bool *connected);
int Curl_quic_ver(char *p, size_t len);
CURLcode Curl_quic_done_sending(struct Curl_easy *data);
void Curl_quic_done(struct Curl_easy *data, bool premature);
bool Curl_quic_data_pending(const struct Curl_easy *data);
void Curl_quic_disconnect(struct Curl_easy *data,
                          struct connectdata *conn, int tempindex);

#else /* ENABLE_QUIC */
#define Curl_quic_done_sending(x)
#define Curl_quic_done(x,y)
#define Curl_quic_data_pending(x)
#define Curl_quic_disconnect(x,y,z)
#endif /* !ENABLE_QUIC */

#endif /* HEADER_CURL_QUIC_H */
Changes to jni/curl/lib/rtsp.c.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2020, 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 https://curl.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"







|
















|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2021, 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 https://curl.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_RTSP) && !defined(USE_HYPER)

#include "urldata.h"
#include <curl/curl.h>
#include "transfer.h"
#include "sendf.h"
#include "multiif.h"
#include "http.h"
44
45
46
47
48
49
50
51
52
53
54

55

56
57
58
59
60
61
62
63
64
65
66
67
68
69

70

71
72
73
74
75
76
77
78
79

80
81
82
83
84
85
86
87
88
89
90
91
92

#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);


/*
 * 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 Curl_easy *data,
                                   struct connectdata *conn,
                                   ssize_t *nread,
                                   bool *readmore);

static CURLcode rtsp_setup_connection(struct connectdata *conn);

static unsigned int rtsp_conncheck(struct connectdata *check,

                                   unsigned int checks_to_perform);

/* 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)
{
  /* write mode */

  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 */







|
|
|
|
>
|
>













|
>
|
>





|



>





|







44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97

#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 Curl_easy *data, bool *done);
static CURLcode rtsp_done(struct Curl_easy *data, CURLcode, bool premature);
static CURLcode rtsp_connect(struct Curl_easy *data, bool *done);
static CURLcode rtsp_disconnect(struct Curl_easy *data,
                                struct connectdata *conn, bool dead);
static int rtsp_getsock_do(struct Curl_easy *data,
                           struct connectdata *conn, curl_socket_t *socks);

/*
 * 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 Curl_easy *data,
                                   struct connectdata *conn,
                                   ssize_t *nread,
                                   bool *readmore);

static CURLcode rtsp_setup_connection(struct Curl_easy *data,
                                      struct connectdata *conn);
static unsigned int rtsp_conncheck(struct Curl_easy *data,
                                   struct connectdata *check,
                                   unsigned int checks_to_perform);

/* 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 Curl_easy *data, struct connectdata *conn,
                           curl_socket_t *socks)
{
  /* write mode */
  (void)data;
  socks[0] = conn->sock[FIRSTSOCKET];
  return GETSOCK_WRITESOCK(0);
}

static
CURLcode rtp_client_write(struct Curl_easy *data, char *ptr, size_t len);


/*
 * RTSP handler interface.
 */
const struct Curl_handler Curl_handler_rtsp = {
  "RTSP",                               /* scheme */
107
108
109
110
111
112
113
114

115
116

117
118
119
120
121
122
123
124
125
  PORT_RTSP,                            /* defport */
  CURLPROTO_RTSP,                       /* protocol */
  CURLPROTO_RTSP,                       /* family */
  PROTOPT_NONE                          /* flags */
};


static CURLcode rtsp_setup_connection(struct connectdata *conn)

{
  struct RTSP *rtsp;


  conn->data->req.p.rtsp = rtsp = calloc(1, sizeof(struct RTSP));
  if(!rtsp)
    return CURLE_OUT_OF_MEMORY;

  return CURLE_OK;
}









|
>


>

|







112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
  PORT_RTSP,                            /* defport */
  CURLPROTO_RTSP,                       /* protocol */
  CURLPROTO_RTSP,                       /* family */
  PROTOPT_NONE                          /* flags */
};


static CURLcode rtsp_setup_connection(struct Curl_easy *data,
                                      struct connectdata *conn)
{
  struct RTSP *rtsp;
  (void)conn;

  data->req.p.rtsp = rtsp = calloc(1, sizeof(struct RTSP));
  if(!rtsp)
    return CURLE_OUT_OF_MEMORY;

  return CURLE_OK;
}


152
153
154
155
156
157
158
159

160
161
162

163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191

192
193

194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240

  return ret_val;
}

/*
 * Function to check on various aspects of a connection.
 */
static unsigned int rtsp_conncheck(struct connectdata *check,

                                   unsigned int checks_to_perform)
{
  unsigned int ret_val = CONNRESULT_NONE;


  if(checks_to_perform & CONNCHECK_ISDEAD) {
    if(rtsp_connisdead(check))
      ret_val |= CONNRESULT_DEAD;
  }

  return ret_val;
}


static CURLcode rtsp_connect(struct connectdata *conn, bool *done)
{
  CURLcode httpStatus;
  struct Curl_easy *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 Curl_easy *data = conn->data;
  struct RTSP *rtsp = data->req.p.rtsp;
  CURLcode httpStatus;

  /* 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 */
    long CSeq_sent = rtsp->CSeq_sent;
    long 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;
    }
    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);
    }
  }

  return httpStatus;
}

static CURLcode rtsp_do(struct connectdata *conn, bool *done)
{
  struct Curl_easy *data = conn->data;
  CURLcode result = CURLE_OK;
  Curl_RtspReq rtspreq = data->set.rtspreq;
  struct RTSP *rtsp = data->req.p.rtsp;
  struct dynbuf req_buffer;
  curl_off_t postsize = 0; /* for ANNOUNCE and SET_PARAMETER */
  curl_off_t putsize = 0; /* for ANNOUNCE and SET_PARAMETER */








|
>



>


|







|


<

|







|




|
>


>





|


<







|












|







|

|







159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184

185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211

212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249

  return ret_val;
}

/*
 * Function to check on various aspects of a connection.
 */
static unsigned int rtsp_conncheck(struct Curl_easy *data,
                                   struct connectdata *conn,
                                   unsigned int checks_to_perform)
{
  unsigned int ret_val = CONNRESULT_NONE;
  (void)data;

  if(checks_to_perform & CONNCHECK_ISDEAD) {
    if(rtsp_connisdead(conn))
      ret_val |= CONNRESULT_DEAD;
  }

  return ret_val;
}


static CURLcode rtsp_connect(struct Curl_easy *data, bool *done)
{
  CURLcode httpStatus;


  httpStatus = Curl_http_connect(data, 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;

  data->conn->proto.rtspc.rtp_channel = -1;

  return httpStatus;
}

static CURLcode rtsp_disconnect(struct Curl_easy *data,
                                struct connectdata *conn, bool dead)
{
  (void) dead;
  (void) data;
  Curl_safefree(conn->proto.rtspc.rtp_buf);
  return CURLE_OK;
}


static CURLcode rtsp_done(struct Curl_easy *data,
                          CURLcode status, bool premature)
{

  struct RTSP *rtsp = data->req.p.rtsp;
  CURLcode httpStatus;

  /* Bypass HTTP empty-reply checks on receive */
  if(data->set.rtspreq == RTSPREQ_RECEIVE)
    premature = TRUE;

  httpStatus = Curl_http_done(data, status, premature);

  if(rtsp) {
    /* Check the sequence numbers */
    long CSeq_sent = rtsp->CSeq_sent;
    long 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;
    }
    if(data->set.rtspreq == RTSPREQ_RECEIVE &&
            (data->conn->proto.rtspc.rtp_channel == -1)) {
      infof(data, "Got an RTP Receive with a CSeq of %ld\n", CSeq_recv);
    }
  }

  return httpStatus;
}

static CURLcode rtsp_do(struct Curl_easy *data, bool *done)
{
  struct connectdata *conn = data->conn;
  CURLcode result = CURLE_OK;
  Curl_RtspReq rtspreq = data->set.rtspreq;
  struct RTSP *rtsp = data->req.p.rtsp;
  struct dynbuf req_buffer;
  curl_off_t postsize = 0; /* for ANNOUNCE and SET_PARAMETER */
  curl_off_t putsize = 0; /* for ANNOUNCE and SET_PARAMETER */

326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
    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(data->state.aptr.rtsp_transport);

      data->state.aptr.rtsp_transport =
        aprintf("Transport: %s\r\n",







|







335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
    p_stream_uri = data->set.str[STRING_RTSP_STREAM_URI];
  }
  else {
    p_stream_uri = "*";
  }

  /* Transport Header for SETUP requests */
  p_transport = Curl_checkheaders(data, "Transport");
  if(rtspreq == RTSPREQ_SETUP && !p_transport) {
    /* New Transport: setting? */
    if(data->set.str[STRING_RTSP_TRANSPORT]) {
      Curl_safefree(data->state.aptr.rtsp_transport);

      data->state.aptr.rtsp_transport =
        aprintf("Transport: %s\r\n",
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387

388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435

    p_transport = data->state.aptr.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(data->state.aptr.accept_encoding);
      data->state.aptr.accept_encoding =
        aprintf("Accept-Encoding: %s\r\n", data->set.str[STRING_ENCODING]);

      if(!data->state.aptr.accept_encoding)
        return CURLE_OUT_OF_MEMORY;

      p_accept_encoding = data->state.aptr.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") && data->state.aptr.uagent) {
    Curl_safefree(data->state.aptr.uagent);
    data->state.aptr.uagent = NULL;
  }
  else if(!Curl_checkheaders(conn, "User-Agent") &&
          data->set.str[STRING_USERAGENT]) {
    p_uagent = data->state.aptr.uagent;
  }

  /* setup the authentication headers */

  result = Curl_http_output_auth(conn, p_request, p_stream_uri, FALSE);
  if(result)
    return result;

  p_proxyuserpwd = data->state.aptr.proxyuserpwd;
  p_userpwd = data->state.aptr.userpwd;

  /* Referrer */
  Curl_safefree(data->state.aptr.ref);
  if(data->change.referer && !Curl_checkheaders(conn, "Referer"))
    data->state.aptr.ref = aprintf("Referer: %s\r\n", data->change.referer);
  else
    data->state.aptr.ref = NULL;

  p_referrer = data->state.aptr.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(data->state.aptr.rangeline);
      data->state.aptr.rangeline = aprintf("Range: %s\r\n", data->state.range);
      p_range = data->state.aptr.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 */
  Curl_dyn_init(&req_buffer, DYN_RTSP_REQ_HEADER);








|



|
















|



|





>
|








|
















|









|



|







359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445

    p_transport = data->state.aptr.rtsp_transport;
  }

  /* Accept Headers for DESCRIBE requests */
  if(rtspreq == RTSPREQ_DESCRIBE) {
    /* Accept Header */
    p_accept = Curl_checkheaders(data, "Accept")?
      NULL:"Accept: application/sdp\r\n";

    /* Accept-Encoding header */
    if(!Curl_checkheaders(data, "Accept-Encoding") &&
       data->set.str[STRING_ENCODING]) {
      Curl_safefree(data->state.aptr.accept_encoding);
      data->state.aptr.accept_encoding =
        aprintf("Accept-Encoding: %s\r\n", data->set.str[STRING_ENCODING]);

      if(!data->state.aptr.accept_encoding)
        return CURLE_OUT_OF_MEMORY;

      p_accept_encoding = data->state.aptr.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(data, "User-Agent") && data->state.aptr.uagent) {
    Curl_safefree(data->state.aptr.uagent);
    data->state.aptr.uagent = NULL;
  }
  else if(!Curl_checkheaders(data, "User-Agent") &&
          data->set.str[STRING_USERAGENT]) {
    p_uagent = data->state.aptr.uagent;
  }

  /* setup the authentication headers */
  result = Curl_http_output_auth(data, conn, p_request, HTTPREQ_GET,
                                 p_stream_uri, FALSE);
  if(result)
    return result;

  p_proxyuserpwd = data->state.aptr.proxyuserpwd;
  p_userpwd = data->state.aptr.userpwd;

  /* Referrer */
  Curl_safefree(data->state.aptr.ref);
  if(data->change.referer && !Curl_checkheaders(data, "Referer"))
    data->state.aptr.ref = aprintf("Referer: %s\r\n", data->change.referer);
  else
    data->state.aptr.ref = NULL;

  p_referrer = data->state.aptr.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(data, "Range") && data->state.range) {
      Curl_safefree(data->state.aptr.rangeline);
      data->state.aptr.rangeline = aprintf("Range: %s\r\n", data->state.range);
      p_range = data->state.aptr.rangeline;
    }
  }

  /*
   * Sanity check the custom headers
   */
  if(Curl_checkheaders(data, "CSeq")) {
    failf(data, "CSeq cannot be set as a custom header.");
    return CURLE_RTSP_CSEQ_ERROR;
  }
  if(Curl_checkheaders(data, "Session")) {
    failf(data, "Session ID cannot be set as a custom header.");
    return CURLE_BAD_FUNCTION_ARGUMENT;
  }

  /* Initialize a dynamic send buffer */
  Curl_dyn_init(&req_buffer, DYN_RTSP_REQ_HEADER);

480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
  Curl_safefree(data->state.aptr.userpwd);
  data->state.aptr.userpwd = NULL;

  if(result)
    return result;

  if((rtspreq == RTSPREQ_SETUP) || (rtspreq == RTSPREQ_DESCRIBE)) {
    result = Curl_add_timecondition(conn, &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) {








|




|







490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
  Curl_safefree(data->state.aptr.userpwd);
  data->state.aptr.userpwd = NULL;

  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(data, FALSE, &req_buffer);
  if(result)
    return result;

  if(rtspreq == RTSPREQ_ANNOUNCE ||
     rtspreq == RTSPREQ_SET_PARAMETER ||
     rtspreq == RTSPREQ_GET_PARAMETER) {

508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
        (data->set.postfields? (curl_off_t)strlen(data->set.postfields):0);
      data->state.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_dyn_addf(&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_dyn_addf(&req_buffer,
                                 "Content-Type: text/parameters\r\n");
          if(result)
            return result;
        }
      }

      if(rtspreq == RTSPREQ_ANNOUNCE) {
        if(!Curl_checkheaders(conn, "Content-Type")) {
          result = Curl_dyn_addf(&req_buffer,
                                 "Content-Type: application/sdp\r\n");
          if(result)
            return result;
        }
      }








|










|








|







518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
        (data->set.postfields? (curl_off_t)strlen(data->set.postfields):0);
      data->state.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(data, "Content-Length")) {
        result =
          Curl_dyn_addf(&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(data, "Content-Type")) {
          result = Curl_dyn_addf(&req_buffer,
                                 "Content-Type: text/parameters\r\n");
          if(result)
            return result;
        }
      }

      if(rtspreq == RTSPREQ_ANNOUNCE) {
        if(!Curl_checkheaders(data, "Content-Type")) {
          result = Curl_dyn_addf(&req_buffer,
                                 "Content-Type: application/sdp\r\n");
          if(result)
            return result;
        }
      }

560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
    result = Curl_dyn_addn(&req_buffer, data->set.postfields,
                           (size_t)postsize);
    if(result)
      return result;
  }

  /* issue the request */
  result = Curl_buffer_send(&req_buffer, conn,
                            &data->info.request_size, 0, FIRSTSOCKET);
  if(result) {
    failf(data, "Failed sending RTSP request");
    return result;
  }

  Curl_setup_transfer(data, FIRSTSOCKET, -1, TRUE, putsize?FIRSTSOCKET:-1);

  /* Increment the CSeq on success */
  data->state.rtsp_next_client_CSeq++;

  if(data->req.writebytecount) {
    /* if a request-body has been sent off, we make sure this progress is
       noted properly */
    Curl_pgrsSetUploadCounter(data, data->req.writebytecount);
    if(Curl_pgrsUpdate(conn))
      result = CURLE_ABORTED_BY_CALLBACK;
  }

  return result;
}









|















|







570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
    result = Curl_dyn_addn(&req_buffer, data->set.postfields,
                           (size_t)postsize);
    if(result)
      return result;
  }

  /* issue the request */
  result = Curl_buffer_send(&req_buffer, data,
                            &data->info.request_size, 0, FIRSTSOCKET);
  if(result) {
    failf(data, "Failed sending RTSP request");
    return result;
  }

  Curl_setup_transfer(data, FIRSTSOCKET, -1, TRUE, putsize?FIRSTSOCKET:-1);

  /* Increment the CSeq on success */
  data->state.rtsp_next_client_CSeq++;

  if(data->req.writebytecount) {
    /* if a request-body has been sent off, we make sure this progress is
       noted properly */
    Curl_pgrsSetUploadCounter(data, data->req.writebytecount);
    if(Curl_pgrsUpdate(data))
      result = CURLE_ABORTED_BY_CALLBACK;
  }

  return result;
}


638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
        *readmore = TRUE;
        break;
      }
      /* 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;







|







648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
        *readmore = TRUE;
        break;
      }
      /* 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(data, &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;
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
  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 Curl_easy *data = conn->data;
  size_t wrote;
  curl_write_callback writeit;
  void *user_ptr;

  if(len == 0) {
    failf(data, "Cannot write a 0 size RTP packet.");
    return CURLE_WRITE_ERROR;







|

<







719
720
721
722
723
724
725
726
727

728
729
730
731
732
733
734
  rtspc->rtp_buf = NULL;
  rtspc->rtp_bufsize = 0;

  return CURLE_OK;
}

static
CURLcode rtp_client_write(struct Curl_easy *data, char *ptr, size_t len)
{

  size_t wrote;
  curl_write_callback writeit;
  void *user_ptr;

  if(len == 0) {
    failf(data, "Cannot write a 0 size RTP packet.");
    return CURLE_WRITE_ERROR;
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
    failf(data, "Failed writing RTP data");
    return CURLE_WRITE_ERROR;
  }

  return CURLE_OK;
}

CURLcode Curl_rtsp_parseheader(struct connectdata *conn,
                               char *header)
{
  struct Curl_easy *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.p.rtsp;







|
<

<







760
761
762
763
764
765
766
767

768

769
770
771
772
773
774
775
    failf(data, "Failed writing RTP data");
    return CURLE_WRITE_ERROR;
  }

  return CURLE_OK;
}

CURLcode Curl_rtsp_parseheader(struct Curl_easy *data, char *header)

{

  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.p.rtsp;
822
823
824
825
826
827
828
829
      memcpy(data->set.str[STRING_RTSP_SESSION_ID], start, idlen);
      (data->set.str[STRING_RTSP_SESSION_ID])[idlen] = '\0';
    }
  }
  return CURLE_OK;
}

#endif /* CURL_DISABLE_RTSP */







|
829
830
831
832
833
834
835
836
      memcpy(data->set.str[STRING_RTSP_SESSION_ID], start, idlen);
      (data->set.str[STRING_RTSP_SESSION_ID])[idlen] = '\0';
    }
  }
  return CURLE_OK;
}

#endif /* CURL_DISABLE_RTSP or using Hyper */
Changes to jni/curl/lib/rtsp.h.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23




24
25
26
27
28
29
30
31
32
33
34
35
#ifndef HEADER_CURL_RTSP_H
#define HEADER_CURL_RTSP_H
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2020, 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 https://curl.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;

CURLcode Curl_rtsp_parseheader(struct connectdata *conn, char *header);

#else
/* disabled */
#define Curl_rtsp_parseheader(x,y) CURLE_NOT_BUILT_IN

#endif /* CURL_DISABLE_RTSP */










|













>
>
>
>




|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
#ifndef HEADER_CURL_RTSP_H
#define HEADER_CURL_RTSP_H
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2021, 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 https://curl.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_HYPER
#define CURL_DISABLE_RTSP
#endif

#ifndef CURL_DISABLE_RTSP

extern const struct Curl_handler Curl_handler_rtsp;

CURLcode Curl_rtsp_parseheader(struct Curl_easy *data, char *header);

#else
/* disabled */
#define Curl_rtsp_parseheader(x,y) CURLE_NOT_BUILT_IN

#endif /* CURL_DISABLE_RTSP */

Changes to jni/curl/lib/select.c.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2020, 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 https://curl.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







|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2021, 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 https://curl.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
126
127
128
129
130
131
132

133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
#endif /* HAVE_POLL_FINE */
#endif /* USE_WINSOCK */
  if(r)
    r = -1;
  return r;
}


/*
 * This is a wrapper around select() to aid in Windows compatibility.
 * A negative timeout value makes this function wait indefinitely,
 * unless 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 signalled file descriptors
 */
int Curl_select(curl_socket_t maxfd,   /* highest socket number */
                fd_set *fds_read,      /* sockets ready for reading */
                fd_set *fds_write,     /* sockets ready for writing */
                fd_set *fds_err,       /* sockets with errors */
                timediff_t timeout_ms) /* milliseconds to wait */
{
  struct timeval pending_tv;
  struct timeval *ptimeout;

#ifdef USE_WINSOCK
  /* WinSock select() can't handle zero events.  See the comment below. */
  if((!fds_read || fds_read->fd_count == 0) &&







>











|
|
|
|
|







126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
#endif /* HAVE_POLL_FINE */
#endif /* USE_WINSOCK */
  if(r)
    r = -1;
  return r;
}

#ifndef HAVE_POLL_FINE
/*
 * This is a wrapper around select() to aid in Windows compatibility.
 * A negative timeout value makes this function wait indefinitely,
 * unless 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 signalled file descriptors
 */
static int our_select(curl_socket_t maxfd,   /* highest socket number */
                      fd_set *fds_read,      /* sockets ready for reading */
                      fd_set *fds_write,     /* sockets ready for writing */
                      fd_set *fds_err,       /* sockets with errors */
                      timediff_t timeout_ms) /* milliseconds to wait */
{
  struct timeval pending_tv;
  struct timeval *ptimeout;

#ifdef USE_WINSOCK
  /* WinSock select() can't handle zero events.  See the comment below. */
  if((!fds_read || fds_read->fd_count == 0) &&
215
216
217
218
219
220
221


222
223
224
225
226
227
228
                fds_read && fds_read->fd_count ? fds_read : NULL,
                fds_write && fds_write->fd_count ? fds_write : NULL,
                fds_err && fds_err->fd_count ? fds_err : NULL, ptimeout);
#else
  return select((int)maxfd + 1, fds_read, fds_write, fds_err, ptimeout);
#endif
}



/*
 * 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.
 *







>
>







216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
                fds_read && fds_read->fd_count ? fds_read : NULL,
                fds_write && fds_write->fd_count ? fds_write : NULL,
                fds_err && fds_err->fd_count ? fds_err : NULL, ptimeout);
#else
  return select((int)maxfd + 1, fds_read, fds_write, fds_err, ptimeout);
#endif
}

#endif

/*
 * 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.
 *
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422

  /*
     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 = Curl_select(maxfd, &fds_read, &fds_write, &fds_err, timeout_ms);
  if(r <= 0)
    return r;

  r = 0;
  for(i = 0; i < nfds; i++) {
    ufds[i].revents = 0;
    if(ufds[i].fd == CURL_SOCKET_BAD)







|







411
412
413
414
415
416
417
418
419
420
421
422
423
424
425

  /*
     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 = our_select(maxfd, &fds_read, &fds_write, &fds_err, timeout_ms);
  if(r <= 0)
    return r;

  r = 0;
  for(i = 0; i < nfds; i++) {
    ufds[i].revents = 0;
    if(ufds[i].fd == CURL_SOCKET_BAD)
Changes to jni/curl/lib/select.h.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#ifndef HEADER_CURL_SELECT_H
#define HEADER_CURL_SELECT_H
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2020, 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 https://curl.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









|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#ifndef HEADER_CURL_SELECT_H
#define HEADER_CURL_SELECT_H
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2021, 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 https://curl.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
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
#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)

int Curl_select(curl_socket_t maxfd,
                fd_set *fds_read,
                fd_set *fds_write,
                fd_set *fds_err,
                timediff_t timeout_ms);

int Curl_socket_check(curl_socket_t readfd, curl_socket_t readfd2,
                      curl_socket_t writefd,
                      timediff_t timeout_ms);
#define SOCKET_READABLE(x,z) \
  Curl_socket_check(x, CURL_SOCKET_BAD, CURL_SOCKET_BAD, z)
#define SOCKET_WRITABLE(x,z) \
  Curl_socket_check(CURL_SOCKET_BAD, CURL_SOCKET_BAD, x, z)







<
<
<
<
<
<







68
69
70
71
72
73
74






75
76
77
78
79
80
81
#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)







int Curl_socket_check(curl_socket_t readfd, curl_socket_t readfd2,
                      curl_socket_t writefd,
                      timediff_t timeout_ms);
#define SOCKET_READABLE(x,z) \
  Curl_socket_check(x, CURL_SOCKET_BAD, CURL_SOCKET_BAD, z)
#define SOCKET_WRITABLE(x,z) \
  Curl_socket_check(CURL_SOCKET_BAD, CURL_SOCKET_BAD, x, z)
Changes to jni/curl/lib/sendf.c.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2020, 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 https://curl.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







|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2021, 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 https://curl.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
138
139
140
141
142
143
144
145

146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
bool Curl_recv_has_postponed_data(struct connectdata *conn, int sockindex)
{
  struct postponed_data * const psnd = &(conn->postponed[sockindex]);
  return psnd->buffer && psnd->allocated_size &&
         psnd->recv_size > psnd->recv_processed;
}

static CURLcode pre_receive_plain(struct connectdata *conn, int num)

{
  const curl_socket_t sockfd = conn->sock[num];
  struct postponed_data * const psnd = &(conn->postponed[num]);
  size_t bytestorecv = psnd->allocated_size - psnd->recv_size;
  /* WinSock will destroy unread received data if send() is
     failed.
     To avoid lossage of received data, recv() must be
     performed before every send() if any incoming data is
     available. However, skip this, if buffer is already full. */
  if((conn->handler->protocol&PROTO_FAMILY_HTTP) != 0 &&
     conn->recv[num] == Curl_recv_plain &&
     (!psnd->buffer || bytestorecv)) {
    const int readymask = Curl_socket_check(sockfd, CURL_SOCKET_BAD,
                                            CURL_SOCKET_BAD, 0);
    if(readymask != -1 && (readymask & CURL_CSELECT_IN) != 0) {
      /* Have some incoming data */
      if(!psnd->buffer) {
        /* Use buffer double default size for intermediate buffer */
        psnd->allocated_size = 2 * conn->data->set.buffer_size;
        psnd->buffer = malloc(psnd->allocated_size);
        if(!psnd->buffer)
          return CURLE_OUT_OF_MEMORY;
        psnd->recv_size = 0;
        psnd->recv_processed = 0;
#ifdef DEBUGBUILD
        psnd->bindsock = sockfd; /* Used only for DEBUGASSERT */







|
>


















|







138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
bool Curl_recv_has_postponed_data(struct connectdata *conn, int sockindex)
{
  struct postponed_data * const psnd = &(conn->postponed[sockindex]);
  return psnd->buffer && psnd->allocated_size &&
         psnd->recv_size > psnd->recv_processed;
}

static CURLcode pre_receive_plain(struct Curl_easy *data,
                                  struct connectdata *conn, int num)
{
  const curl_socket_t sockfd = conn->sock[num];
  struct postponed_data * const psnd = &(conn->postponed[num]);
  size_t bytestorecv = psnd->allocated_size - psnd->recv_size;
  /* WinSock will destroy unread received data if send() is
     failed.
     To avoid lossage of received data, recv() must be
     performed before every send() if any incoming data is
     available. However, skip this, if buffer is already full. */
  if((conn->handler->protocol&PROTO_FAMILY_HTTP) != 0 &&
     conn->recv[num] == Curl_recv_plain &&
     (!psnd->buffer || bytestorecv)) {
    const int readymask = Curl_socket_check(sockfd, CURL_SOCKET_BAD,
                                            CURL_SOCKET_BAD, 0);
    if(readymask != -1 && (readymask & CURL_CSELECT_IN) != 0) {
      /* Have some incoming data */
      if(!psnd->buffer) {
        /* Use buffer double default size for intermediate buffer */
        psnd->allocated_size = 2 * data->set.buffer_size;
        psnd->buffer = malloc(psnd->allocated_size);
        if(!psnd->buffer)
          return CURLE_OUT_OF_MEMORY;
        psnd->recv_size = 0;
        psnd->recv_processed = 0;
#ifdef DEBUGBUILD
        psnd->bindsock = sockfd; /* Used only for DEBUGASSERT */
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
/* Use "do-nothing" macros instead of functions when workaround not used */
bool Curl_recv_has_postponed_data(struct connectdata *conn, int sockindex)
{
  (void)conn;
  (void)sockindex;
  return false;
}
#define pre_receive_plain(c,n) CURLE_OK
#define get_pre_recved(c,n,b,l) 0
#endif /* ! USE_RECV_BEFORE_SEND_WORKAROUND */

/* Curl_infof() is for info message along the way */

void Curl_infof(struct Curl_easy *data, const char *fmt, ...)
{







|







227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
/* Use "do-nothing" macros instead of functions when workaround not used */
bool Curl_recv_has_postponed_data(struct connectdata *conn, int sockindex)
{
  (void)conn;
  (void)sockindex;
  return false;
}
#define pre_receive_plain(d,c,n) CURLE_OK
#define get_pre_recved(c,n,b,l) 0
#endif /* ! USE_RECV_BEFORE_SEND_WORKAROUND */

/* Curl_infof() is for info message along the way */

void Curl_infof(struct Curl_easy *data, const char *fmt, ...)
{
263
264
265
266
267
268
269

270
271
272
273
274
275
276

/* Curl_failf() is for messages stating why we failed.
 * The message SHALL NOT include any LF or CR.
 */

void Curl_failf(struct Curl_easy *data, const char *fmt, ...)
{

  if(data->set.verbose || data->set.errorbuffer) {
    va_list ap;
    size_t len;
    char error[CURL_ERROR_SIZE + 2];
    va_start(ap, fmt);
    (void)mvsnprintf(error, CURL_ERROR_SIZE, fmt, ap);
    len = strlen(error);







>







264
265
266
267
268
269
270
271
272
273
274
275
276
277
278

/* Curl_failf() is for messages stating why we failed.
 * The message SHALL NOT include any LF or CR.
 */

void Curl_failf(struct Curl_easy *data, const char *fmt, ...)
{
  DEBUGASSERT(!strchr(fmt, '\n'));
  if(data->set.verbose || data->set.errorbuffer) {
    va_list ap;
    size_t len;
    char error[CURL_ERROR_SIZE + 2];
    va_start(ap, fmt);
    (void)mvsnprintf(error, CURL_ERROR_SIZE, fmt, ap);
    len = strlen(error);
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302





303
304
305
306
307
308
309
310
311
312
/*
 * 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.
 */
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 */







|







>
>
>
>
>
|

|







290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
/*
 * 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.
 */
CURLcode Curl_write(struct Curl_easy *data,
                    curl_socket_t sockfd,
                    const void *mem,
                    size_t len,
                    ssize_t *written)
{
  ssize_t bytes_written;
  CURLcode result = CURLE_OK;
  struct connectdata *conn;
  int num;
  DEBUGASSERT(data);
  DEBUGASSERT(data->conn);
  conn = data->conn;
  num = (sockfd == conn->sock[SECONDARYSOCKET]);

  bytes_written = conn->send[num](data, 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 */
321
322
323
324
325
326
327
328
329
330

331
332





333
334
335
336
337
338
339
340
341
342
343
344
345

  default:
    /* we got a specific curlcode, forward it */
    return result;
  }
}

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;





  /* WinSock will destroy unread received data if send() is
     failed.
     To avoid lossage of received data, recv() must be
     performed before every send() if any incoming data is
     available. */
  if(pre_receive_plain(conn, num)) {
    *code = CURLE_OUT_OF_MEMORY;
    return -1;
  }

#if defined(MSG_FASTOPEN) && !defined(TCP_FASTOPEN_CONNECT) /* Linux */
  if(conn->bits.tcp_fastopen) {
    bytes_written = sendto(sockfd, mem, len, MSG_FASTOPEN,







|


>
|

>
>
>
>
>





|







328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358

  default:
    /* we got a specific curlcode, forward it */
    return result;
  }
}

ssize_t Curl_send_plain(struct Curl_easy *data, int num,
                        const void *mem, size_t len, CURLcode *code)
{
  struct connectdata *conn;
  curl_socket_t sockfd;
  ssize_t bytes_written;

  DEBUGASSERT(data);
  DEBUGASSERT(data->conn);
  conn = data->conn;
  sockfd = conn->sock[num];
  /* WinSock will destroy unread received data if send() is
     failed.
     To avoid lossage of received data, recv() must be
     performed before every send() if any incoming data is
     available. */
  if(pre_receive_plain(data, conn, num)) {
    *code = CURLE_OUT_OF_MEMORY;
    return -1;
  }

#if defined(MSG_FASTOPEN) && !defined(TCP_FASTOPEN_CONNECT) /* Linux */
  if(conn->bits.tcp_fastopen) {
    bytes_written = sendto(sockfd, mem, len, MSG_FASTOPEN,
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396



397
398
399
400
401
402
403
404
405
406
407
408

409
410




411
412
413
414
415
416
417
      ) {
      /* this is just a case of EWOULDBLOCK */
      bytes_written = 0;
      *code = CURLE_AGAIN;
    }
    else {
      char buffer[STRERROR_LEN];
      failf(conn->data, "Send failure: %s",
            Curl_strerror(err, buffer, sizeof(buffer)));
      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()
 */
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;
}

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;




  /* Check and return data that already received and storied in internal
     intermediate buffer */
  nread = get_pre_recved(conn, num, buf, len);
  if(nread > 0) {
    *code = CURLE_OK;
    return nread;
  }







|

|











|





<

>
>
>
|

|
<
<




|


>
|

>
>
>
>







381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407

408
409
410
411
412
413
414


415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
      ) {
      /* this is just a case of EWOULDBLOCK */
      bytes_written = 0;
      *code = CURLE_AGAIN;
    }
    else {
      char buffer[STRERROR_LEN];
      failf(data, "Send failure: %s",
            Curl_strerror(err, buffer, sizeof(buffer)));
      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()
 */
CURLcode Curl_write_plain(struct Curl_easy *data,
                          curl_socket_t sockfd,
                          const void *mem,
                          size_t len,
                          ssize_t *written)
{

  CURLcode result;
  struct connectdata *conn = data->conn;
  int num;
  DEBUGASSERT(conn);
  num = (sockfd == conn->sock[SECONDARYSOCKET]);

  *written = Curl_send_plain(data, num, mem, len, &result);



  return result;
}

ssize_t Curl_recv_plain(struct Curl_easy *data, int num, char *buf,
                        size_t len, CURLcode *code)
{
  struct connectdata *conn;
  curl_socket_t sockfd;
  ssize_t nread;
  DEBUGASSERT(data);
  DEBUGASSERT(data->conn);
  conn = data->conn;
  sockfd = conn->sock[num];
  /* Check and return data that already received and storied in internal
     intermediate buffer */
  nread = get_pre_recved(conn, num, buf, len);
  if(nread > 0) {
    *code = CURLE_OK;
    return nread;
  }
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
#endif
      ) {
      /* this is just a case of EWOULDBLOCK */
      *code = CURLE_AGAIN;
    }
    else {
      char buffer[STRERROR_LEN];
      failf(conn->data, "Recv failure: %s",
            Curl_strerror(err, buffer, sizeof(buffer)));
      conn->data->state.os_errno = err;
      *code = CURLE_RECV_ERROR;
    }
  }
  return nread;
}

static CURLcode pausewrite(struct Curl_easy *data,







|

|







452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
#endif
      ) {
      /* this is just a case of EWOULDBLOCK */
      *code = CURLE_AGAIN;
    }
    else {
      char buffer[STRERROR_LEN];
      failf(data, "Recv failure: %s",
            Curl_strerror(err, buffer, sizeof(buffer)));
      data->state.os_errno = err;
      *code = CURLE_RECV_ERROR;
    }
  }
  return nread;
}

static CURLcode pausewrite(struct Curl_easy *data,
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
}


/* 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.
 */
static CURLcode chop_write(struct connectdata *conn,
                           int type,
                           char *optr,
                           size_t olen)
{
  struct Curl_easy *data = conn->data;
  curl_write_callback writeheader = NULL;
  curl_write_callback writebody = NULL;
  char *ptr = optr;
  size_t len = olen;

  if(!len)
    return CURLE_OK;







|




|







513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
}


/* 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.
 */
static CURLcode chop_write(struct Curl_easy *data,
                           int type,
                           char *optr,
                           size_t olen)
{
  struct connectdata *conn = data->conn;
  curl_write_callback writeheader = NULL;
  curl_write_callback writebody = NULL;
  char *ptr = optr;
  size_t len = olen;

  if(!len)
    return CURLE_OK;
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
   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.
 */
CURLcode Curl_client_write(struct connectdata *conn,
                           int type,
                           char *ptr,
                           size_t len)
{
  struct Curl_easy *data = conn->data;

  if(0 == len)
    len = strlen(ptr);

  DEBUGASSERT(type <= 3);

  /* FTP data may need conversion. */
  if((type & CLIENTWRITE_BODY) &&







|




<
|







608
609
610
611
612
613
614
615
616
617
618
619

620
621
622
623
624
625
626
627
   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.
 */
CURLcode Curl_client_write(struct Curl_easy *data,
                           int type,
                           char *ptr,
                           size_t len)
{

  struct connectdata *conn = data->conn;
  if(0 == len)
    len = strlen(ptr);

  DEBUGASSERT(type <= 3);

  /* FTP data may need conversion. */
  if((type & CLIENTWRITE_BODY) &&
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632

#ifdef CURL_DO_LINEEND_CONV
    /* convert end-of-line markers */
    len = convert_lineends(data, ptr, len);
#endif /* CURL_DO_LINEEND_CONV */
    }

  return chop_write(conn, type, ptr, len);
}

CURLcode Curl_read_plain(curl_socket_t sockfd,
                         char *buf,
                         size_t bytesfromsocket,
                         ssize_t *n)
{







|







635
636
637
638
639
640
641
642
643
644
645
646
647
648
649

#ifdef CURL_DO_LINEEND_CONV
    /* convert end-of-line markers */
    len = convert_lineends(data, ptr, len);
#endif /* CURL_DO_LINEEND_CONV */
    }

  return chop_write(data, type, ptr, len);
}

CURLcode Curl_read_plain(curl_socket_t sockfd,
                         char *buf,
                         size_t bytesfromsocket,
                         ssize_t *n)
{
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689

/*
 * 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;
  struct Curl_easy *data = conn->data;

  /* 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 */

  bytesfromsocket = CURLMIN(sizerequested, (size_t)data->set.buffer_size);
  buffertofill = buf;

  nread = conn->recv[num](conn, num, buffertofill, bytesfromsocket, &result);
  if(nread < 0)
    return result;

  *n += nread;

  return CURLE_OK;
}







|









|











|







670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706

/*
 * 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 Curl_easy *data,   /* transfer */
                   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;
  struct connectdata *conn = data->conn;

  /* 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 */

  bytesfromsocket = CURLMIN(sizerequested, (size_t)data->set.buffer_size);
  buffertofill = buf;

  nread = conn->recv[num](data, num, buffertofill, bytesfromsocket, &result);
  if(nread < 0)
    return result;

  *n += nread;

  return CURLE_OK;
}
Changes to jni/curl/lib/sendf.h.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#ifndef HEADER_CURL_SENDF_H
#define HEADER_CURL_SENDF_H
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2020, 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 https://curl.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









|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#ifndef HEADER_CURL_SENDF_H
#define HEADER_CURL_SENDF_H
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2021, 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 https://curl.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
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71

72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89

#define failf Curl_failf

#define CLIENTWRITE_BODY   (1<<0)
#define CLIENTWRITE_HEADER (1<<1)
#define CLIENTWRITE_BOTH   (CLIENTWRITE_BODY|CLIENTWRITE_HEADER)

CURLcode Curl_client_write(struct connectdata *conn, int type, char *ptr,
                           size_t len) WARN_UNUSED_RESULT;

bool Curl_recv_has_postponed_data(struct connectdata *conn, int sockindex);

/* internal read-function, does plain socket only */
CURLcode Curl_read_plain(curl_socket_t sockfd,
                         char *buf,
                         size_t bytesfromsocket,
                         ssize_t *n);

ssize_t Curl_recv_plain(struct connectdata *conn, int num, char *buf,
                        size_t len, CURLcode *code);
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 */
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 */
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 */
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 */
int Curl_debug(struct Curl_easy *data, curl_infotype type,
               char *ptr, size_t size);


#endif /* HEADER_CURL_SENDF_H */







|










|

|



|


>

|





|










45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90

#define failf Curl_failf

#define CLIENTWRITE_BODY   (1<<0)
#define CLIENTWRITE_HEADER (1<<1)
#define CLIENTWRITE_BOTH   (CLIENTWRITE_BODY|CLIENTWRITE_HEADER)

CURLcode Curl_client_write(struct Curl_easy *data, int type, char *ptr,
                           size_t len) WARN_UNUSED_RESULT;

bool Curl_recv_has_postponed_data(struct connectdata *conn, int sockindex);

/* internal read-function, does plain socket only */
CURLcode Curl_read_plain(curl_socket_t sockfd,
                         char *buf,
                         size_t bytesfromsocket,
                         ssize_t *n);

ssize_t Curl_recv_plain(struct Curl_easy *data, int num, char *buf,
                        size_t len, CURLcode *code);
ssize_t Curl_send_plain(struct Curl_easy *data, int num,
                        const void *mem, size_t len, CURLcode *code);

/* internal read-function, does plain socket, SSL and krb4 */
CURLcode Curl_read(struct Curl_easy *data, curl_socket_t sockfd,
                   char *buf, size_t buffersize,
                   ssize_t *n);

/* internal write-function, does plain socket, SSL, SCP, SFTP and krb4 */
CURLcode Curl_write(struct Curl_easy *data,
                    curl_socket_t sockfd,
                    const void *mem, size_t len,
                    ssize_t *written);

/* internal write-function, does plain sockets ONLY */
CURLcode Curl_write_plain(struct Curl_easy *data,
                          curl_socket_t sockfd,
                          const void *mem, size_t len,
                          ssize_t *written);

/* the function used to output verbose information */
int Curl_debug(struct Curl_easy *data, curl_infotype type,
               char *ptr, size_t size);


#endif /* HEADER_CURL_SENDF_H */
Changes to jni/curl/lib/setopt.c.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2020, 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 https://curl.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







|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2021, 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 https://curl.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
270
271
272
273
274
275
276

277
278
279
280
281

282
283
284
285
286
287
288
      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;

    if(data->set.opt_no_body)
      /* in HTTP lingo, no body means using the HEAD request... */
      data->set.method = HTTPREQ_HEAD;
    else if(data->set.method == HTTPREQ_HEAD)
      data->set.method = HTTPREQ_GET;

    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;







>





>







270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
      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;
#ifndef CURL_DISABLE_HTTP
    if(data->set.opt_no_body)
      /* in HTTP lingo, no body means using the HEAD request... */
      data->set.method = HTTPREQ_HEAD;
    else if(data->set.method == HTTPREQ_HEAD)
      data->set.method = HTTPREQ_GET;
#endif
    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;
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
    if(arg < -1)
      return CURLE_BAD_FUNCTION_ARGUMENT;
    data->set.maxredirs = arg;
    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
     */







|







598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
    if(arg < -1)
      return CURLE_BAD_FUNCTION_ARGUMENT;
    data->set.maxredirs = arg;
    break;

  case CURLOPT_POSTREDIR:
    /*
     * Set the behavior 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
     */
632
633
634
635
636
637
638















639
640
641
642
643
644
645
    /*
     * Set to make us do HTTP POST
     */
    data->set.httppost = va_arg(param, struct curl_httppost *);
    data->set.method = HTTPREQ_POST_FORM;
    data->set.opt_no_body = FALSE; /* this is implied */
    break;















#endif   /* CURL_DISABLE_HTTP */

  case CURLOPT_MIMEPOST:
    /*
     * Set to make us do MIME/form POST
     */
    result = Curl_mime_set_subparts(&data->set.mimepost,







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
    /*
     * Set to make us do HTTP POST
     */
    data->set.httppost = va_arg(param, struct curl_httppost *);
    data->set.method = HTTPREQ_POST_FORM;
    data->set.opt_no_body = FALSE; /* this is implied */
    break;

  case CURLOPT_AWS_SIGV4:
    /*
     * String that is merged to some authentication
     * parameters are used by the algorithm.
     */
    result = Curl_setstropt(&data->set.str[STRING_AWS_SIGV4],
                            va_arg(param, char *));
    /*
     * Basic been set by default it need to be unset here
     */
    if(data->set.str[STRING_AWS_SIGV4])
      data->set.httpauth = CURLAUTH_AWS_SIGV4;
    break;

#endif   /* CURL_DISABLE_HTTP */

  case CURLOPT_MIMEPOST:
    /*
     * Set to make us do MIME/form POST
     */
    result = Curl_mime_set_subparts(&data->set.mimepost,
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
    if(arg < CURL_HTTP_VERSION_NONE)
      return CURLE_BAD_FUNCTION_ARGUMENT;
#ifdef ENABLE_QUIC
    if(arg == CURL_HTTP_VERSION_3)
      ;
    else
#endif
#ifndef USE_NGHTTP2
    if(arg >= CURL_HTTP_VERSION_2)
      return CURLE_UNSUPPORTED_PROTOCOL;
#else
    if(arg >= CURL_HTTP_VERSION_LAST)
      return CURLE_UNSUPPORTED_PROTOCOL;
    if(arg == CURL_HTTP_VERSION_NONE)
      arg = CURL_HTTP_VERSION_2TLS;







|







878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
    if(arg < CURL_HTTP_VERSION_NONE)
      return CURLE_BAD_FUNCTION_ARGUMENT;
#ifdef ENABLE_QUIC
    if(arg == CURL_HTTP_VERSION_3)
      ;
    else
#endif
#if !defined(USE_NGHTTP2) && !defined(USE_HYPER)
    if(arg >= CURL_HTTP_VERSION_2)
      return CURLE_UNSUPPORTED_PROTOCOL;
#else
    if(arg >= CURL_HTTP_VERSION_LAST)
      return CURLE_UNSUPPORTED_PROTOCOL;
    if(arg == CURL_HTTP_VERSION_NONE)
      arg = CURL_HTTP_VERSION_2TLS;
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452





1453
1454
1455
1456
1457
1458
1459
1460
    /*
     * 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:
    /*







|
<
<
|


>
>
>
>
>
|







1457
1458
1459
1460
1461
1462
1463
1464


1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
    /*
     * 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 HOST:PORT:[addresses] strings to populate the DNS cache with


     * Entries added this way will remain in the cache until explicitly
     * removed or the handle is cleaned up.
     *
     * Prefix the HOST with plus sign (+) to have the entry expire just like
     * automatically added entries.
     *
     * Prefix the HOST with dash (-) to _remove_ the entry from the cache.
     *
     * This API can remove any entry 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:
    /*
2146
2147
2148
2149
2150
2151
2152

2153
2154
2155
2156
2157
2158
2159
2160
2161

      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->specifier & (1<< CURL_LOCK_DATA_DNS)) {







>
|
|







2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182

      data->share->dirty--;

      Curl_share_unlock(data, CURL_LOCK_DATA_SHARE);
      data->share = NULL;
    }

    if(GOOD_SHARE_HANDLE(set))
      /* 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->specifier & (1<< CURL_LOCK_DATA_DNS)) {
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
                            va_arg(param, char *));
    break;
#endif
  case CURLOPT_IPRESOLVE:
    arg = va_arg(param, long);
    if((arg < CURL_IPRESOLVE_WHATEVER) || (arg > CURL_IPRESOLVE_V6))
      return CURLE_BAD_FUNCTION_ARGUMENT;
    data->set.ipver = arg;
    break;

  case CURLOPT_MAXFILESIZE_LARGE:
    /*
     * Set the maximum size of a file to download.
     */
    bigsize = va_arg(param, curl_off_t);







|







2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
                            va_arg(param, char *));
    break;
#endif
  case CURLOPT_IPRESOLVE:
    arg = va_arg(param, long);
    if((arg < CURL_IPRESOLVE_WHATEVER) || (arg > CURL_IPRESOLVE_V6))
      return CURLE_BAD_FUNCTION_ARGUMENT;
    data->set.ipver = (unsigned char) arg;
    break;

  case CURLOPT_MAXFILESIZE_LARGE:
    /*
     * Set the maximum size of a file to download.
     */
    bigsize = va_arg(param, curl_off_t);
Changes to jni/curl/lib/sha256.c.
23
24
25
26
27
28
29

30
31
32
33
34
35
36

#include "curl_setup.h"

#ifndef CURL_DISABLE_CRYPTO_AUTH

#include "warnless.h"
#include "curl_sha256.h"


#if defined(USE_OPENSSL)

#include <openssl/opensslv.h>

#if (OPENSSL_VERSION_NUMBER >= 0x0090800fL)
#define USE_OPENSSL_SHA256







>







23
24
25
26
27
28
29
30
31
32
33
34
35
36
37

#include "curl_setup.h"

#ifndef CURL_DISABLE_CRYPTO_AUTH

#include "warnless.h"
#include "curl_sha256.h"
#include "curl_hmac.h"

#if defined(USE_OPENSSL)

#include <openssl/opensslv.h>

#if (OPENSSL_VERSION_NUMBER >= 0x0090800fL)
#define USE_OPENSSL_SHA256
339
340
341
342
343
344
345
346

347
348
349
350


351
352
353
354
355
356
357
  /* fill W[16..63] */
  for(i = 16; i < 64; i++) {
    W[i] = Gamma1(W[i - 2]) + W[i - 7] + Gamma0(W[i - 15]) +
      W[i - 16];
  }

  /* Compress */
#define RND(a,b,c,d,e,f,g,h,i)                                  \

  unsigned long t0 = h + Sigma1(e) + Ch(e, f, g) + K[i] + W[i]; \
  unsigned long t1 = Sigma0(a) + Maj(a, b, c);                  \
  d += t0;                                                      \
  h = t0 + t1;


  for(i = 0; i < 64; ++i) {
    unsigned long t;
    RND(S[0], S[1], S[2], S[3], S[4], S[5], S[6], S[7], i);
    t = S[7]; S[7] = S[6]; S[6] = S[5]; S[5] = S[4];
    S[4] = S[3]; S[3] = S[2]; S[2] = S[1]; S[1] = S[0]; S[0] = t;
  }








|
>
|
|
|
|
>
>







340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
  /* fill W[16..63] */
  for(i = 16; i < 64; i++) {
    W[i] = Gamma1(W[i - 2]) + W[i - 7] + Gamma0(W[i - 15]) +
      W[i - 16];
  }

  /* Compress */
#define RND(a,b,c,d,e,f,g,h,i)                                          \
  do {                                                                  \
    unsigned long t0 = h + Sigma1(e) + Ch(e, f, g) + K[i] + W[i];       \
    unsigned long t1 = Sigma0(a) + Maj(a, b, c);                        \
    d += t0;                                                            \
    h = t0 + t1;                                                        \
  } while(0)

  for(i = 0; i < 64; ++i) {
    unsigned long t;
    RND(S[0], S[1], S[2], S[3], S[4], S[5], S[6], S[7], i);
    t = S[7]; S[7] = S[6]; S[6] = S[5]; S[5] = S[4];
    S[4] = S[3]; S[3] = S[2]; S[2] = S[1]; S[1] = S[0]; S[0] = t;
  }

486
487
488
489
490
491
492
493



















494
{
  SHA256_CTX ctx;

  SHA256_Init(&ctx);
  SHA256_Update(&ctx, input, curlx_uztoui(length));
  SHA256_Final(output, &ctx);
}




















#endif /* CURL_DISABLE_CRYPTO_AUTH */








>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
{
  SHA256_CTX ctx;

  SHA256_Init(&ctx);
  SHA256_Update(&ctx, input, curlx_uztoui(length));
  SHA256_Final(output, &ctx);
}


const struct HMAC_params Curl_HMAC_SHA256[] = {
  {
    /* Hash initialization function. */
    CURLX_FUNCTION_CAST(HMAC_hinit_func, SHA256_Init),
    /* Hash update function. */
    CURLX_FUNCTION_CAST(HMAC_hupdate_func, SHA256_Update),
    /* Hash computation end function. */
    CURLX_FUNCTION_CAST(HMAC_hfinal_func, SHA256_Final),
    /* Size of hash context structure. */
    sizeof(SHA256_CTX),
    /* Maximum key length. */
    64,
    /* Result size. */
    32
  }
};


#endif /* CURL_DISABLE_CRYPTO_AUTH */
Changes to jni/curl/lib/share.c.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2020, 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 https://curl.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







|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2021, 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 https://curl.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
33
34
35
36
37
38
39

40
41
42
43
44
45
46
#include "memdebug.h"

struct Curl_share *
curl_share_init(void)
{
  struct Curl_share *share = calloc(1, sizeof(struct Curl_share));
  if(share) {

    share->specifier |= (1<<CURL_LOCK_DATA_SHARE);

    if(Curl_mk_dnscache(&share->hostcache)) {
      free(share);
      return NULL;
    }
  }







>







33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
#include "memdebug.h"

struct Curl_share *
curl_share_init(void)
{
  struct Curl_share *share = calloc(1, sizeof(struct Curl_share));
  if(share) {
    share->magic = CURL_GOOD_SHARE;
    share->specifier |= (1<<CURL_LOCK_DATA_SHARE);

    if(Curl_mk_dnscache(&share->hostcache)) {
      free(share);
      return NULL;
    }
  }
54
55
56
57
58
59
60



61
62
63
64
65
66
67
{
  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);







>
>
>







55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
{
  va_list param;
  int type;
  curl_lock_function lockfunc;
  curl_unlock_function unlockfunc;
  void *ptr;
  CURLSHcode res = CURLSHE_OK;

  if(!GOOD_SHARE_HANDLE(share))
    return CURLSHE_INVALID;

  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);
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194

  return res;
}

CURLSHcode
curl_share_cleanup(struct Curl_share *share)
{
  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) {







|







184
185
186
187
188
189
190
191
192
193
194
195
196
197
198

  return res;
}

CURLSHcode
curl_share_cleanup(struct Curl_share *share)
{
  if(!GOOD_SHARE_HANDLE(share))
    return CURLSHE_INVALID;

  if(share->lockfunc)
    share->lockfunc(NULL, CURL_LOCK_DATA_SHARE, CURL_LOCK_ACCESS_SINGLE,
                    share->clientdata);

  if(share->dirty) {
214
215
216
217
218
219
220

221
222
223
224
225
226
227
  }
#endif

  Curl_psl_destroy(&share->psl);

  if(share->unlockfunc)
    share->unlockfunc(NULL, CURL_LOCK_DATA_SHARE, share->clientdata);

  free(share);

  return CURLSHE_OK;
}


CURLSHcode







>







218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
  }
#endif

  Curl_psl_destroy(&share->psl);

  if(share->unlockfunc)
    share->unlockfunc(NULL, CURL_LOCK_DATA_SHARE, share->clientdata);
  share->magic = 0;
  free(share);

  return CURLSHE_OK;
}


CURLSHcode
Changes to jni/curl/lib/share.h.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#ifndef HEADER_CURL_SHARE_H
#define HEADER_CURL_SHARE_H
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2020, 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 https://curl.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









|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#ifndef HEADER_CURL_SHARE_H
#define HEADER_CURL_SHARE_H
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2021, 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 https://curl.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
33
34
35
36
37
38
39



40
41

42
43
44
45
46
47
48
 */
#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 conncache conn_cache;







>
>
>


>







33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
 */
#ifdef __SALFORDC__
#define CURL_VOLATILE
#else
#define CURL_VOLATILE volatile
#endif

#define CURL_GOOD_SHARE 0x7e117a1e
#define GOOD_SHARE_HANDLE(x) ((x) && (x)->magic == CURL_GOOD_SHARE)

/* this struct is libcurl-private, don't export details */
struct Curl_share {
  unsigned int magic; /* CURL_GOOD_SHARE */
  unsigned int specifier;
  CURL_VOLATILE unsigned int dirty;

  curl_lock_function lockfunc;
  curl_unlock_function unlockfunc;
  void *clientdata;
  struct conncache conn_cache;
Changes to jni/curl/lib/smb.c.
1
2
3
4
5
6
7

8
9
10
11
12
13
14
15
16
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *

 * Copyright (C) 2014, Bill Nagel <wnagel@tycoint.com>, Exacq Technologies
 * Copyright (C) 2016-2020, 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 https://curl.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







>

<







1
2
3
4
5
6
7
8
9

10
11
12
13
14
15
16
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 2016 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
 * 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 https://curl.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
50
51
52
53
54
55
56
57

58
59
60
61
62
63
64
65


66

67
68
69
70
71
72
73
#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_do(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);


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 */







|
>
|
|
|
|
|

|
|
>
>
|
>







50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
#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 Curl_easy *data,
                                     struct connectdata *conn);
static CURLcode smb_connect(struct Curl_easy *data, bool *done);
static CURLcode smb_connection_state(struct Curl_easy *data, bool *done);
static CURLcode smb_do(struct Curl_easy *data, bool *done);
static CURLcode smb_request_state(struct Curl_easy *data, bool *done);
static CURLcode smb_done(struct Curl_easy *data, CURLcode status,
                         bool premature);
static CURLcode smb_disconnect(struct Curl_easy *data,
                               struct connectdata *conn, bool dead);
static int smb_getsock(struct Curl_easy *data, struct connectdata *conn,
                       curl_socket_t *socks);
static CURLcode smb_parse_url_path(struct Curl_easy *data,
                                   struct connectdata *conn);

/*
 * SMB handler interface
 */
const struct Curl_handler Curl_handler_smb = {
  "SMB",                                /* scheme */
  smb_setup_connection,                 /* setup_connection */
120
121
122
123
124
125
126

127
128

129
130
131

132
133

134
135
136
137
138
139
140
#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 (unsigned short) ((x << 8) | ((x >> 8) & 0xff));







>
|
|
>



>
|
|
>







124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
#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)                             \
  do {                                          \
    strcpy(p, (str));                           \
    p += strlen(str);                           \
  } while(0)

/* Append a null-terminated string to an SMB message */
#define MSGCATNULL(str)                         \
  do {                                          \
    strcpy(p, (str));                           \
    p += strlen(str) + 1;                       \
  } while(0)

/* 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 (unsigned short) ((x << 8) | ((x >> 8) & 0xff));
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232

233
234
235
236
237
238
239
240
241
242
243
244
245
246

247
248
249
250
251
252
253
  enum smb_req_state state;
  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 *smbc = &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(smbc->state != newstate)
    infof(conn->data, "SMB conn %p state change from %s to %s\n",
          (void *)smbc, names[smbc->state], names[newstate]);
#endif

  smbc->state = newstate;
}

static void request_state(struct connectdata *conn,
                          enum smb_req_state newstate)
{
  struct smb_request *req = conn->data->req.p.smb;
#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;
}

/* this should setup things in the connection, not in the easy
   handle */
static CURLcode smb_setup_connection(struct connectdata *conn)

{
  struct smb_request *req;

  /* Initialize the request state */
  conn->data->req.p.smb = 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)







|

|












|






|


|















|








|
>




|




|


|

>







183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
  enum smb_req_state state;
  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 Curl_easy *data, enum smb_conn_state newstate)
{
  struct smb_conn *smbc = &data->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(smbc->state != newstate)
    infof(data, "SMB conn %p state change from %s to %s\n",
          (void *)smbc, names[smbc->state], names[newstate]);
#endif

  smbc->state = newstate;
}

static void request_state(struct Curl_easy *data,
                          enum smb_req_state newstate)
{
  struct smb_request *req = data->req.p.smb;
#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(data, "SMB request %p state change from %s to %s\n",
          (void *)req, names[req->state], names[newstate]);
#endif

  req->state = newstate;
}

/* this should setup things in the connection, not in the easy
   handle */
static CURLcode smb_setup_connection(struct Curl_easy *data,
                                     struct connectdata *conn)
{
  struct smb_request *req;

  /* Initialize the request state */
  data->req.p.smb = req = calloc(1, sizeof(struct smb_request));
  if(!req)
    return CURLE_OUT_OF_MEMORY;

  /* Parse the URL path */
  return smb_parse_url_path(data, conn);
}

static CURLcode smb_connect(struct Curl_easy *data, bool *done)
{
  struct connectdata *conn = data->conn;
  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)
280
281
282
283
284
285
286
287
288

289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
    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;







|

>








|







290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
    if(!smbc->domain)
      return CURLE_OUT_OF_MEMORY;
  }

  return CURLE_OK;
}

static CURLcode smb_recv_message(struct Curl_easy *data, void **msg)
{
  struct connectdata *conn = data->conn;
  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(data, FIRSTSOCKET, buf + smbc->got, len, &bytes_read);
  if(result)
    return result;

  if(!bytes_read)
    return CURLE_OK;

  smbc->got += bytes_read;
334
335
336
337
338
339
340
341
342
343

344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364

365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385

386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430

431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
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.p.smb;
  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.ulbuf,
                      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.ulbuf + 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)
{
  CURLcode result = Curl_get_upload_buffer(conn->data);
  if(result)
    return result;
  smb_format_message(conn, (struct smb_header *)conn->data->state.ulbuf,
                     cmd, msg_len);
  memcpy(conn->data->state.ulbuf + 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);
#ifdef 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;







|


>

|
















|


>




|














|

>








|
|












|


|


|

|


|


|



|


|

>














|


|







345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
static void smb_pop_message(struct connectdata *conn)
{
  struct smb_conn *smbc = &conn->proto.smbc;

  smbc->got = 0;
}

static void smb_format_message(struct Curl_easy *data, struct smb_header *h,
                               unsigned char cmd, size_t len)
{
  struct connectdata *conn = data->conn;
  struct smb_conn *smbc = &conn->proto.smbc;
  struct smb_request *req = data->req.p.smb;
  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 Curl_easy *data, ssize_t len,
                         size_t upload_size)
{
  struct connectdata *conn = data->conn;
  struct smb_conn *smbc = &conn->proto.smbc;
  ssize_t bytes_written;
  CURLcode result;

  result = Curl_write(data, FIRSTSOCKET, data->state.ulbuf,
                      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 Curl_easy *data)
{
  struct connectdata *conn = data->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(data, FIRSTSOCKET,
                      data->state.ulbuf + 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 Curl_easy *data, unsigned char cmd,
                                 const void *msg, size_t msg_len)
{
  CURLcode result = Curl_get_upload_buffer(data);
  if(result)
    return result;
  smb_format_message(data, (struct smb_header *)data->state.ulbuf,
                     cmd, msg_len);
  memcpy(data->state.ulbuf + sizeof(struct smb_header),
         msg, msg_len);

  return smb_send(data, sizeof(struct smb_header) + msg_len, 0);
}

static CURLcode smb_send_negotiate(struct Curl_easy *data)
{
  const char *msg = "\x00\x0c\x00\x02NT LM 0.12";

  return smb_send_message(data, SMB_COM_NEGOTIATE, msg, 15);
}

static CURLcode smb_send_setup(struct Curl_easy *data)
{
  struct connectdata *conn = data->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(data, conn->passwd, lm_hash);
  Curl_ntlm_core_lm_resp(lm_hash, smbc->challenge, lm);
#ifdef USE_NTRESPONSES
  Curl_ntlm_core_mk_nt_hash(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;
468
469
470
471
472
473
474
475
476
477
478
479
480
481

482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606

607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643

644
645
646
647
648
649
650
651
652
653
654

655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
  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_tree_connect msg;

  struct smb_conn *smbc = &conn->proto.smbc;
  char *p = msg.bytes;

  size_t byte_count = strlen(conn->host.name) + strlen(smbc->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(smbc->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.p.smb;
  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.p.smb;
  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.p.smb;
  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_request *req = conn->data->req.p.smb;
  curl_off_t offset = conn->data->req.offset;
  curl_off_t upload_size = conn->data->req.size - conn->data->req.bytecount;
  CURLcode result = Curl_get_upload_buffer(conn->data);
  if(result)
    return result;
  msg = (struct smb_write *)conn->data->state.ulbuf;

  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;
  *msg = NULL; /* if it returns early */

  /* Check if there is data in the transfer buffer */
  if(!smbc->send_size && smbc->upload_size) {
    size_t nread = smbc->upload_size > conn->data->set.upload_buffer_size ?
      conn->data->set.upload_buffer_size :
      smbc->upload_size;
    conn->data->req.upload_fromhere = conn->data->state.ulbuf;
    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 = FALSE;
      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((smbc->got < sizeof(*nrsp) + sizeof(smbc->challenge) - 1) ||
       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 */
  }







|



|


>




















|



|

|












|










|



|

|






|


|





|


|

|
|











|


|


|
|
|
|


|














|


|


|

>






|
|

|
|












|








|


|

>










|
>







|





|



|




















|




|








|







483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
  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(data, SMB_COM_SETUP_ANDX, &msg,
                          sizeof(msg) - sizeof(msg.bytes) + byte_count);
}

static CURLcode smb_send_tree_connect(struct Curl_easy *data)
{
  struct smb_tree_connect msg;
  struct connectdata *conn = data->conn;
  struct smb_conn *smbc = &conn->proto.smbc;
  char *p = msg.bytes;

  size_t byte_count = strlen(conn->host.name) + strlen(smbc->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(smbc->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(data, SMB_COM_TREE_CONNECT_ANDX, &msg,
                          sizeof(msg) - sizeof(msg.bytes) + byte_count);
}

static CURLcode smb_send_open(struct Curl_easy *data)
{
  struct smb_request *req = data->req.p.smb;
  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(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(data, SMB_COM_NT_CREATE_ANDX, &msg,
                          sizeof(msg) - sizeof(msg.bytes) + byte_count);
}

static CURLcode smb_send_close(struct Curl_easy *data)
{
  struct smb_request *req = data->req.p.smb;
  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(data, SMB_COM_CLOSE, &msg, sizeof(msg));
}

static CURLcode smb_send_tree_disconnect(struct Curl_easy *data)
{
  struct smb_tree_disconnect msg;

  memset(&msg, 0, sizeof(msg));

  return smb_send_message(data, SMB_COM_TREE_DISCONNECT, &msg, sizeof(msg));
}

static CURLcode smb_send_read(struct Curl_easy *data)
{
  struct smb_request *req = data->req.p.smb;
  curl_off_t offset = 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(data, SMB_COM_READ_ANDX, &msg, sizeof(msg));
}

static CURLcode smb_send_write(struct Curl_easy *data)
{
  struct smb_write *msg;
  struct smb_request *req = data->req.p.smb;
  curl_off_t offset = data->req.offset;
  curl_off_t upload_size = data->req.size - data->req.bytecount;
  CURLcode result = Curl_get_upload_buffer(data);
  if(result)
    return result;
  msg = (struct smb_write *)data->state.ulbuf;

  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(data, &msg->h, SMB_COM_WRITE_ANDX,
                     sizeof(*msg) - sizeof(msg->h) + (size_t) upload_size);

  return smb_send(data, sizeof(*msg), (size_t) upload_size);
}

static CURLcode smb_send_and_recv(struct Curl_easy *data, void **msg)
{
  struct connectdata *conn = data->conn;
  struct smb_conn *smbc = &conn->proto.smbc;
  CURLcode result;
  *msg = NULL; /* if it returns early */

  /* Check if there is data in the transfer buffer */
  if(!smbc->send_size && smbc->upload_size) {
    size_t nread = smbc->upload_size > data->set.upload_buffer_size ?
      data->set.upload_buffer_size :
      smbc->upload_size;
    data->req.upload_fromhere = data->state.ulbuf;
    result = Curl_fillreadbuffer(data, 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(data);
    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(data, msg);
}

static CURLcode smb_connection_state(struct Curl_easy *data, bool *done)
{
  struct connectdata *conn = data->conn;
  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 = FALSE;
      result = Curl_ssl_connect_nonblocking(data, conn,
                                            FIRSTSOCKET, &ssl_done);
      if(result && result != CURLE_AGAIN)
        return result;
      if(!ssl_done)
        return CURLE_OK;
    }
#endif

    result = smb_send_negotiate(data);
    if(result) {
      connclose(conn, "SMB: failed to send negotiate message");
      return result;
    }

    conn_state(data, SMB_NEGOTIATE);
  }

  /* Send the previous message and check for a response */
  result = smb_send_and_recv(data, &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((smbc->got < sizeof(*nrsp) + sizeof(smbc->challenge) - 1) ||
       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(data);
    if(result) {
      connclose(conn, "SMB: failed to send setup message");
      return result;
    }
    conn_state(data, 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(data, SMB_CONNECTED);
    *done = true;
    break;

  default:
    smb_pop_message(conn);
    return CURLE_OK; /* ignore */
  }
732
733
734
735
736
737
738
739
740

741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
  else if(timestamp < TIME_T_MIN)
    *out = TIME_T_MIN;
  else
#endif
    *out = (time_t) timestamp;
}

static CURLcode smb_request_state(struct connectdata *conn, bool *done)
{

  struct smb_request *req = conn->data->req.p.smb;
  struct smb_header *h;
  struct smb_conn *smbc = &conn->proto.smbc;
  enum smb_req_state next_state = SMB_DONE;
  unsigned short len;
  unsigned short off;
  CURLcode result;
  void *msg = NULL;
  const struct smb_nt_create_response *smb_m;

  /* 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;







|

>
|











|





|



|







751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
  else if(timestamp < TIME_T_MIN)
    *out = TIME_T_MIN;
  else
#endif
    *out = (time_t) timestamp;
}

static CURLcode smb_request_state(struct Curl_easy *data, bool *done)
{
  struct connectdata *conn = data->conn;
  struct smb_request *req = data->req.p.smb;
  struct smb_header *h;
  struct smb_conn *smbc = &conn->proto.smbc;
  enum smb_req_state next_state = SMB_DONE;
  unsigned short len;
  unsigned short off;
  CURLcode result;
  void *msg = NULL;
  const struct smb_nt_create_response *smb_m;

  /* Start the request */
  if(req->state == SMB_REQUESTING) {
    result = smb_send_tree_connect(data);
    if(result) {
      connclose(conn, "SMB: failed to send tree connect message");
      return result;
    }

    request_state(data, SMB_TREE_CONNECT);
  }

  /* Send the previous message and check for a response */
  result = smb_send_and_recv(data, &msg);
  if(result && result != CURLE_AGAIN) {
    connclose(conn, "SMB: failed to communicate");
    return result;
  }

  if(!msg)
    return CURLE_OK;
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
      if(h->status == smb_swap32(SMB_ERR_NOACCESS))
        req->result = CURLE_REMOTE_ACCESS_DENIED;
      next_state = SMB_TREE_DISCONNECT;
      break;
    }
    smb_m = (const struct smb_nt_create_response*) msg;
    req->fid = smb_swap16(smb_m->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 {
      smb_m = (const struct smb_nt_create_response*) msg;
      conn->data->req.size = smb_swap64(smb_m->end_of_file);
      if(conn->data->req.size < 0) {
        req->result = CURLE_WEIRD_SERVER_REPLY;
        next_state = SMB_CLOSE;
      }
      else {
        Curl_pgrsSetDownloadSize(conn->data, conn->data->req.size);
        if(conn->data->set.get_filetime)
          get_posix_time(&conn->data->info.filetime, smb_m->last_change_time);
        next_state = SMB_DOWNLOAD;
      }
    }
    break;

  case SMB_DOWNLOAD:
    if(h->status || smbc->got < sizeof(struct smb_header) + 14) {
      req->result = CURLE_RECV_ERROR;
      next_state = SMB_CLOSE;
      break;
    }
    len = Curl_read16_le(((const unsigned char *) msg) +
                         sizeof(struct smb_header) + 11);
    off = Curl_read16_le(((const unsigned char *) msg) +
                         sizeof(struct smb_header) + 13);
    if(len > 0) {
      if(off + sizeof(unsigned int) + len > smbc->got) {
        failf(conn->data, "Invalid input packet");
        result = CURLE_RECV_ERROR;
      }
      else
        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 || smbc->got < sizeof(struct smb_header) + 6) {
      req->result = CURLE_UPLOAD_FAILED;
      next_state = SMB_CLOSE;
      break;
    }
    len = Curl_read16_le(((const 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 */







|
|
|
|




|
|




|
|
|

















|



|








|
|
|











|
|
|
|







809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
      if(h->status == smb_swap32(SMB_ERR_NOACCESS))
        req->result = CURLE_REMOTE_ACCESS_DENIED;
      next_state = SMB_TREE_DISCONNECT;
      break;
    }
    smb_m = (const struct smb_nt_create_response*) msg;
    req->fid = smb_swap16(smb_m->fid);
    data->req.offset = 0;
    if(data->set.upload) {
      data->req.size = data->state.infilesize;
      Curl_pgrsSetUploadSize(data, data->req.size);
      next_state = SMB_UPLOAD;
    }
    else {
      smb_m = (const struct smb_nt_create_response*) msg;
      data->req.size = smb_swap64(smb_m->end_of_file);
      if(data->req.size < 0) {
        req->result = CURLE_WEIRD_SERVER_REPLY;
        next_state = SMB_CLOSE;
      }
      else {
        Curl_pgrsSetDownloadSize(data, data->req.size);
        if(data->set.get_filetime)
          get_posix_time(&data->info.filetime, smb_m->last_change_time);
        next_state = SMB_DOWNLOAD;
      }
    }
    break;

  case SMB_DOWNLOAD:
    if(h->status || smbc->got < sizeof(struct smb_header) + 14) {
      req->result = CURLE_RECV_ERROR;
      next_state = SMB_CLOSE;
      break;
    }
    len = Curl_read16_le(((const unsigned char *) msg) +
                         sizeof(struct smb_header) + 11);
    off = Curl_read16_le(((const unsigned char *) msg) +
                         sizeof(struct smb_header) + 13);
    if(len > 0) {
      if(off + sizeof(unsigned int) + len > smbc->got) {
        failf(data, "Invalid input packet");
        result = CURLE_RECV_ERROR;
      }
      else
        result = Curl_client_write(data, CLIENTWRITE_BODY,
                                   (char *)msg + off + sizeof(unsigned int),
                                   len);
      if(result) {
        req->result = result;
        next_state = SMB_CLOSE;
        break;
      }
    }
    data->req.bytecount += len;
    data->req.offset += len;
    Curl_pgrsSetDownloadCounter(data, data->req.bytecount);
    next_state = (len < MAX_PAYLOAD_SIZE) ? SMB_CLOSE : SMB_DOWNLOAD;
    break;

  case SMB_UPLOAD:
    if(h->status || smbc->got < sizeof(struct smb_header) + 6) {
      req->result = CURLE_UPLOAD_FAILED;
      next_state = SMB_CLOSE;
      break;
    }
    len = Curl_read16_le(((const unsigned char *) msg) +
                         sizeof(struct smb_header) + 5);
    data->req.bytecount += len;
    data->req.offset += len;
    Curl_pgrsSetUploadCounter(data, data->req.bytecount);
    if(data->req.bytecount >= 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 */
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930

931
932
933

934
935
936
937
938
939

940
941

942
943
944
945
946
947

948
949
950
951
952
953
954
955
956
957

958
959
960
961
962
963
964
965
966
    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)
{
  (void) premature;
  Curl_safefree(conn->data->req.p.smb);
  return status;
}

static CURLcode smb_disconnect(struct connectdata *conn, bool dead)

{
  struct smb_conn *smbc = &conn->proto.smbc;
  (void) dead;

  Curl_safefree(smbc->share);
  Curl_safefree(smbc->domain);
  Curl_safefree(smbc->recv_buf);
  return CURLE_OK;
}


static int smb_getsock(struct connectdata *conn, curl_socket_t *socks)
{

  socks[0] = conn->sock[FIRSTSOCKET];
  return GETSOCK_READSOCK(0) | GETSOCK_WRITESOCK(0);
}

static CURLcode smb_do(struct connectdata *conn, bool *done)
{

  struct smb_conn *smbc = &conn->proto.smbc;

  *done = FALSE;
  if(smbc->share) {
    return CURLE_OK;
  }
  return CURLE_URL_MALFORMAT;
}

static CURLcode smb_parse_url_path(struct connectdata *conn)

{
  struct Curl_easy *data = conn->data;
  struct smb_request *req = data->req.p.smb;
  struct smb_conn *smbc = &conn->proto.smbc;
  char *path;
  char *slash;

  /* URL decode the path */
  CURLcode result = Curl_urldecode(data, data->state.up.path, 0, &path, NULL,







|



|



|



|



|
















|




|



|



|
>



>






>
|

>




|

>









|
>

<







897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984

985
986
987
988
989
990
991
    return CURLE_OK; /* ignore */
  }

  smb_pop_message(conn);

  switch(next_state) {
  case SMB_OPEN:
    result = smb_send_open(data);
    break;

  case SMB_DOWNLOAD:
    result = smb_send_read(data);
    break;

  case SMB_UPLOAD:
    result = smb_send_write(data);
    break;

  case SMB_CLOSE:
    result = smb_send_close(data);
    break;

  case SMB_TREE_DISCONNECT:
    result = smb_send_tree_disconnect(data);
    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(data, next_state);

  return CURLE_OK;
}

static CURLcode smb_done(struct Curl_easy *data, CURLcode status,
                         bool premature)
{
  (void) premature;
  Curl_safefree(data->req.p.smb);
  return status;
}

static CURLcode smb_disconnect(struct Curl_easy *data,
                               struct connectdata *conn, bool dead)
{
  struct smb_conn *smbc = &conn->proto.smbc;
  (void) dead;
  (void) data;
  Curl_safefree(smbc->share);
  Curl_safefree(smbc->domain);
  Curl_safefree(smbc->recv_buf);
  return CURLE_OK;
}

static int smb_getsock(struct Curl_easy *data,
                       struct connectdata *conn, curl_socket_t *socks)
{
  (void)data;
  socks[0] = conn->sock[FIRSTSOCKET];
  return GETSOCK_READSOCK(0) | GETSOCK_WRITESOCK(0);
}

static CURLcode smb_do(struct Curl_easy *data, bool *done)
{
  struct connectdata *conn = data->conn;
  struct smb_conn *smbc = &conn->proto.smbc;

  *done = FALSE;
  if(smbc->share) {
    return CURLE_OK;
  }
  return CURLE_URL_MALFORMAT;
}

static CURLcode smb_parse_url_path(struct Curl_easy *data,
                                   struct connectdata *conn)
{

  struct smb_request *req = data->req.p.smb;
  struct smb_conn *smbc = &conn->proto.smbc;
  char *path;
  char *slash;

  /* URL decode the path */
  CURLcode result = Curl_urldecode(data, data->state.up.path, 0, &path, NULL,
Changes to jni/curl/lib/smtp.c.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2020, 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 https://curl.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







|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2021, 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 https://curl.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
87
88
89
90
91
92
93
94
95
96
97
98
99

100

101
102
103

104
105
106
107
108
109

110
111

112
113
114
115
116
117
118
#include "warnless.h"
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
#include "curl_memory.h"
#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);
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_parse_address(struct connectdata *conn, const char *fqma,
                                   char **address, struct hostname *host);
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 = {







|
|
|

|
|
>
|
>
|
|
|
>

|
|
|

|
>

|
>







87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
#include "warnless.h"
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
#include "curl_memory.h"
#include "memdebug.h"

/* Local API functions */
static CURLcode smtp_regular_transfer(struct Curl_easy *data, bool *done);
static CURLcode smtp_do(struct Curl_easy *data, bool *done);
static CURLcode smtp_done(struct Curl_easy *data, CURLcode status,
                          bool premature);
static CURLcode smtp_connect(struct Curl_easy *data, bool *done);
static CURLcode smtp_disconnect(struct Curl_easy *data,
                                struct connectdata *conn, bool dead);
static CURLcode smtp_multi_statemach(struct Curl_easy *data, bool *done);
static int smtp_getsock(struct Curl_easy *data,
                        struct connectdata *conn, curl_socket_t *socks);
static CURLcode smtp_doing(struct Curl_easy *data, bool *dophase_done);
static CURLcode smtp_setup_connection(struct Curl_easy *data,
                                      struct connectdata *conn);
static CURLcode smtp_parse_url_options(struct connectdata *conn);
static CURLcode smtp_parse_url_path(struct Curl_easy *data);
static CURLcode smtp_parse_custom_request(struct Curl_easy *data);
static CURLcode smtp_parse_address(struct Curl_easy *data, const char *fqma,
                                   char **address, struct hostname *host);
static CURLcode smtp_perform_auth(struct Curl_easy *data,
                                  struct connectdata *conn, const char *mech,
                                  const char *initresp);
static CURLcode smtp_continue_auth(struct Curl_easy *data,
                                   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 = {
195
196
197
198
199
200
201
202
203
204
205
206

207
208
209
210
211
212
213
 *
 * 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







|
|



>







200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
 *
 * 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 Curl_easy *data, struct connectdata *conn,
                           char *line, size_t len, int *resp)
{
  struct smtp_conn *smtpc = &conn->proto.smtpc;
  bool result = FALSE;
  (void)data;

  /* 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
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319

320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343

344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366

367
368
369

370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385

386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410

411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435

436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451

452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532

533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584

/***********************************************************************
 *
 * 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)

{
  /* Send the STARTTLS command */
  CURLcode 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)
{
  /* Start the SSL connection */

  struct smtp_conn *smtpc = &conn->proto.smtpc;
  CURLcode 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 Curl_easy *data = conn->data;
  struct SMTP *smtp = data->req.p.smtp;

  if(smtp->rcpt) {
    /* We notify the server we are sending UTF-8 data if a) it supports the
       SMTPUTF8 extension and b) The mailbox contains UTF-8 charaacters, in
       either the local address or host name parts. This is regardless of
       whether the host name is encoded using IDN ACE */
    bool utf8 = FALSE;

    if((!smtp->custom) || (!smtp->custom[0])) {
      char *address = NULL;
      struct hostname host = { NULL, NULL, NULL, NULL };

      /* Parse the mailbox to verify into the local address and host name
         parts, converting the host name to an IDN A-label if necessary */
      result = smtp_parse_address(conn, smtp->rcpt->data,
                                  &address, &host);
      if(result)
        return result;

      /* Establish whether we should report SMTPUTF8 to the server for this
         mailbox as per RFC-6531 sect. 3.1 point 6 */
      utf8 = (conn->proto.smtpc.utf8_supported) &&
             ((host.encalloc) || (!Curl_is_ASCII_name(address)) ||
              (!Curl_is_ASCII_name(host.name)));

      /* Send the VRFY command (Note: The host name part may be absent when the
         host is a local system) */
      result = Curl_pp_sendf(&conn->proto.smtpc.pp, "VRFY %s%s%s%s",
                             address,
                             host.name ? "@" : "",
                             host.name ? host.name : "",
                             utf8 ? " SMTPUTF8" : "");

      Curl_free_idnconverted_hostname(&host);
      free(address);
    }
    else {
      /* Establish whether we should report that we support SMTPUTF8 for EXPN
         commands to the server as per RFC-6531 sect. 3.1 point 6 */
      utf8 = (conn->proto.smtpc.utf8_supported) &&
             (!strcmp(smtp->custom, "EXPN"));

      /* Send the custom recipient based command such as the EXPN command */

      result = Curl_pp_sendf(&conn->proto.smtpc.pp, "%s %s%s", smtp->custom,
                             smtp->rcpt->data,
                             utf8 ? " SMTPUTF8" : "");
    }
  }
  else
    /* Send the non-recipient based command such as HELP */
    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 Curl_easy *data = conn->data;

  /* We notify the server we are sending UTF-8 data if a) it supports the
     SMTPUTF8 extension and b) The mailbox contains UTF-8 charaacters, in
     either the local address or host name parts. This is regardless of
     whether the host name is encoded using IDN ACE */
  bool utf8 = FALSE;

  /* Calculate the FROM parameter */
  if(data->set.str[STRING_MAIL_FROM]) {
    char *address = NULL;
    struct hostname host = { NULL, NULL, NULL, NULL };

    /* Parse the FROM mailbox into the local address and host name parts,
       converting the host name to an IDN A-label if necessary */
    result = smtp_parse_address(conn, data->set.str[STRING_MAIL_FROM],
                                &address, &host);
    if(result)
      return result;

    /* Establish whether we should report SMTPUTF8 to the server for this
       mailbox as per RFC-6531 sect. 3.1 point 4 and sect. 3.4 */
    utf8 = (conn->proto.smtpc.utf8_supported) &&







|

|




















|













|


>









|


|










|
>








|


|










|
>


|
>


|










|


>

|




|



|













|
>








|



|











|
>



|









|


>







|




|



|


|













|


|















|












|















>
|






|




|










|





|














|







279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599

/***********************************************************************
 *
 * state()
 *
 * This is the ONLY way to change SMTP state!
 */
static void state(struct Curl_easy *data, smtpstate newstate)
{
  struct smtp_conn *smtpc = &data->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(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 Curl_easy *data)
{
  CURLcode result = CURLE_OK;
  struct connectdata *conn = data->conn;
  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(data, &smtpc->pp, "EHLO %s", smtpc->domain);

  if(!result)
    state(data, SMTP_EHLO);

  return result;
}

/***********************************************************************
 *
 * smtp_perform_helo()
 *
 * Sends the HELO command to initialise communication with the SMTP server.
 */
static CURLcode smtp_perform_helo(struct Curl_easy *data,
                                  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(data, &smtpc->pp, "HELO %s", smtpc->domain);

  if(!result)
    state(data, SMTP_HELO);

  return result;
}

/***********************************************************************
 *
 * smtp_perform_starttls()
 *
 * Sends the STLS command to start the upgrade to TLS.
 */
static CURLcode smtp_perform_starttls(struct Curl_easy *data,
                                      struct connectdata *conn)
{
  /* Send the STARTTLS command */
  CURLcode result = Curl_pp_sendf(data, &conn->proto.smtpc.pp,
                                  "%s", "STARTTLS");

  if(!result)
    state(data, SMTP_STARTTLS);

  return result;
}

/***********************************************************************
 *
 * smtp_perform_upgrade_tls()
 *
 * Performs the upgrade to TLS.
 */
static CURLcode smtp_perform_upgrade_tls(struct Curl_easy *data)
{
  /* Start the SSL connection */
  struct connectdata *conn = data->conn;
  struct smtp_conn *smtpc = &conn->proto.smtpc;
  CURLcode result = Curl_ssl_connect_nonblocking(data, conn, FIRSTSOCKET,
                                                 &smtpc->ssldone);

  if(!result) {
    if(smtpc->state != SMTP_UPGRADETLS)
      state(data, SMTP_UPGRADETLS);

    if(smtpc->ssldone) {
      smtp_to_smtps(conn);
      result = smtp_perform_ehlo(data);
    }
  }

  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 Curl_easy *data,
                                  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(data, &smtpc->pp, "AUTH %s %s", mech, initresp);
  }
  else {
    /* Send the AUTH command */
    result = Curl_pp_sendf(data, &smtpc->pp, "AUTH %s", mech);
  }

  return result;
}

/***********************************************************************
 *
 * smtp_continue_auth()
 *
 * Sends SASL continuation data or cancellation.
 */
static CURLcode smtp_continue_auth(struct Curl_easy *data,
                                   struct connectdata *conn, const char *resp)
{
  struct smtp_conn *smtpc = &conn->proto.smtpc;

  return Curl_pp_sendf(data, &smtpc->pp, "%s", resp);
}

/***********************************************************************
 *
 * smtp_perform_authentication()
 *
 * Initiates the authentication sequence, with the appropriate SASL
 * authentication mechanism.
 */
static CURLcode smtp_perform_authentication(struct Curl_easy *data)
{
  CURLcode result = CURLE_OK;
  struct connectdata *conn = data->conn;
  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(data, SMTP_STOP);
    return result;
  }

  /* Calculate the SASL login details */
  result = Curl_sasl_start(&smtpc->sasl, data, conn, FALSE, &progress);

  if(!result) {
    if(progress == SASL_INPROGRESS)
      state(data, SMTP_AUTH);
    else {
      /* Other mechanisms not supported */
      infof(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 Curl_easy *data)
{
  CURLcode result = CURLE_OK;
  struct connectdata *conn = data->conn;
  struct SMTP *smtp = data->req.p.smtp;

  if(smtp->rcpt) {
    /* We notify the server we are sending UTF-8 data if a) it supports the
       SMTPUTF8 extension and b) The mailbox contains UTF-8 charaacters, in
       either the local address or host name parts. This is regardless of
       whether the host name is encoded using IDN ACE */
    bool utf8 = FALSE;

    if((!smtp->custom) || (!smtp->custom[0])) {
      char *address = NULL;
      struct hostname host = { NULL, NULL, NULL, NULL };

      /* Parse the mailbox to verify into the local address and host name
         parts, converting the host name to an IDN A-label if necessary */
      result = smtp_parse_address(data, smtp->rcpt->data,
                                  &address, &host);
      if(result)
        return result;

      /* Establish whether we should report SMTPUTF8 to the server for this
         mailbox as per RFC-6531 sect. 3.1 point 6 */
      utf8 = (conn->proto.smtpc.utf8_supported) &&
             ((host.encalloc) || (!Curl_is_ASCII_name(address)) ||
              (!Curl_is_ASCII_name(host.name)));

      /* Send the VRFY command (Note: The host name part may be absent when the
         host is a local system) */
      result = Curl_pp_sendf(data, &conn->proto.smtpc.pp, "VRFY %s%s%s%s",
                             address,
                             host.name ? "@" : "",
                             host.name ? host.name : "",
                             utf8 ? " SMTPUTF8" : "");

      Curl_free_idnconverted_hostname(&host);
      free(address);
    }
    else {
      /* Establish whether we should report that we support SMTPUTF8 for EXPN
         commands to the server as per RFC-6531 sect. 3.1 point 6 */
      utf8 = (conn->proto.smtpc.utf8_supported) &&
             (!strcmp(smtp->custom, "EXPN"));

      /* Send the custom recipient based command such as the EXPN command */
      result = Curl_pp_sendf(data, &conn->proto.smtpc.pp,
                             "%s %s%s", smtp->custom,
                             smtp->rcpt->data,
                             utf8 ? " SMTPUTF8" : "");
    }
  }
  else
    /* Send the non-recipient based command such as HELP */
    result = Curl_pp_sendf(data, &conn->proto.smtpc.pp, "%s",
                           smtp->custom && smtp->custom[0] != '\0' ?
                           smtp->custom : "HELP");

  if(!result)
    state(data, SMTP_COMMAND);

  return result;
}

/***********************************************************************
 *
 * smtp_perform_mail()
 *
 * Sends an MAIL command to initiate the upload of a message.
 */
static CURLcode smtp_perform_mail(struct Curl_easy *data)
{
  char *from = NULL;
  char *auth = NULL;
  char *size = NULL;
  CURLcode result = CURLE_OK;
  struct connectdata *conn = data->conn;

  /* We notify the server we are sending UTF-8 data if a) it supports the
     SMTPUTF8 extension and b) The mailbox contains UTF-8 charaacters, in
     either the local address or host name parts. This is regardless of
     whether the host name is encoded using IDN ACE */
  bool utf8 = FALSE;

  /* Calculate the FROM parameter */
  if(data->set.str[STRING_MAIL_FROM]) {
    char *address = NULL;
    struct hostname host = { NULL, NULL, NULL, NULL };

    /* Parse the FROM mailbox into the local address and host name parts,
       converting the host name to an IDN A-label if necessary */
    result = smtp_parse_address(data, data->set.str[STRING_MAIL_FROM],
                                &address, &host);
    if(result)
      return result;

    /* Establish whether we should report SMTPUTF8 to the server for this
       mailbox as per RFC-6531 sect. 3.1 point 4 and sect. 3.4 */
    utf8 = (conn->proto.smtpc.utf8_supported) &&
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
  if(data->set.str[STRING_MAIL_AUTH] && conn->proto.smtpc.sasl.authused) {
    if(data->set.str[STRING_MAIL_AUTH][0] != '\0') {
      char *address = NULL;
      struct hostname host = { NULL, NULL, NULL, NULL };

      /* Parse the AUTH mailbox into the local address and host name parts,
         converting the host name to an IDN A-label if necessary */
      result = smtp_parse_address(conn, data->set.str[STRING_MAIL_AUTH],
                                  &address, &host);
      if(result) {
        free(from);
        return result;
      }

      /* Establish whether we should report SMTPUTF8 to the server for this







|







623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
  if(data->set.str[STRING_MAIL_AUTH] && conn->proto.smtpc.sasl.authused) {
    if(data->set.str[STRING_MAIL_AUTH][0] != '\0') {
      char *address = NULL;
      struct hostname host = { NULL, NULL, NULL, NULL };

      /* Parse the AUTH mailbox into the local address and host name parts,
         converting the host name to an IDN A-label if necessary */
      result = smtp_parse_address(data, data->set.str[STRING_MAIL_AUTH],
                                  &address, &host);
      if(result) {
        free(from);
        return result;
      }

      /* Establish whether we should report SMTPUTF8 to the server for this
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670

    /* Add external headers and mime version. */
    curl_mime_headers(&data->set.mimepost, data->set.headers, 0);
    result = Curl_mime_prepare_headers(&data->set.mimepost, NULL,
                                       NULL, MIMESTRATEGY_MAIL);

    if(!result)
      if(!Curl_checkheaders(conn, "Mime-Version"))
        result = Curl_mime_add_header(&data->set.mimepost.curlheaders,
                                      "Mime-Version: 1.0");

    /* Make sure we will read the entire mime structure. */
    if(!result)
      result = Curl_mime_rewind(&data->set.mimepost);








|







671
672
673
674
675
676
677
678
679
680
681
682
683
684
685

    /* Add external headers and mime version. */
    curl_mime_headers(&data->set.mimepost, data->set.headers, 0);
    result = Curl_mime_prepare_headers(&data->set.mimepost, NULL,
                                       NULL, MIMESTRATEGY_MAIL);

    if(!result)
      if(!Curl_checkheaders(data, "Mime-Version"))
        result = Curl_mime_add_header(&data->set.mimepost.curlheaders,
                                      "Mime-Version: 1.0");

    /* Make sure we will read the entire mime structure. */
    if(!result)
      result = Curl_mime_rewind(&data->set.mimepost);

708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764

765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781

782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837

838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
        utf8 = TRUE;

      rcpt = rcpt->next;
    }
  }

  /* Send the MAIL command */
  result = Curl_pp_sendf(&conn->proto.smtpc.pp,
                         "MAIL FROM:%s%s%s%s%s%s",
                         from,                 /* Mandatory                 */
                         auth ? " AUTH=" : "", /* Optional on AUTH support  */
                         auth ? auth : "",     /*                           */
                         size ? " SIZE=" : "", /* Optional on SIZE support  */
                         size ? size : "",     /*                           */
                         utf8 ? " SMTPUTF8"    /* Internationalised mailbox */
                               : "");          /* included in our envelope  */

  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 Curl_easy *data = conn->data;
  struct SMTP *smtp = data->req.p.smtp;
  char *address = NULL;
  struct hostname host = { NULL, NULL, NULL, NULL };

  /* Parse the recipient mailbox into the local address and host name parts,
     converting the host name to an IDN A-label if necessary */
  result = smtp_parse_address(conn, smtp->rcpt->data,
                              &address, &host);
  if(result)
    return result;

  /* Send the RCPT TO command */
  if(host.name)
    result = Curl_pp_sendf(&conn->proto.smtpc.pp, "RCPT TO:<%s@%s>", address,
                           host.name);
  else
    /* An invalid mailbox was provided but we'll simply let the server worry
       about that and reply with a 501 error */
    result = Curl_pp_sendf(&conn->proto.smtpc.pp, "RCPT TO:<%s>", address);


  Curl_free_idnconverted_hostname(&host);
  free(address);

  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)

{
  /* Send the QUIT command */
  CURLcode 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 Curl_easy *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_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 Curl_easy *data = conn->data;

  (void)instate; /* no use for this yet */

  if(smtpcode != 220) {
    if(data->set.use_ssl != CURLUSESSL_TRY) {
      failf(data, "STARTTLS denied, code %d", 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 Curl_easy *data = conn->data;
  struct smtp_conn *smtpc = &conn->proto.smtpc;
  const char *line = data->state.buffer;
  size_t len = strlen(line);

  (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 if(len >= 4) {
    line += 4;







|














|











|


|






|






|
|



|
>





|










|
>


|


|





|




<
<







|





|




<
<








|


|





|
>



<








|







723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814


815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832


833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854

855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
        utf8 = TRUE;

      rcpt = rcpt->next;
    }
  }

  /* Send the MAIL command */
  result = Curl_pp_sendf(data, &conn->proto.smtpc.pp,
                         "MAIL FROM:%s%s%s%s%s%s",
                         from,                 /* Mandatory                 */
                         auth ? " AUTH=" : "", /* Optional on AUTH support  */
                         auth ? auth : "",     /*                           */
                         size ? " SIZE=" : "", /* Optional on SIZE support  */
                         size ? size : "",     /*                           */
                         utf8 ? " SMTPUTF8"    /* Internationalised mailbox */
                               : "");          /* included in our envelope  */

  free(from);
  free(auth);
  free(size);

  if(!result)
    state(data, 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 Curl_easy *data)
{
  CURLcode result = CURLE_OK;
  struct connectdata *conn = data->conn;
  struct SMTP *smtp = data->req.p.smtp;
  char *address = NULL;
  struct hostname host = { NULL, NULL, NULL, NULL };

  /* Parse the recipient mailbox into the local address and host name parts,
     converting the host name to an IDN A-label if necessary */
  result = smtp_parse_address(data, smtp->rcpt->data,
                              &address, &host);
  if(result)
    return result;

  /* Send the RCPT TO command */
  if(host.name)
    result = Curl_pp_sendf(data, &conn->proto.smtpc.pp, "RCPT TO:<%s@%s>",
                           address, host.name);
  else
    /* An invalid mailbox was provided but we'll simply let the server worry
       about that and reply with a 501 error */
    result = Curl_pp_sendf(data, &conn->proto.smtpc.pp, "RCPT TO:<%s>",
                           address);

  Curl_free_idnconverted_hostname(&host);
  free(address);

  if(!result)
    state(data, SMTP_RCPT);

  return result;
}

/***********************************************************************
 *
 * smtp_perform_quit()
 *
 * Performs the quit action prior to sclose() being called.
 */
static CURLcode smtp_perform_quit(struct Curl_easy *data,
                                  struct connectdata *conn)
{
  /* Send the QUIT command */
  CURLcode result = Curl_pp_sendf(data, &conn->proto.smtpc.pp, "%s", "QUIT");

  if(!result)
    state(data, SMTP_QUIT);

  return result;
}

/* For the initial server greeting */
static CURLcode smtp_state_servergreet_resp(struct Curl_easy *data,
                                            int smtpcode,
                                            smtpstate instate)
{
  CURLcode result = CURLE_OK;


  (void)instate; /* no use for this yet */

  if(smtpcode/100 != 2) {
    failf(data, "Got unexpected smtp-server response: %d", smtpcode);
    result = CURLE_WEIRD_SERVER_REPLY;
  }
  else
    result = smtp_perform_ehlo(data);

  return result;
}

/* For STARTTLS responses */
static CURLcode smtp_state_starttls_resp(struct Curl_easy *data,
                                         int smtpcode,
                                         smtpstate instate)
{
  CURLcode result = CURLE_OK;


  (void)instate; /* no use for this yet */

  if(smtpcode != 220) {
    if(data->set.use_ssl != CURLUSESSL_TRY) {
      failf(data, "STARTTLS denied, code %d", smtpcode);
      result = CURLE_USE_SSL_FAILED;
    }
    else
      result = smtp_perform_authentication(data);
  }
  else
    result = smtp_perform_upgrade_tls(data);

  return result;
}

/* For EHLO responses */
static CURLcode smtp_state_ehlo_resp(struct Curl_easy *data,
                                     struct connectdata *conn, int smtpcode,
                                     smtpstate instate)
{
  CURLcode result = CURLE_OK;

  struct smtp_conn *smtpc = &conn->proto.smtpc;
  const char *line = data->state.buffer;
  size_t len = strlen(line);

  (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(data, conn);
    else {
      failf(data, "Remote access denied: %d", smtpcode);
      result = CURLE_REMOTE_ACCESS_DENIED;
    }
  }
  else if(len >= 4) {
    line += 4;
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055

1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
    }

    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);
    }
  }
  else {
    failf(data, "Unexpectedly short EHLO response");
    result = CURLE_WEIRD_SERVER_REPLY;
  }

  return result;
}

/* For HELO responses */
static CURLcode smtp_state_helo_resp(struct connectdata *conn, int smtpcode,
                                     smtpstate instate)
{
  CURLcode result = CURLE_OK;
  struct Curl_easy *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 Curl_easy *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 Curl_easy *data = conn->data;
  struct SMTP *smtp = data->req.p.smtp;
  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 Curl_easy *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 Curl_easy *data = conn->data;
  struct SMTP *smtp = data->req.p.smtp;
  bool is_smtp_err = FALSE;
  bool is_smtp_blocking_err = FALSE;

  (void)instate; /* no use for this yet */

  is_smtp_err = (smtpcode/100 != 2) ? TRUE : FALSE;







|


|






|











|



<
<








|





|




|





|



|













|



<















|









|



|



|







|



<
<








|





|
>



<







924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956


957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003

1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048


1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067

1068
1069
1070
1071
1072
1073
1074
    }

    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(data, conn);
        else if(data->set.use_ssl == CURLUSESSL_TRY)
          /* Fallback and carry on with authentication */
          result = smtp_perform_authentication(data);
        else {
          failf(data, "STARTTLS not supported.");
          result = CURLE_USE_SSL_FAILED;
        }
      }
      else
        result = smtp_perform_authentication(data);
    }
  }
  else {
    failf(data, "Unexpectedly short EHLO response");
    result = CURLE_WEIRD_SERVER_REPLY;
  }

  return result;
}

/* For HELO responses */
static CURLcode smtp_state_helo_resp(struct Curl_easy *data, int smtpcode,
                                     smtpstate instate)
{
  CURLcode result = CURLE_OK;


  (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(data, SMTP_STOP);

  return result;
}

/* For SASL authentication responses */
static CURLcode smtp_state_auth_resp(struct Curl_easy *data,
                                     int smtpcode,
                                     smtpstate instate)
{
  CURLcode result = CURLE_OK;
  struct connectdata *conn = data->conn;
  struct smtp_conn *smtpc = &conn->proto.smtpc;
  saslprogress progress;

  (void)instate; /* no use for this yet */

  result = Curl_sasl_continue(&smtpc->sasl, data, conn, smtpcode, &progress);
  if(!result)
    switch(progress) {
    case SASL_DONE:
      state(data, 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 Curl_easy *data, int smtpcode,
                                        smtpstate instate)
{
  CURLcode result = CURLE_OK;

  struct SMTP *smtp = data->req.p.smtp;
  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(data, 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(data);
        }
        else
          /* End of DO phase */
          state(data, SMTP_STOP);
      }
      else
        /* End of DO phase */
        state(data, SMTP_STOP);
    }
  }

  return result;
}

/* For MAIL responses */
static CURLcode smtp_state_mail_resp(struct Curl_easy *data, int smtpcode,
                                     smtpstate instate)
{
  CURLcode result = CURLE_OK;


  (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(data);

  return result;
}

/* For RCPT responses */
static CURLcode smtp_state_rcpt_resp(struct Curl_easy *data,
                                     struct connectdata *conn, int smtpcode,
                                     smtpstate instate)
{
  CURLcode result = CURLE_OK;

  struct SMTP *smtp = data->req.p.smtp;
  bool is_smtp_err = FALSE;
  bool is_smtp_blocking_err = FALSE;

  (void)instate; /* no use for this yet */

  is_smtp_err = (smtpcode/100 != 2) ? TRUE : FALSE;
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160

1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248

1249
1250
1251
1252

1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263

1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290

1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308

1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
  }

  if(!is_smtp_blocking_err) {
    smtp->rcpt = smtp->rcpt->next;

    if(smtp->rcpt)
      /* Send the next RCPT TO command */
      result = smtp_perform_rcpt_to(conn);
    else {
      /* We weren't able to issue a successful RCPT TO command while going
         over recipients (potentially multiple). Sending back last error. */
      if(!smtp->rcpt_had_ok) {
        failf(data, "RCPT failed: %d (last error)", smtp->rcpt_last_error);
        result = CURLE_SEND_ERROR;
      }
      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 Curl_easy *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(data, -1, -1, FALSE, FIRSTSOCKET);

    /* 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 Curl_easy *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, FALSE);
  *done = (smtpc->state == SMTP_STOP) ? TRUE : FALSE;

  return result;
}

static CURLcode smtp_block_statemach(struct connectdata *conn,

                                     bool disconnecting)
{
  CURLcode result = CURLE_OK;
  struct smtp_conn *smtpc = &conn->proto.smtpc;

  while(smtpc->state != SMTP_STOP && !result)
    result = Curl_pp_statemach(&smtpc->pp, TRUE, disconnecting);

  return result;
}

/* Allocate and initialize the SMTP struct for the current Curl_easy if
   required */
static CURLcode smtp_init(struct connectdata *conn)
{
  CURLcode result = CURLE_OK;
  struct Curl_easy *data = conn->data;
  struct SMTP *smtp;

  smtp = data->req.p.smtp = 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)
{
  return Curl_pp_getsock(&conn->proto.smtpc.pp, socks);
}

/***********************************************************************
 *
 * 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_setup(pp);
  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 Curl_easy *data = conn->data;
  struct SMTP *smtp = data->req.p.smtp;
  struct pingpong *pp = &conn->proto.smtpc.pp;
  char *eob;
  ssize_t len;
  ssize_t bytes_written;

  (void)premature;

  if(!smtp || !pp->conn)
    return CURLE_OK;

  /* Cleanup our per-request based variables */
  Curl_safefree(smtp->custom);

  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.mail_rcpt &&
          (data->set.upload || data->set.mimepost.kind)) {
    /* 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_now();

      free(eob);
    }

    state(conn, SMTP_POSTDATA);

    /* Run the state-machine */
    result = smtp_block_statemach(conn, FALSE);
  }

  /* 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 Curl_easy *data = conn->data;
  struct SMTP *smtp = data->req.p.smtp;

  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 */







|









|


|








|



<
<














|







|











|




|
>



<







|



|



|













|



|



|



|



|



|



|



|



|



|






|








|


>



|
>




|





|
>






|






|


<










>
|

|












|


>








<
<
|
<
<






|







|




|

|













|



|








|



















|












|



















|


|















|




|


|







1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126


1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170

1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288

1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326


1327


1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
  }

  if(!is_smtp_blocking_err) {
    smtp->rcpt = smtp->rcpt->next;

    if(smtp->rcpt)
      /* Send the next RCPT TO command */
      result = smtp_perform_rcpt_to(data);
    else {
      /* We weren't able to issue a successful RCPT TO command while going
         over recipients (potentially multiple). Sending back last error. */
      if(!smtp->rcpt_had_ok) {
        failf(data, "RCPT failed: %d (last error)", smtp->rcpt_last_error);
        result = CURLE_SEND_ERROR;
      }
      else {
        /* Send the DATA command */
        result = Curl_pp_sendf(data, &conn->proto.smtpc.pp, "%s", "DATA");

        if(!result)
          state(data, SMTP_DATA);
      }
    }
  }

  return result;
}

/* For DATA response */
static CURLcode smtp_state_data_resp(struct Curl_easy *data, int smtpcode,
                                     smtpstate instate)
{
  CURLcode result = CURLE_OK;


  (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(data, -1, -1, FALSE, FIRSTSOCKET);

    /* End of DO phase */
    state(data, 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 Curl_easy *data,
                                         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(data, SMTP_STOP);

  return result;
}

static CURLcode smtp_statemachine(struct Curl_easy *data,
                                  struct connectdata *conn)
{
  CURLcode result = CURLE_OK;
  curl_socket_t sock = conn->sock[FIRSTSOCKET];

  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(data);

  /* Flush any data that needs to be sent */
  if(pp->sendleft)
    return Curl_pp_flushsend(data, pp);

  do {
    /* Read the response from the server */
    result = Curl_pp_readresp(data, 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(data, smtpcode, smtpc->state);
      break;

    case SMTP_EHLO:
      result = smtp_state_ehlo_resp(data, conn, smtpcode, smtpc->state);
      break;

    case SMTP_HELO:
      result = smtp_state_helo_resp(data, smtpcode, smtpc->state);
      break;

    case SMTP_STARTTLS:
      result = smtp_state_starttls_resp(data, smtpcode, smtpc->state);
      break;

    case SMTP_AUTH:
      result = smtp_state_auth_resp(data, smtpcode, smtpc->state);
      break;

    case SMTP_COMMAND:
      result = smtp_state_command_resp(data, smtpcode, smtpc->state);
      break;

    case SMTP_MAIL:
      result = smtp_state_mail_resp(data, smtpcode, smtpc->state);
      break;

    case SMTP_RCPT:
      result = smtp_state_rcpt_resp(data, conn, smtpcode, smtpc->state);
      break;

    case SMTP_DATA:
      result = smtp_state_data_resp(data, smtpcode, smtpc->state);
      break;

    case SMTP_POSTDATA:
      result = smtp_state_postdata_resp(data, smtpcode, smtpc->state);
      break;

    case SMTP_QUIT:
      /* fallthrough, just stop! */
    default:
      /* internal error */
      state(data, 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 Curl_easy *data, bool *done)
{
  CURLcode result = CURLE_OK;
  struct connectdata *conn = data->conn;
  struct smtp_conn *smtpc = &conn->proto.smtpc;

  if((conn->handler->flags & PROTOPT_SSL) && !smtpc->ssldone) {
    result = Curl_ssl_connect_nonblocking(data, conn,
                                          FIRSTSOCKET, &smtpc->ssldone);
    if(result || !smtpc->ssldone)
      return result;
  }

  result = Curl_pp_statemach(data, &smtpc->pp, FALSE, FALSE);
  *done = (smtpc->state == SMTP_STOP) ? TRUE : FALSE;

  return result;
}

static CURLcode smtp_block_statemach(struct Curl_easy *data,
                                     struct connectdata *conn,
                                     bool disconnecting)
{
  CURLcode result = CURLE_OK;
  struct smtp_conn *smtpc = &conn->proto.smtpc;

  while(smtpc->state != SMTP_STOP && !result)
    result = Curl_pp_statemach(data, &smtpc->pp, TRUE, disconnecting);

  return result;
}

/* Allocate and initialize the SMTP struct for the current Curl_easy if
   required */
static CURLcode smtp_init(struct Curl_easy *data)
{
  CURLcode result = CURLE_OK;

  struct SMTP *smtp;

  smtp = data->req.p.smtp = 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 Curl_easy *data,
                        struct connectdata *conn, curl_socket_t *socks)
{
  return Curl_pp_getsock(data, &conn->proto.smtpc.pp, socks);
}

/***********************************************************************
 *
 * 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 Curl_easy *data, bool *done)
{
  CURLcode result = CURLE_OK;
  struct connectdata *conn = data->conn;
  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");



  PINGPONG_SETUP(pp, smtp_statemachine, smtp_endofresp);



  /* Initialize the SASL storage */
  Curl_sasl_init(&smtpc->sasl, &saslsmtp);

  /* Initialise the pingpong layer */
  Curl_pp_setup(pp);
  Curl_pp_init(data, pp);

  /* Parse the URL options */
  result = smtp_parse_url_options(conn);
  if(result)
    return result;

  /* Parse the URL path */
  result = smtp_parse_url_path(data);
  if(result)
    return result;

  /* Start off waiting for the server greeting response */
  state(data, SMTP_SERVERGREET);

  result = smtp_multi_statemach(data, 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 Curl_easy *data, CURLcode status,
                          bool premature)
{
  CURLcode result = CURLE_OK;
  struct connectdata *conn = data->conn;
  struct SMTP *smtp = data->req.p.smtp;
  struct pingpong *pp = &conn->proto.smtpc.pp;
  char *eob;
  ssize_t len;
  ssize_t bytes_written;

  (void)premature;

  if(!smtp)
    return CURLE_OK;

  /* Cleanup our per-request based variables */
  Curl_safefree(smtp->custom);

  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.mail_rcpt &&
          (data->set.upload || data->set.mimepost.kind)) {
    /* 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 || !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(data, 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_now();

      free(eob);
    }

    state(data, SMTP_POSTDATA);

    /* Run the state-machine */
    result = smtp_block_statemach(data, conn, FALSE);
  }

  /* 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 Curl_easy *data, bool *connected,
                             bool *dophase_done)
{
  /* This is SMTP and no proxy */
  CURLcode result = CURLE_OK;
  struct connectdata *conn = data->conn;
  struct SMTP *smtp = data->req.p.smtp;

  DEBUGF(infof(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 */
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527


1528
1529

1530
1531
1532
1533
1534
1535
1536
1537
1538
1539

1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618

1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
     preceded by a virtual CRLF. */
  smtp->trailing_crlf = TRUE;
  smtp->eob = 2;

  /* Start the first command in the DO phase */
  if((data->set.upload || data->set.mimepost.kind) && 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, TRUE); /* 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.p.smtp;

  (void)connected;

  if(smtp->transfer != FTPTRANSFER_BODY)
    /* no data to transfer */
    Curl_setup_transfer(conn->data, -1, -1, FALSE, -1);

  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 Curl_easy *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)

{
  CURLcode result;

  /* Clear the TLS upgraded flag */
  conn->bits.tls_upgraded = FALSE;

  /* Initialise the SMTP layer */
  result = smtp_init(conn);
  if(result)
    return result;

  return CURLE_OK;
}

/***********************************************************************







|


|





|




|













|


<



|



|











|
>
>


>





<
<
|
|
|
>














|

|





|





|

|


|

|

|














|




<











|



|




|
>







|







1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512

1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542


1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603

1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
     preceded by a virtual CRLF. */
  smtp->trailing_crlf = TRUE;
  smtp->eob = 2;

  /* Start the first command in the DO phase */
  if((data->set.upload || data->set.mimepost.kind) && data->set.mail_rcpt)
    /* MAIL transfer */
    result = smtp_perform_mail(data);
  else
    /* SMTP based command (VRFY, EXPN, NOOP, RSET or HELP) */
    result = smtp_perform_command(data);

  if(result)
    return result;

  /* Run the state-machine */
  result = smtp_multi_statemach(data, dophase_done);

  *connected = conn->bits.tcpconnect[FIRSTSOCKET];

  if(*dophase_done)
    DEBUGF(infof(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 Curl_easy *data, bool *done)
{
  CURLcode result = CURLE_OK;

  *done = FALSE; /* default to false */

  /* Parse the custom request */
  result = smtp_parse_custom_request(data);
  if(result)
    return result;

  result = smtp_regular_transfer(data, done);

  return result;
}

/***********************************************************************
 *
 * smtp_disconnect()
 *
 * Disconnect from an SMTP server. Cleanup protocol-specific per-connection
 * resources. BLOCKING.
 */
static CURLcode smtp_disconnect(struct Curl_easy *data,
                                struct connectdata *conn,
                                bool dead_connection)
{
  struct smtp_conn *smtpc = &conn->proto.smtpc;
  (void)data;

  /* 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. */



  if(!dead_connection && conn->bits.protoconnstart) {
    if(!smtp_perform_quit(data, conn))
      (void)smtp_block_statemach(data, conn, TRUE); /* 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 Curl_easy *data, bool connected)
{
  struct SMTP *smtp = data->req.p.smtp;

  (void)connected;

  if(smtp->transfer != FTPTRANSFER_BODY)
    /* no data to transfer */
    Curl_setup_transfer(data, -1, -1, FALSE, -1);

  return CURLE_OK;
}

/* Called from multi.c while DOing */
static CURLcode smtp_doing(struct Curl_easy *data, bool *dophase_done)
{
  CURLcode result = smtp_multi_statemach(data, dophase_done);

  if(result)
    DEBUGF(infof(data, "DO phase failed\n"));
  else if(*dophase_done) {
    result = smtp_dophase_done(data, FALSE /* not connected */);

    DEBUGF(infof(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 Curl_easy *data,
                                      bool *dophase_done)
{
  CURLcode result = CURLE_OK;
  bool connected = FALSE;


  /* 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(data, &connected, dophase_done);

  /* Perform post DO phase operations if necessary */
  if(!result && *dophase_done)
    result = smtp_dophase_done(data, connected);

  return result;
}

static CURLcode smtp_setup_connection(struct Curl_easy *data,
                                      struct connectdata *conn)
{
  CURLcode result;

  /* Clear the TLS upgraded flag */
  conn->bits.tls_upgraded = FALSE;

  /* Initialise the SMTP layer */
  result = smtp_init(data);
  if(result)
    return result;

  return CURLE_OK;
}

/***********************************************************************
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715

/***********************************************************************
 *
 * 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 Curl_easy *data = conn->data;
  struct smtp_conn *smtpc = &conn->proto.smtpc;
  const char *path = &data->state.up.path[1]; /* skip leading 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,
                        REJECT_CTRL);
}

/***********************************************************************
 *
 * smtp_parse_custom_request()
 *
 * Parse the custom request.
 */
static CURLcode smtp_parse_custom_request(struct connectdata *conn)
{
  CURLcode result = CURLE_OK;
  struct Curl_easy *data = conn->data;
  struct SMTP *smtp = data->req.p.smtp;
  const char *custom = data->set.str[STRING_CUSTOMREQUEST];

  /* URL decode the custom request */
  if(custom)
    result = Curl_urldecode(data, custom, 0, &smtp->custom, NULL, REJECT_CTRL);








|


|













|









|


<







1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714

1715
1716
1717
1718
1719
1720
1721

/***********************************************************************
 *
 * smtp_parse_url_path()
 *
 * Parse the URL path into separate path components.
 */
static CURLcode smtp_parse_url_path(struct Curl_easy *data)
{
  /* The SMTP struct is already initialised in smtp_connect() */
  struct connectdata *conn = data->conn;
  struct smtp_conn *smtpc = &conn->proto.smtpc;
  const char *path = &data->state.up.path[1]; /* skip leading 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(data, path, 0, &smtpc->domain, NULL,
                        REJECT_CTRL);
}

/***********************************************************************
 *
 * smtp_parse_custom_request()
 *
 * Parse the custom request.
 */
static CURLcode smtp_parse_custom_request(struct Curl_easy *data)
{
  CURLcode result = CURLE_OK;

  struct SMTP *smtp = data->req.p.smtp;
  const char *custom = data->set.str[STRING_CUSTOMREQUEST];

  /* URL decode the custom request */
  if(custom)
    result = Curl_urldecode(data, custom, 0, &smtp->custom, NULL, REJECT_CTRL);

1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
 * the data to the server as a U-label (as per RFC-6531 sect. 3.2).
 *
 * If an mailbox '@' separator cannot be located then the mailbox is considered
 * to be either a local mailbox or an invalid mailbox (depending on what the
 * calling function deems it to be) then the input will simply be returned in
 * the address part with the host name being NULL.
 */
static CURLcode smtp_parse_address(struct connectdata *conn, const char *fqma,
                                   char **address, struct hostname *host)
{
  CURLcode result = CURLE_OK;
  size_t length;

  /* Duplicate the fully qualified email address so we can manipulate it,
     ensuring it doesn't contain the delimiters if specified */







|







1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
 * the data to the server as a U-label (as per RFC-6531 sect. 3.2).
 *
 * If an mailbox '@' separator cannot be located then the mailbox is considered
 * to be either a local mailbox or an invalid mailbox (depending on what the
 * calling function deems it to be) then the input will simply be returned in
 * the address part with the host name being NULL.
 */
static CURLcode smtp_parse_address(struct Curl_easy *data, const char *fqma,
                                   char **address, struct hostname *host)
{
  CURLcode result = CURLE_OK;
  size_t length;

  /* Duplicate the fully qualified email address so we can manipulate it,
     ensuring it doesn't contain the delimiters if specified */
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
  /* Extract the host name from the address (if we can) */
  host->name = strpbrk(dup, "@");
  if(host->name) {
    *host->name = '\0';
    host->name = host->name + 1;

    /* Attempt to convert the host name to IDN ACE */
    (void) Curl_idnconvert_hostname(conn, host);

    /* If Curl_idnconvert_hostname() fails then we shall attempt to continue
       and send the host name using UTF-8 rather than as 7-bit ACE (which is
       our preference) */
  }

  /* Extract the local address from the mailbox */
  *address = dup;

  return result;
}

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 Curl_easy *data = conn->data;
  struct SMTP *smtp = data->req.p.smtp;
  char *scratch = data->state.scratch;
  char *newscratch = NULL;
  char *oldscratch = NULL;
  size_t eob_sent;

  /* Do we need to allocate a scratch buffer? */







|












|









<







1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806

1807
1808
1809
1810
1811
1812
1813
  /* Extract the host name from the address (if we can) */
  host->name = strpbrk(dup, "@");
  if(host->name) {
    *host->name = '\0';
    host->name = host->name + 1;

    /* Attempt to convert the host name to IDN ACE */
    (void) Curl_idnconvert_hostname(data, host);

    /* If Curl_idnconvert_hostname() fails then we shall attempt to continue
       and send the host name using UTF-8 rather than as 7-bit ACE (which is
       our preference) */
  }

  /* Extract the local address from the mailbox */
  *address = dup;

  return result;
}

CURLcode Curl_smtp_escape_eob(struct Curl_easy *data, 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 SMTP *smtp = data->req.p.smtp;
  char *scratch = data->state.scratch;
  char *newscratch = NULL;
  char *oldscratch = NULL;
  size_t eob_sent;

  /* Do we need to allocate a scratch buffer? */
Changes to jni/curl/lib/smtp.h.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#ifndef HEADER_CURL_SMTP_H
#define HEADER_CURL_SMTP_H
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 2009 - 2020, 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 https://curl.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









|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#ifndef HEADER_CURL_SMTP_H
#define HEADER_CURL_SMTP_H
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 2009 - 2021, 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 https://curl.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
53
54
55
56
57
58
59

60
61
62
63
64
65
66
67
68
69
70
   used. */
struct SMTP {
  curl_pp_transfer transfer;
  char *custom;            /* Custom Request */
  struct curl_slist *rcpt; /* Recipient list */
  bool rcpt_had_ok;        /* Whether any of RCPT TO commands (depends on
                              total number of recipients) succeeded so far */

  int rcpt_last_error;     /* The last error received for RCPT TO command */
  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! */







>



<







53
54
55
56
57
58
59
60
61
62
63

64
65
66
67
68
69
70
   used. */
struct SMTP {
  curl_pp_transfer transfer;
  char *custom;            /* Custom Request */
  struct curl_slist *rcpt; /* Recipient list */
  bool rcpt_had_ok;        /* Whether any of RCPT TO commands (depends on
                              total number of recipients) succeeded so far */
  bool trailing_crlf;      /* Specifies if the trailing CRLF is present */
  int rcpt_last_error;     /* The last error received for RCPT TO command */
  size_t eob;              /* Number of bytes of the EOB (End Of Body) that
                              have been received so far */

};

/* 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! */
87
88
89
90
91
92
93
94
95
96
#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

CURLcode Curl_smtp_escape_eob(struct connectdata *conn, const ssize_t nread);

#endif /* HEADER_CURL_SMTP_H */







|


87
88
89
90
91
92
93
94
95
96
#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

CURLcode Curl_smtp_escape_eob(struct Curl_easy *data, const ssize_t nread);

#endif /* HEADER_CURL_SMTP_H */
Changes to jni/curl/lib/socks.c.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2020, 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 https://curl.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







|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2021, 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 https://curl.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
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI)
/*
 * 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 behavior. Only used by the SOCKS GSSAPI functions.
 */
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 = 0;
  ssize_t allread = 0;
  int result;
  *n = 0;
  for(;;) {
    timediff_t timeout_ms = Curl_timeleft(conn->data, NULL, TRUE);
    if(timeout_ms < 0) {
      /* we already got the timeout */
      result = CURLE_OPERATION_TIMEDOUT;
      break;
    }
    if(!timeout_ms)
      timeout_ms = TIMEDIFF_T_MAX;







|










|







47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI)
/*
 * 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 behavior. Only used by the SOCKS GSSAPI functions.
 */
int Curl_blockread_all(struct Curl_easy *data,   /* transfer */
                       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 = 0;
  ssize_t allread = 0;
  int result;
  *n = 0;
  for(;;) {
    timediff_t timeout_ms = Curl_timeleft(data, NULL, TRUE);
    if(timeout_ms < 0) {
      /* we already got the timeout */
      result = CURLE_OPERATION_TIMEDOUT;
      break;
    }
    if(!timeout_ms)
      timeout_ms = TIMEDIFF_T_MAX;
103
104
105
106
107
108
109
110
111
112
113
114
115
116

117
118
119
120
121
122
123
#define sxstate(x,y) socksstate(x,y)
#else
#define sxstate(x,y) socksstate(x,y, __LINE__)
#endif


/* always use this function to change state, to make debugging easier */
static void socksstate(struct connectdata *conn,
                       enum connect_t state
#ifdef DEBUGBUILD
                       , int lineno
#endif
)
{

  enum connect_t oldstate = conn->cnnct.state;
#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
  /* synced with the state list in urldata.h */
  static const char * const statename[] = {
    "INIT",
    "SOCKS_INIT",
    "SOCKS_SEND",







|






>







103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
#define sxstate(x,y) socksstate(x,y)
#else
#define sxstate(x,y) socksstate(x,y, __LINE__)
#endif


/* always use this function to change state, to make debugging easier */
static void socksstate(struct Curl_easy *data,
                       enum connect_t state
#ifdef DEBUGBUILD
                       , int lineno
#endif
)
{
  struct connectdata *conn = data->conn;
  enum connect_t oldstate = conn->cnnct.state;
#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
  /* synced with the state list in urldata.h */
  static const char * const statename[] = {
    "INIT",
    "SOCKS_INIT",
    "SOCKS_SEND",
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
  if(oldstate == state)
    /* don't bother when the new state is the same as the old state */
    return;

  conn->cnnct.state = state;

#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
  infof(conn->data,
        "SXSTATE: %s => %s conn %p; line %d\n",
        statename[oldstate], statename[conn->cnnct.state], conn,
        lineno);
#endif
}

int Curl_SOCKS_getsock(struct connectdata *conn, curl_socket_t *sock,







|







143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
  if(oldstate == state)
    /* don't bother when the new state is the same as the old state */
    return;

  conn->cnnct.state = state;

#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
  infof(data,
        "SXSTATE: %s => %s conn %p; line %d\n",
        statename[oldstate], statename[conn->cnnct.state], conn,
        lineno);
#endif
}

int Curl_SOCKS_getsock(struct connectdata *conn, curl_socket_t *sock,
184
185
186
187
188
189
190
191
192
193

194
195
196
197
198
199
200
201
202
203
204



205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
*   Set protocol4a=true for  "SOCKS 4A (Simple Extension to SOCKS 4 Protocol)"
*   Nonsupport "Identification Protocol (RFC1413)"
*/
CURLproxycode Curl_SOCKS4(const char *proxy_user,
                          const char *hostname,
                          int remote_port,
                          int sockindex,
                          struct connectdata *conn,
                          bool *done)
{

  const bool protocol4a =
    (conn->socks_proxy.proxytype == CURLPROXY_SOCKS4A) ? TRUE : FALSE;
  unsigned char *socksreq = &conn->cnnct.socksreq[0];
  CURLcode result;
  curl_socket_t sockfd = conn->sock[sockindex];
  struct Curl_easy *data = conn->data;
  struct connstate *sx = &conn->cnnct;
  struct Curl_dns_entry *dns = NULL;
  ssize_t actualread;
  ssize_t written;




  if(!SOCKS_STATE(sx->state) && !*done)
    sxstate(conn, CONNECT_SOCKS_INIT);

  switch(sx->state) {
  case CONNECT_SOCKS_INIT:
    /* SOCKS4 can only do IPv4, insist! */
    conn->ip_version = CURL_IPRESOLVE_V4;
    if(conn->bits.httpproxy)
      infof(conn->data, "SOCKS4%s: connecting to HTTP proxy %s port %d\n",
            protocol4a ? "a" : "", hostname, remote_port);

    infof(data, "SOCKS4 communication to %s:%d\n", hostname, remote_port);

    /*
     * Compose socks4 request
     *







|


>


|


<





>
>
>

|






|







185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200

201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
*   Set protocol4a=true for  "SOCKS 4A (Simple Extension to SOCKS 4 Protocol)"
*   Nonsupport "Identification Protocol (RFC1413)"
*/
CURLproxycode Curl_SOCKS4(const char *proxy_user,
                          const char *hostname,
                          int remote_port,
                          int sockindex,
                          struct Curl_easy *data,
                          bool *done)
{
  struct connectdata *conn = data->conn;
  const bool protocol4a =
    (conn->socks_proxy.proxytype == CURLPROXY_SOCKS4A) ? TRUE : FALSE;
  unsigned char *socksreq = (unsigned char *)data->state.buffer;
  CURLcode result;
  curl_socket_t sockfd = conn->sock[sockindex];

  struct connstate *sx = &conn->cnnct;
  struct Curl_dns_entry *dns = NULL;
  ssize_t actualread;
  ssize_t written;

  /* make sure that the buffer is at least 600 bytes */
  DEBUGASSERT(READBUFFER_MIN >= 600);

  if(!SOCKS_STATE(sx->state) && !*done)
    sxstate(data, CONNECT_SOCKS_INIT);

  switch(sx->state) {
  case CONNECT_SOCKS_INIT:
    /* SOCKS4 can only do IPv4, insist! */
    conn->ip_version = CURL_IPRESOLVE_V4;
    if(conn->bits.httpproxy)
      infof(data, "SOCKS4%s: connecting to HTTP proxy %s port %d\n",
            protocol4a ? "a" : "", hostname, remote_port);

    infof(data, "SOCKS4 communication to %s:%d\n", hostname, remote_port);

    /*
     * Compose socks4 request
     *
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
    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) {
      enum resolve_t rc =
        Curl_resolv(conn, hostname, remote_port, FALSE, &dns);

      if(rc == CURLRESOLV_ERROR)
        return CURLPX_RESOLVE_HOST;
      else if(rc == CURLRESOLV_PENDING) {
        sxstate(conn, CONNECT_RESOLVING);
        infof(data, "SOCKS4 non-blocking resolve of %s\n", hostname);
        return CURLPX_OK;
      }
      sxstate(conn, CONNECT_RESOLVED);
      goto CONNECT_RESOLVED;
    }

    /* socks4a doesn't resolve anything locally */
    sxstate(conn, CONNECT_REQ_INIT);
    goto CONNECT_REQ_INIT;

  case CONNECT_RESOLVING:
    /* check if we have the name resolved by now */
    dns = Curl_fetch_addr(conn, hostname, (int)conn->port);

    if(dns) {
#ifdef CURLRES_ASYNCH
      conn->async.dns = dns;
      conn->async.done = TRUE;
#endif
      infof(data, "Hostname '%s' was found\n", hostname);
      sxstate(conn, CONNECT_RESOLVED);
    }
    else {
      result = Curl_resolv_check(data->conn, &dns);
      if(!dns) {
        if(result)
          return CURLPX_RESOLVE_HOST;
        return CURLPX_OK;
      }
    }
    /* FALLTHROUGH */







|




|



|




|




|



|
|


|


|







234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
    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) {
      enum resolve_t rc =
        Curl_resolv(data, hostname, remote_port, FALSE, &dns);

      if(rc == CURLRESOLV_ERROR)
        return CURLPX_RESOLVE_HOST;
      else if(rc == CURLRESOLV_PENDING) {
        sxstate(data, CONNECT_RESOLVING);
        infof(data, "SOCKS4 non-blocking resolve of %s\n", hostname);
        return CURLPX_OK;
      }
      sxstate(data, CONNECT_RESOLVED);
      goto CONNECT_RESOLVED;
    }

    /* socks4a doesn't resolve anything locally */
    sxstate(data, CONNECT_REQ_INIT);
    goto CONNECT_REQ_INIT;

  case CONNECT_RESOLVING:
    /* check if we have the name resolved by now */
    dns = Curl_fetch_addr(data, hostname, (int)conn->port);

    if(dns) {
#ifdef CURLRES_ASYNCH
      data->state.async.dns = dns;
      data->state.async.done = TRUE;
#endif
      infof(data, "Hostname '%s' was found\n", hostname);
      sxstate(data, CONNECT_RESOLVED);
    }
    else {
      result = Curl_resolv_check(data, &dns);
      if(!dns) {
        if(result)
          return CURLPX_RESOLVE_HOST;
        return CURLPX_OK;
      }
    }
    /* FALLTHROUGH */
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
        socksreq[6] = ((unsigned char *)&saddr_in->sin_addr.s_addr)[2];
        socksreq[7] = ((unsigned char *)&saddr_in->sin_addr.s_addr)[3];

        infof(data, "SOCKS4 connect to IPv4 %s (locally resolved)\n", buf);
      }
      else {
        hp = NULL; /* fail! */
        failf(data, "SOCKS4 connection to %s not supported\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 CURLPX_RESOLVE_HOST;
    }
  }
    /* FALLTHROUGH */
  CONNECT_REQ_INIT:
  case CONNECT_REQ_INIT:
    /*
     * This is currently not supporting "Identification Protocol (RFC1413)".
     */
    socksreq[8] = 0; /* ensure empty userid is NUL-terminated */
    if(proxy_user) {
      size_t plen = strlen(proxy_user);
      if(plen >= sizeof(sx->socksreq) - 8) {
        failf(data, "Too long SOCKS proxy user name, can't use!\n");
        return CURLPX_LONG_USER;
      }
      /* copy the proxy name WITH trailing zero */
      memcpy(socksreq + 8, proxy_user, plen + 1);
    }

    /*







|



















|
|







298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
        socksreq[6] = ((unsigned char *)&saddr_in->sin_addr.s_addr)[2];
        socksreq[7] = ((unsigned char *)&saddr_in->sin_addr.s_addr)[3];

        infof(data, "SOCKS4 connect to IPv4 %s (locally resolved)\n", buf);
      }
      else {
        hp = NULL; /* fail! */
        failf(data, "SOCKS4 connection to %s not supported", 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 CURLPX_RESOLVE_HOST;
    }
  }
    /* FALLTHROUGH */
  CONNECT_REQ_INIT:
  case CONNECT_REQ_INIT:
    /*
     * This is currently not supporting "Identification Protocol (RFC1413)".
     */
    socksreq[8] = 0; /* ensure empty userid is NUL-terminated */
    if(proxy_user) {
      size_t plen = strlen(proxy_user);
      if(plen >= (size_t)data->set.buffer_size - 8) {
        failf(data, "Too long SOCKS proxy user name, can't use!");
        return CURLPX_LONG_USER;
      }
      /* copy the proxy name WITH trailing zero */
      memcpy(socksreq + 8, proxy_user, plen + 1);
    }

    /*
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
          failf(data, "SOCKS4: too long host name");
          return CURLPX_LONG_HOSTNAME;
        }
        packetsize += hostnamelen;
      }
      sx->outp = socksreq;
      sx->outstanding = packetsize;
      sxstate(conn, CONNECT_REQ_SENDING);
    }
    /* FALLTHROUGH */
  case CONNECT_REQ_SENDING:
    /* Send request */
    result = Curl_write_plain(conn, sockfd, (char *)sx->outp,
                              sx->outstanding, &written);
    if(result && (CURLE_AGAIN != result)) {
      failf(data, "Failed to send SOCKS4 connect request.");
      return CURLPX_SEND_CONNECT;
    }
    if(written != sx->outstanding) {
      /* not done, remain in state */
      sx->outstanding -= written;
      sx->outp += written;
      return CURLPX_OK;
    }

    /* done sending! */
    sx->outstanding = 8; /* receive data size */
    sx->outp = socksreq;
    sxstate(conn, CONNECT_SOCKS_READ);

    /* FALLTHROUGH */
  case CONNECT_SOCKS_READ:
    /* Receive response */
    result = Curl_read_plain(sockfd, (char *)sx->outp,
                             sx->outstanding, &actualread);
    if(result && (CURLE_AGAIN != result)) {







|




|















|







352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
          failf(data, "SOCKS4: too long host name");
          return CURLPX_LONG_HOSTNAME;
        }
        packetsize += hostnamelen;
      }
      sx->outp = socksreq;
      sx->outstanding = packetsize;
      sxstate(data, CONNECT_REQ_SENDING);
    }
    /* FALLTHROUGH */
  case CONNECT_REQ_SENDING:
    /* Send request */
    result = Curl_write_plain(data, sockfd, (char *)sx->outp,
                              sx->outstanding, &written);
    if(result && (CURLE_AGAIN != result)) {
      failf(data, "Failed to send SOCKS4 connect request.");
      return CURLPX_SEND_CONNECT;
    }
    if(written != sx->outstanding) {
      /* not done, remain in state */
      sx->outstanding -= written;
      sx->outp += written;
      return CURLPX_OK;
    }

    /* done sending! */
    sx->outstanding = 8; /* receive data size */
    sx->outp = socksreq;
    sxstate(data, CONNECT_SOCKS_READ);

    /* FALLTHROUGH */
  case CONNECT_SOCKS_READ:
    /* Receive response */
    result = Curl_read_plain(sockfd, (char *)sx->outp,
                             sx->outstanding, &actualread);
    if(result && (CURLE_AGAIN != result)) {
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
    }
    else if(actualread != sx->outstanding) {
      /* remain in reading state */
      sx->outstanding -= actualread;
      sx->outp += actualread;
      return CURLPX_OK;
    }
    sxstate(conn, CONNECT_DONE);
    break;
  default: /* lots of unused states in SOCKS4 */
    break;
  }

  /*
   * Response format







|







396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
    }
    else if(actualread != sx->outstanding) {
      /* remain in reading state */
      sx->outstanding -= actualread;
      sx->outp += actualread;
      return CURLPX_OK;
    }
    sxstate(data, CONNECT_DONE);
    break;
  default: /* lots of unused states in SOCKS4 */
    break;
  }

  /*
   * Response format
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507

508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
  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],
          (((unsigned char)socksreq[2] << 8) | (unsigned char)socksreq[3]),
          (unsigned char)socksreq[1]);
    return CURLPX_REQUEST_FAILED;
  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],
          (((unsigned char)socksreq[2] << 8) | (unsigned char)socksreq[3]),
          (unsigned char)socksreq[1]);
    return CURLPX_IDENTD;
  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],
          (((unsigned char)socksreq[2] << 8) | (unsigned char)socksreq[3]),
          (unsigned char)socksreq[1]);
    return CURLPX_IDENTD_DIFFER;
  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],
          (((unsigned char)socksreq[2] << 8) | (unsigned char)socksreq[3]),
          (unsigned char)socksreq[1]);
    return CURLPX_UNKNOWN_FAIL;
  }

  *done = TRUE;
  return CURLPX_OK; /* Proxy was successful! */
}

/*
 * This function logs in to a SOCKS5 proxy and sends the specifics to the final
 * destination server.
 */
CURLproxycode Curl_SOCKS5(const char *proxy_user,
                          const char *proxy_password,
                          const char *hostname,
                          int remote_port,
                          int sockindex,
                          struct connectdata *conn,
                          bool *done)
{
  /*
    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 = &conn->cnnct.socksreq[0];
  char dest[256] = "unknown";  /* printable hostname:port */
  int idx;
  ssize_t actualread;
  ssize_t written;
  CURLcode result;
  curl_socket_t sockfd = conn->sock[sockindex];
  struct Curl_easy *data = conn->data;
  bool socks5_resolve_local =
    (conn->socks_proxy.proxytype == CURLPROXY_SOCKS5) ? TRUE : FALSE;
  const size_t hostname_len = strlen(hostname);
  ssize_t len = 0;
  const unsigned long auth = data->set.socks5auth;
  bool allow_gssapi = FALSE;
  struct connstate *sx = &conn->cnnct;
  struct Curl_dns_entry *dns = NULL;

  if(!SOCKS_STATE(sx->state) && !*done)
    sxstate(conn, CONNECT_SOCKS_INIT);

  switch(sx->state) {
  case CONNECT_SOCKS_INIT:
    if(conn->bits.httpproxy)
      infof(conn->data, "SOCKS5: connecting to HTTP proxy %s port %d\n",
            hostname, remote_port);

    /* 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;
    }

    if(auth & ~(CURLAUTH_BASIC | CURLAUTH_GSSAPI))
      infof(conn->data,
            "warning: unsupported value passed to CURLOPT_SOCKS5_AUTH: %lu\n",
            auth);
    if(!(auth & CURLAUTH_BASIC))
      /* disable username/password auth */
      proxy_user = NULL;
#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI)
    if(auth & CURLAUTH_GSSAPI)







|
<








|
<








|
<







|
<


















|


















>
|






<










|




|




|





|







437
438
439
440
441
442
443
444

445
446
447
448
449
450
451
452
453

454
455
456
457
458
459
460
461
462

463
464
465
466
467
468
469
470

471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515

516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
  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.",
          socksreq[4], socksreq[5], socksreq[6], socksreq[7],

          (((unsigned char)socksreq[2] << 8) | (unsigned char)socksreq[3]),
          (unsigned char)socksreq[1]);
    return CURLPX_REQUEST_FAILED;
  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.",
          socksreq[4], socksreq[5], socksreq[6], socksreq[7],

          (((unsigned char)socksreq[2] << 8) | (unsigned char)socksreq[3]),
          (unsigned char)socksreq[1]);
    return CURLPX_IDENTD;
  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.",
          socksreq[4], socksreq[5], socksreq[6], socksreq[7],

          (((unsigned char)socksreq[2] << 8) | (unsigned char)socksreq[3]),
          (unsigned char)socksreq[1]);
    return CURLPX_IDENTD_DIFFER;
  default:
    failf(data,
          "Can't complete SOCKS4 connection to %d.%d.%d.%d:%d. (%d)"
          ", Unknown.",
          socksreq[4], socksreq[5], socksreq[6], socksreq[7],

          (((unsigned char)socksreq[2] << 8) | (unsigned char)socksreq[3]),
          (unsigned char)socksreq[1]);
    return CURLPX_UNKNOWN_FAIL;
  }

  *done = TRUE;
  return CURLPX_OK; /* Proxy was successful! */
}

/*
 * This function logs in to a SOCKS5 proxy and sends the specifics to the final
 * destination server.
 */
CURLproxycode Curl_SOCKS5(const char *proxy_user,
                          const char *proxy_password,
                          const char *hostname,
                          int remote_port,
                          int sockindex,
                          struct Curl_easy *data,
                          bool *done)
{
  /*
    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
  */
  struct connectdata *conn = data->conn;
  unsigned char *socksreq = (unsigned char *)data->state.buffer;
  char dest[256] = "unknown";  /* printable hostname:port */
  int idx;
  ssize_t actualread;
  ssize_t written;
  CURLcode result;
  curl_socket_t sockfd = conn->sock[sockindex];

  bool socks5_resolve_local =
    (conn->socks_proxy.proxytype == CURLPROXY_SOCKS5) ? TRUE : FALSE;
  const size_t hostname_len = strlen(hostname);
  ssize_t len = 0;
  const unsigned long auth = data->set.socks5auth;
  bool allow_gssapi = FALSE;
  struct connstate *sx = &conn->cnnct;
  struct Curl_dns_entry *dns = NULL;

  if(!SOCKS_STATE(sx->state) && !*done)
    sxstate(data, CONNECT_SOCKS_INIT);

  switch(sx->state) {
  case CONNECT_SOCKS_INIT:
    if(conn->bits.httpproxy)
      infof(data, "SOCKS5: connecting to HTTP proxy %s port %d\n",
            hostname, remote_port);

    /* RFC1928 chapter 5 specifies max 255 chars for domain name in packet */
    if(!socks5_resolve_local && hostname_len > 255) {
      infof(data, "SOCKS5: server resolving disabled for hostnames of "
            "length > 255 [actual len=%zu]\n", hostname_len);
      socks5_resolve_local = TRUE;
    }

    if(auth & ~(CURLAUTH_BASIC | CURLAUTH_GSSAPI))
      infof(data,
            "warning: unsupported value passed to CURLOPT_SOCKS5_AUTH: %lu\n",
            auth);
    if(!(auth & CURLAUTH_BASIC))
      /* disable username/password auth */
      proxy_user = NULL;
#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI)
    if(auth & CURLAUTH_GSSAPI)
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
    if(allow_gssapi)
      socksreq[idx++] = 1; /* GSS-API */
    if(proxy_user)
      socksreq[idx++] = 2; /* username/password */
    /* write the number of authentication methods */
    socksreq[1] = (unsigned char) (idx - 2);

    result = Curl_write_plain(conn, sockfd, (char *)socksreq, idx, &written);
    if(result && (CURLE_AGAIN != result)) {
      failf(data, "Unable to send initial SOCKS5 request.");
      return CURLPX_SEND_CONNECT;
    }
    if(written != idx) {
      sxstate(conn, CONNECT_SOCKS_SEND);
      sx->outstanding = idx - written;
      sx->outp = &socksreq[written];
      return CURLPX_OK;
    }
    sxstate(conn, CONNECT_SOCKS_READ);
    goto CONNECT_SOCKS_READ_INIT;
  case CONNECT_SOCKS_SEND:
    result = Curl_write_plain(conn, sockfd, (char *)sx->outp,
                              sx->outstanding, &written);
    if(result && (CURLE_AGAIN != result)) {
      failf(data, "Unable to send initial SOCKS5 request.");
      return CURLPX_SEND_CONNECT;
    }
    if(written != sx->outstanding) {
      /* not done, remain in state */







|





|




|


|







557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
    if(allow_gssapi)
      socksreq[idx++] = 1; /* GSS-API */
    if(proxy_user)
      socksreq[idx++] = 2; /* username/password */
    /* write the number of authentication methods */
    socksreq[1] = (unsigned char) (idx - 2);

    result = Curl_write_plain(data, sockfd, (char *)socksreq, idx, &written);
    if(result && (CURLE_AGAIN != result)) {
      failf(data, "Unable to send initial SOCKS5 request.");
      return CURLPX_SEND_CONNECT;
    }
    if(written != idx) {
      sxstate(data, CONNECT_SOCKS_SEND);
      sx->outstanding = idx - written;
      sx->outp = &socksreq[written];
      return CURLPX_OK;
    }
    sxstate(data, CONNECT_SOCKS_READ);
    goto CONNECT_SOCKS_READ_INIT;
  case CONNECT_SOCKS_SEND:
    result = Curl_write_plain(data, sockfd, (char *)sx->outp,
                              sx->outstanding, &written);
    if(result && (CURLE_AGAIN != result)) {
      failf(data, "Unable to send initial SOCKS5 request.");
      return CURLPX_SEND_CONNECT;
    }
    if(written != sx->outstanding) {
      /* not done, remain in state */
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
    }
    else if(socksreq[0] != 5) {
      failf(data, "Received invalid version in initial SOCKS5 response.");
      return CURLPX_BAD_VERSION;
    }
    else if(socksreq[1] == 0) {
      /* DONE! No authentication needed. Send request. */
      sxstate(conn, CONNECT_REQ_INIT);
      goto CONNECT_REQ_INIT;
    }
    else if(socksreq[1] == 2) {
      /* regular name + password authentication */
      sxstate(conn, CONNECT_AUTH_INIT);
      goto CONNECT_AUTH_INIT;
    }
#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI)
    else if(allow_gssapi && (socksreq[1] == 1)) {
      sxstate(conn, CONNECT_GSSAPI_INIT);
      result = Curl_SOCKS5_gssapi_negotiate(sockindex, conn);
      if(result) {
        failf(data, "Unable to negotiate SOCKS5 GSS-API context.");
        return CURLPX_GSSAPI;
      }
    }
#endif
    else {







|




|




|
|







613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
    }
    else if(socksreq[0] != 5) {
      failf(data, "Received invalid version in initial SOCKS5 response.");
      return CURLPX_BAD_VERSION;
    }
    else if(socksreq[1] == 0) {
      /* DONE! No authentication needed. Send request. */
      sxstate(data, CONNECT_REQ_INIT);
      goto CONNECT_REQ_INIT;
    }
    else if(socksreq[1] == 2) {
      /* regular name + password authentication */
      sxstate(data, CONNECT_AUTH_INIT);
      goto CONNECT_AUTH_INIT;
    }
#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI)
    else if(allow_gssapi && (socksreq[1] == 1)) {
      sxstate(data, CONNECT_GSSAPI_INIT);
      result = Curl_SOCKS5_gssapi_negotiate(sockindex, data);
      if(result) {
        failf(data, "Unable to negotiate SOCKS5 GSS-API context.");
        return CURLPX_GSSAPI;
      }
    }
#endif
    else {
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
      if(proxy_password_len > 255) {
        failf(data, "Excessive password length for proxy auth");
        return CURLPX_LONG_PASSWD;
      }
      memcpy(socksreq + len, proxy_password, proxy_password_len);
    }
    len += proxy_password_len;
    sxstate(conn, CONNECT_AUTH_SEND);
    sx->outstanding = len;
    sx->outp = socksreq;
  }
    /* FALLTHROUGH */
  case CONNECT_AUTH_SEND:
    result = Curl_write_plain(conn, sockfd, (char *)sx->outp,
                              sx->outstanding, &written);
    if(result && (CURLE_AGAIN != result)) {
      failf(data, "Failed to send SOCKS5 sub-negotiation request.");
      return CURLPX_SEND_AUTH;
    }
    if(sx->outstanding != written) {
      /* remain in state */
      sx->outstanding -= written;
      sx->outp += written;
      return CURLPX_OK;
    }
    sx->outp = socksreq;
    sx->outstanding = 2;
    sxstate(conn, CONNECT_AUTH_READ);
    /* FALLTHROUGH */
  case CONNECT_AUTH_READ:
    result = Curl_read_plain(sockfd, (char *)sx->outp,
                             sx->outstanding, &actualread);
    if(result && (CURLE_AGAIN != result)) {
      failf(data, "Unable to receive SOCKS5 sub-negotiation response.");
      return CURLPX_RECV_AUTH;







|





|













|







697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
      if(proxy_password_len > 255) {
        failf(data, "Excessive password length for proxy auth");
        return CURLPX_LONG_PASSWD;
      }
      memcpy(socksreq + len, proxy_password, proxy_password_len);
    }
    len += proxy_password_len;
    sxstate(data, CONNECT_AUTH_SEND);
    sx->outstanding = len;
    sx->outp = socksreq;
  }
    /* FALLTHROUGH */
  case CONNECT_AUTH_SEND:
    result = Curl_write_plain(data, sockfd, (char *)sx->outp,
                              sx->outstanding, &written);
    if(result && (CURLE_AGAIN != result)) {
      failf(data, "Failed to send SOCKS5 sub-negotiation request.");
      return CURLPX_SEND_AUTH;
    }
    if(sx->outstanding != written) {
      /* remain in state */
      sx->outstanding -= written;
      sx->outp += written;
      return CURLPX_OK;
    }
    sx->outp = socksreq;
    sx->outstanding = 2;
    sxstate(data, CONNECT_AUTH_READ);
    /* FALLTHROUGH */
  case CONNECT_AUTH_READ:
    result = Curl_read_plain(sockfd, (char *)sx->outp,
                             sx->outstanding, &actualread);
    if(result && (CURLE_AGAIN != result)) {
      failf(data, "Unable to receive SOCKS5 sub-negotiation response.");
      return CURLPX_RECV_AUTH;
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
    else if(socksreq[1] != 0) { /* status */
      failf(data, "User was rejected by the SOCKS5 server (%d %d).",
            socksreq[0], socksreq[1]);
      return CURLPX_USER_REJECTED;
    }

    /* Everything is good so far, user was authenticated! */
    sxstate(conn, CONNECT_REQ_INIT);
    /* FALLTHROUGH */
  CONNECT_REQ_INIT:
  case CONNECT_REQ_INIT:
    if(socks5_resolve_local) {
      enum resolve_t rc = Curl_resolv(conn, hostname, remote_port,
                                      FALSE, &dns);

      if(rc == CURLRESOLV_ERROR)
        return CURLPX_RESOLVE_HOST;

      if(rc == CURLRESOLV_PENDING) {
        sxstate(conn, CONNECT_RESOLVING);
        return CURLPX_OK;
      }
      sxstate(conn, CONNECT_RESOLVED);
      goto CONNECT_RESOLVED;
    }
    goto CONNECT_RESOLVE_REMOTE;

  case CONNECT_RESOLVING:
    /* check if we have the name resolved by now */
    dns = Curl_fetch_addr(conn, hostname, remote_port);

    if(dns) {
#ifdef CURLRES_ASYNCH
      conn->async.dns = dns;
      conn->async.done = TRUE;
#endif
      infof(data, "SOCKS5: hostname '%s' found\n", hostname);
    }

    if(!dns) {
      result = Curl_resolv_check(data->conn, &dns);
      if(!dns) {
        if(result)
          return CURLPX_RESOLVE_HOST;
        return CURLPX_OK;
      }
    }
    /* FALLTHROUGH */







|




|






|


|






|



|
|





|







745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
    else if(socksreq[1] != 0) { /* status */
      failf(data, "User was rejected by the SOCKS5 server (%d %d).",
            socksreq[0], socksreq[1]);
      return CURLPX_USER_REJECTED;
    }

    /* Everything is good so far, user was authenticated! */
    sxstate(data, CONNECT_REQ_INIT);
    /* FALLTHROUGH */
  CONNECT_REQ_INIT:
  case CONNECT_REQ_INIT:
    if(socks5_resolve_local) {
      enum resolve_t rc = Curl_resolv(data, hostname, remote_port,
                                      FALSE, &dns);

      if(rc == CURLRESOLV_ERROR)
        return CURLPX_RESOLVE_HOST;

      if(rc == CURLRESOLV_PENDING) {
        sxstate(data, CONNECT_RESOLVING);
        return CURLPX_OK;
      }
      sxstate(data, CONNECT_RESOLVED);
      goto CONNECT_RESOLVED;
    }
    goto CONNECT_RESOLVE_REMOTE;

  case CONNECT_RESOLVING:
    /* check if we have the name resolved by now */
    dns = Curl_fetch_addr(data, hostname, remote_port);

    if(dns) {
#ifdef CURLRES_ASYNCH
      data->state.async.dns = dns;
      data->state.async.done = TRUE;
#endif
      infof(data, "SOCKS5: hostname '%s' found\n", hostname);
    }

    if(!dns) {
      result = Curl_resolv_check(data, &dns);
      if(!dns) {
        if(result)
          return CURLPX_RESOLVE_HOST;
        return CURLPX_OK;
      }
    }
    /* FALLTHROUGH */
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
      }

      infof(data, "SOCKS5 connect to IPv6 %s (locally resolved)\n", dest);
    }
#endif
    else {
      hp = NULL; /* fail! */
      failf(data, "SOCKS5 connection to %s not supported\n", dest);
    }

    Curl_resolv_unlock(data, dns); /* not used anymore from now on */
    goto CONNECT_REQ_SEND;
  }
  CONNECT_RESOLVE_REMOTE:
  case CONNECT_RESOLVE_REMOTE:







|







835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
      }

      infof(data, "SOCKS5 connect to IPv6 %s (locally resolved)\n", dest);
    }
#endif
    else {
      hp = NULL; /* fail! */
      failf(data, "SOCKS5 connection to %s not supported", dest);
    }

    Curl_resolv_unlock(data, dns); /* not used anymore from now on */
    goto CONNECT_REQ_SEND;
  }
  CONNECT_RESOLVE_REMOTE:
  case CONNECT_RESOLVE_REMOTE:
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
    if(conn->socks5_gssapi_enctype) {
      failf(data, "SOCKS5 GSS-API protection not yet implemented.");
      return CURLPX_GSSAPI_PROTECTION;
    }
#endif
    sx->outp = socksreq;
    sx->outstanding = len;
    sxstate(conn, CONNECT_REQ_SENDING);
    /* FALLTHROUGH */
  case CONNECT_REQ_SENDING:
    result = Curl_write_plain(conn, sockfd, (char *)sx->outp,
                              sx->outstanding, &written);
    if(result && (CURLE_AGAIN != result)) {
      failf(data, "Failed to send SOCKS5 connect request.");
      return CURLPX_SEND_REQUEST;
    }
    if(sx->outstanding != written) {
      /* remain in state */
      sx->outstanding -= written;
      sx->outp += written;
      return CURLPX_OK;
    }
#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI)
    if(conn->socks5_gssapi_enctype) {
      failf(data, "SOCKS5 GSS-API protection not yet implemented.");
      return CURLPX_GSSAPI_PROTECTION;
    }
#endif
    sx->outstanding = 10; /* minimum packet size is 10 */
    sx->outp = socksreq;
    sxstate(conn, CONNECT_REQ_READ);
    /* FALLTHROUGH */
  case CONNECT_REQ_READ:
    result = Curl_read_plain(sockfd, (char *)sx->outp,
                             sx->outstanding, &actualread);
    if(result && (CURLE_AGAIN != result)) {
      failf(data, "Failed to receive SOCKS5 connect request ack.");
      return CURLPX_RECV_REQACK;







|


|



















|







874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
    if(conn->socks5_gssapi_enctype) {
      failf(data, "SOCKS5 GSS-API protection not yet implemented.");
      return CURLPX_GSSAPI_PROTECTION;
    }
#endif
    sx->outp = socksreq;
    sx->outstanding = len;
    sxstate(data, CONNECT_REQ_SENDING);
    /* FALLTHROUGH */
  case CONNECT_REQ_SENDING:
    result = Curl_write_plain(data, sockfd, (char *)sx->outp,
                              sx->outstanding, &written);
    if(result && (CURLE_AGAIN != result)) {
      failf(data, "Failed to send SOCKS5 connect request.");
      return CURLPX_SEND_REQUEST;
    }
    if(sx->outstanding != written) {
      /* remain in state */
      sx->outstanding -= written;
      sx->outp += written;
      return CURLPX_OK;
    }
#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI)
    if(conn->socks5_gssapi_enctype) {
      failf(data, "SOCKS5 GSS-API protection not yet implemented.");
      return CURLPX_GSSAPI_PROTECTION;
    }
#endif
    sx->outstanding = 10; /* minimum packet size is 10 */
    sx->outp = socksreq;
    sxstate(data, CONNECT_REQ_READ);
    /* FALLTHROUGH */
  case CONNECT_REQ_READ:
    result = Curl_read_plain(sockfd, (char *)sx->outp,
                             sx->outstanding, &actualread);
    if(result && (CURLE_AGAIN != result)) {
      failf(data, "Failed to receive SOCKS5 connect request ack.");
      return CURLPX_RECV_REQACK;
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
#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) {
        sx->outstanding = len - 10; /* get the rest */
        sx->outp = &socksreq[10];
        sxstate(conn, CONNECT_REQ_READ_MORE);
      }
      else {
        sxstate(conn, CONNECT_DONE);
        break;
      }
#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI)
    }
#endif
    /* FALLTHROUGH */
  case CONNECT_REQ_READ_MORE:







|


|







988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
#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) {
        sx->outstanding = len - 10; /* get the rest */
        sx->outp = &socksreq[10];
        sxstate(data, CONNECT_REQ_READ_MORE);
      }
      else {
        sxstate(data, CONNECT_DONE);
        break;
      }
#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI)
    }
#endif
    /* FALLTHROUGH */
  case CONNECT_REQ_READ_MORE:
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
    }
    else if(actualread != sx->outstanding) {
      /* remain in state */
      sx->outstanding -= actualread;
      sx->outp += actualread;
      return CURLPX_OK;
    }
    sxstate(conn, CONNECT_DONE);
  }
  infof(data, "SOCKS5 request granted.\n");

  *done = TRUE;
  return CURLPX_OK; /* Proxy was successful! */
}

#endif /* CURL_DISABLE_PROXY */







|








1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
    }
    else if(actualread != sx->outstanding) {
      /* remain in state */
      sx->outstanding -= actualread;
      sx->outp += actualread;
      return CURLPX_OK;
    }
    sxstate(data, CONNECT_DONE);
  }
  infof(data, "SOCKS5 request granted.\n");

  *done = TRUE;
  return CURLPX_OK; /* Proxy was successful! */
}

#endif /* CURL_DISABLE_PROXY */
Changes to jni/curl/lib/socks.h.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#ifndef HEADER_CURL_SOCKS_H
#define HEADER_CURL_SOCKS_H
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2020, 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 https://curl.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









|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#ifndef HEADER_CURL_SOCKS_H
#define HEADER_CURL_SOCKS_H
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2021, 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 https://curl.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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
#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 behavior
 */
int Curl_blockread_all(struct connectdata *conn,
                       curl_socket_t sockfd,
                       char *buf,
                       ssize_t buffersize,
                       ssize_t *n);

int Curl_SOCKS_getsock(struct connectdata *conn,
                       curl_socket_t *sock,
                       int sockindex);
/*
 * This function logs in to a SOCKS4(a) proxy and sends the specifics to the
 * final destination server.
 */
CURLproxycode Curl_SOCKS4(const char *proxy_name,
                          const char *hostname,
                          int remote_port,
                          int sockindex,
                          struct connectdata *conn,
                          bool *done);

/*
 * This function logs in to a SOCKS5 proxy and sends the specifics to the
 * final destination server.
 */
CURLproxycode Curl_SOCKS5(const char *proxy_name,
                          const char *proxy_password,
                          const char *hostname,
                          int remote_port,
                          int sockindex,
                          struct connectdata *conn,
                          bool *done);

#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI)
/*
 * This function handles the SOCKS5 GSS-API negotiation and initialisation
 */
CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex,
                                      struct connectdata *conn);
#endif

#endif /* CURL_DISABLE_PROXY */

#endif  /* HEADER_CURL_SOCKS_H */







|
















|











|







|





31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
#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 behavior
 */
int Curl_blockread_all(struct Curl_easy *data,
                       curl_socket_t sockfd,
                       char *buf,
                       ssize_t buffersize,
                       ssize_t *n);

int Curl_SOCKS_getsock(struct connectdata *conn,
                       curl_socket_t *sock,
                       int sockindex);
/*
 * This function logs in to a SOCKS4(a) proxy and sends the specifics to the
 * final destination server.
 */
CURLproxycode Curl_SOCKS4(const char *proxy_name,
                          const char *hostname,
                          int remote_port,
                          int sockindex,
                          struct Curl_easy *data,
                          bool *done);

/*
 * This function logs in to a SOCKS5 proxy and sends the specifics to the
 * final destination server.
 */
CURLproxycode Curl_SOCKS5(const char *proxy_name,
                          const char *proxy_password,
                          const char *hostname,
                          int remote_port,
                          int sockindex,
                          struct Curl_easy *data,
                          bool *done);

#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI)
/*
 * This function handles the SOCKS5 GSS-API negotiation and initialisation
 */
CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex,
                                      struct Curl_easy *data);
#endif

#endif /* CURL_DISABLE_PROXY */

#endif  /* HEADER_CURL_SOCKS_H */
Changes to jni/curl/lib/socks_gssapi.c.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 2012 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
 * Copyright (C) 2009, 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 https://curl.se/docs/copyright.html.
 *
 * You may opt to use, copy, modify, merge, publish, distribute and/or sell







|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 2012 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
 * Copyright (C) 2009, 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 https://curl.se/docs/copyright.html.
 *
 * You may opt to use, copy, modify, merge, publish, distribute and/or sell
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
        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;
}

CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex,
                                      struct connectdata *conn)
{
  struct Curl_easy *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;







|







|

|







88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
        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: %s", function, buf);
    return 1;
  }

  return 0;
}

CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex,
                                      struct Curl_easy *data)
{
  struct connectdata *conn = data->conn;
  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;
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221

    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);







|









|







197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221

    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(data, 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(data, 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);
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
     * +----+------+-----+----------------+
     * |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;
    }








|







236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
     * +----+------+-----+----------------+
     * |VER | MTYP | LEN |     TOKEN      |
     * +----+------+----------------------+
     * | 1  |  1   |  2  | up to 2^16 - 1 |
     * +----+------+-----+----------------+
     */

    result = Curl_blockread_all(data, 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;
    }

275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
            "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);







|







275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
            "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(data, 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);
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
    }
    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 */







|









|







|










|







404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
    }
    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(data, 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(data, 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(data, 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(data, 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 */
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478

  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;







|







464
465
466
467
468
469
470
471
472
473
474
475
476
477
478

  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(data, 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;
Changes to jni/curl/lib/socks_sspi.c.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 2012 - 2020, 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 https://curl.se/docs/copyright.html.
 *
 * You may opt to use, copy, modify, merge, publish, distribute and/or sell







|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 2012 - 2021, 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 https://curl.se/docs/copyright.html.
 *
 * You may opt to use, copy, modify, merge, publish, distribute and/or sell
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
#include "curl_printf.h"
#include "curl_memory.h"
#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) {
    char buffer[STRERROR_LEN];
    failf(conn->data, "SSPI error: %s failed: %s", function,
          Curl_sspi_strerror(status, buffer, sizeof(buffer)));
    return 1;
  }
  return 0;
}

/* This is the SSPI-using version of this function */
CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex,
                                      struct connectdata *conn)
{
  struct Curl_easy *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;







|








|








|

|







39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
#include "curl_printf.h"
#include "curl_memory.h"
#include "memdebug.h"

/*
 * Helper sspi error functions.
 */
static int check_sspi_err(struct Curl_easy *data,
                          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) {
    char buffer[STRERROR_LEN];
    failf(data, "SSPI error: %s failed: %s", function,
          Curl_sspi_strerror(status, buffer, sizeof(buffer)));
    return 1;
  }
  return 0;
}

/* This is the SSPI-using version of this function */
CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex,
                                      struct Curl_easy *data)
{
  struct connectdata *conn = data->conn;
  curl_socket_t sock = conn->sock[sockindex];
  CURLcode code;
  ssize_t actualread;
  ssize_t written;
  int result;
  /* Needs GSS-API authentication */
  SECURITY_STATUS status;
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
  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 */
  const char *service = data->set.str[STRING_PROXY_SERVICE_NAME] ?
                        data->set.str[STRING_PROXY_SERVICE_NAME]  : "rcmd";
  const size_t service_length = strlen(service);

  /*   GSS-API request looks like
   * +----+------+-----+----------------+
   * |VER | MTYP | LEN |     TOKEN      |
   * +----+------+----------------------+
   * | 1  |  1   |  2  | up to 2^16 - 1 |







|







82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
  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 */
  const char *service = data->set.str[STRING_PROXY_SERVICE_NAME] ?
    data->set.str[STRING_PROXY_SERVICE_NAME]  : "rcmd";
  const size_t service_length = strlen(service);

  /*   GSS-API request looks like
   * +----+------+-----+----------------+
   * |VER | MTYP | LEN |     TOKEN      |
   * +----+------+----------------------+
   * | 1  |  1   |  2  | up to 2^16 - 1 |
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
                                              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;
  }

  (void)curlx_nonblock(sock, FALSE);







|







142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
                                              NULL,
                                              NULL,
                                              NULL,
                                              NULL,
                                              &cred_handle,
                                              &expiry);

  if(check_sspi_err(data, status, "AcquireCredentialsHandle")) {
    failf(data, "Failed to acquire credentials.");
    free(service_name);
    s_pSecFn->FreeCredentialsHandle(&cred_handle);
    return CURLE_COULDNT_CONNECT;
  }

  (void)curlx_nonblock(sock, FALSE);
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227

    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)







|















|












|







184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227

    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(data, 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(data, 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(data, 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)
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
     * +----+------+-----+----------------+
     * |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;
    }







|







254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
     * +----+------+-----+----------------+
     * |VER | MTYP | LEN |     TOKEN      |
     * +----+------+----------------------+
     * | 1  |  1   |  2  | up to 2^16 - 1 |
     * +----+------+-----+----------------+
     */

    result = Curl_blockread_all(data, 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;
    }
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308

    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);







|







294
295
296
297
298
299
300
301
302
303
304
305
306
307
308

    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(data, 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);
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
  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 authenticated user %s with GSS-API.\n",
        names.sUserName);







|







317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
  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(data, 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 authenticated user %s with GSS-API.\n",
        names.sUserName);
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
    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;







|







382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
    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(data, 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;
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
      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;
    }







|







419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
      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(data, 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;
    }
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
    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 */







|










|







|












|







462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
    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(data, 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(data, 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(data, 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(data, 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 */
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
  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;







|







526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
  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(data, 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;
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
    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;







|







549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
    sspi_w_token[1].pvBuffer = NULL;

    status = s_pSecFn->DecryptMessage(&sspi_context,
                                      &wrap_desc,
                                      0,
                                      &qop);

    if(check_sspi_err(data, 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;
Changes to jni/curl/lib/speedcheck.c.
35
36
37
38
39
40
41




42
43
44
45
46
47
48

/*
 * @unittest: 1606
 */
CURLcode Curl_speedcheck(struct Curl_easy *data,
                         struct curltime now)
{




  if((data->progress.current_speed >= 0) && data->set.low_speed_time) {
    if(data->progress.current_speed < data->set.low_speed_limit) {
      if(!data->state.keeps_speed.tv_sec)
        /* under the limit at this very moment */
        data->state.keeps_speed = now;
      else {
        /* how long has it been under the limit */







>
>
>
>







35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52

/*
 * @unittest: 1606
 */
CURLcode Curl_speedcheck(struct Curl_easy *data,
                         struct curltime now)
{
  if(data->req.keepon & KEEP_RECV_PAUSE)
    /* A paused transfer is not qualified for speed checks */
    return CURLE_OK;

  if((data->progress.current_speed >= 0) && data->set.low_speed_time) {
    if(data->progress.current_speed < data->set.low_speed_limit) {
      if(!data->state.keeps_speed.tv_sec)
        /* under the limit at this very moment */
        data->state.keeps_speed = now;
      else {
        /* how long has it been under the limit */
Changes to jni/curl/lib/strerror.c.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 2004 - 2020, 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 https://curl.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







|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 2004 - 2021, 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 https://curl.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
717
718
719
720
721
722
723

724

725
726
727
728
729
730
731
  int old_errno = errno;
  char *p;
  size_t max;

  if(!buflen)
    return NULL;


  DEBUGASSERT(err >= 0);


  max = buflen - 1;
  *buf = '\0';

#if defined(WIN32) || defined(_WIN32_WCE)
#if defined(WIN32)
  /* 'sys_nerr' is the maximum errno number, it is not widely portable */







>

>







717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
  int old_errno = errno;
  char *p;
  size_t max;

  if(!buflen)
    return NULL;

#ifndef WIN32
  DEBUGASSERT(err >= 0);
#endif

  max = buflen - 1;
  *buf = '\0';

#if defined(WIN32) || defined(_WIN32_WCE)
#if defined(WIN32)
  /* 'sys_nerr' is the maximum errno number, it is not widely portable */
Changes to jni/curl/lib/system_win32.c.
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
     supported by command prompt */
  if(_tcspbrk(filename, TEXT("\\/"))) {
    /** !checksrc! disable BANNEDFUNC 1 **/
    hModule = pLoadLibraryEx ?
      pLoadLibraryEx(filename, NULL, LOAD_WITH_ALTERED_SEARCH_PATH) :
      LoadLibrary(filename);
  }
  /* Detect if KB2533623 is installed, as LOAD_LIBARY_SEARCH_SYSTEM32 is only
     supported on Windows Vista, Windows Server 2008, Windows 7 and Windows
     Server 2008 R2 with this patch or natively on Windows 8 and above */
  else if(pLoadLibraryEx && GetProcAddress(hKernel32, "AddDllDirectory")) {
    /* Load the DLL from the Windows system directory */
    hModule = pLoadLibraryEx(filename, NULL, LOAD_LIBRARY_SEARCH_SYSTEM32);
  }
  else {







|







192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
     supported by command prompt */
  if(_tcspbrk(filename, TEXT("\\/"))) {
    /** !checksrc! disable BANNEDFUNC 1 **/
    hModule = pLoadLibraryEx ?
      pLoadLibraryEx(filename, NULL, LOAD_WITH_ALTERED_SEARCH_PATH) :
      LoadLibrary(filename);
  }
  /* Detect if KB2533623 is installed, as LOAD_LIBRARY_SEARCH_SYSTEM32 is only
     supported on Windows Vista, Windows Server 2008, Windows 7 and Windows
     Server 2008 R2 with this patch or natively on Windows 8 and above */
  else if(pLoadLibraryEx && GetProcAddress(hKernel32, "AddDllDirectory")) {
    /* Load the DLL from the Windows system directory */
    hModule = pLoadLibraryEx(filename, NULL, LOAD_LIBRARY_SEARCH_SYSTEM32);
  }
  else {
Changes to jni/curl/lib/telnet.c.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2020, 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 https://curl.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







|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2021, 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 https://curl.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
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
#define  CURL_SB_EOF(x) (x->subpointer >= x->subend) */

#ifdef CURL_DISABLE_VERBOSE_STRINGS
#define printoption(a,b,c,d)  Curl_nop_stmt
#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 Curl_easy *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 *conn,
                             int option, int newstate);
static void set_remote_option(struct connectdata *conn,
                              int option, int newstate);

static void printsub(struct Curl_easy *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







|









|
|
|

|





|
|

|
|

|







84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
#define  CURL_SB_EOF(x) (x->subpointer >= x->subend) */

#ifdef CURL_DISABLE_VERBOSE_STRINGS
#define printoption(a,b,c,d)  Curl_nop_stmt
#endif

static
CURLcode telrcv(struct Curl_easy *data,
                const unsigned char *inbuf, /* Data received from socket */
                ssize_t count);             /* Number of bytes received */

#ifndef CURL_DISABLE_VERBOSE_STRINGS
static void printoption(struct Curl_easy *data,
                        const char *direction,
                        int cmd, int option);
#endif

static void negotiate(struct Curl_easy *data);
static void send_negotiation(struct Curl_easy *data, int cmd, int option);
static void set_local_option(struct Curl_easy *data,
                             int option, int newstate);
static void set_remote_option(struct Curl_easy *data,
                              int option, int newstate);

static void printsub(struct Curl_easy *data,
                     int direction, unsigned char *pointer,
                     size_t length);
static void suboption(struct Curl_easy *data);
static void sendsuboption(struct Curl_easy *data, int option);

static CURLcode telnet_do(struct Curl_easy *data, bool *done);
static CURLcode telnet_done(struct Curl_easy *data,
                                 CURLcode, bool premature);
static CURLcode send_telnet_data(struct Curl_easy *data,
                                 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
152
153
154
155
156
157
158

159
160
161
162
163
164
165
166
167
168
169
170
171
172
  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.
 */








>





<
<







152
153
154
155
156
157
158
159
160
161
162
163
164


165
166
167
168
169
170
171
  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 */
  TelnetReceive telrcv_state;
  struct curl_slist *telnet_vars;    /* Environment variables */

  /* suboptions */
  unsigned char subbuffer[SUBBUFSIZE];
  unsigned char *subpointer, *subend;      /* buffer for sub-options */


};


/*
 * TELNET protocol handler.
 */

190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
  CURLPROTO_TELNET,                     /* protocol */
  CURLPROTO_TELNET,                     /* family */
  PROTOPT_NONE | PROTOPT_NOURLQUERY     /* flags */
};


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.p.telnet = 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







|







|











|







189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
  CURLPROTO_TELNET,                     /* protocol */
  CURLPROTO_TELNET,                     /* family */
  PROTOPT_NONE | PROTOPT_NOURLQUERY     /* flags */
};


static
CURLcode init_telnet(struct Curl_easy *data)
{
  struct TELNET *tn;

  tn = calloc(1, sizeof(struct TELNET));
  if(!tn)
    return CURLE_OUT_OF_MEMORY;

  data->req.p.telnet = 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 behavior
         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
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
         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.p.telnet;

  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 Curl_easy *data,
                        const char *direction, int cmd, int option)
{







|


|






|


|







239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
         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 Curl_easy *data)
{
  int i;
  struct TELNET *tn = data->req.p.telnet;

  for(i = 0; i < CURL_NTELOPTS; i++) {
    if(i == CURL_TELOPT_ECHO)
      continue;

    if(tn->us_preferred[i] == CURL_YES)
      set_local_option(data, i, CURL_YES);

    if(tn->him_preferred[i] == CURL_YES)
      set_remote_option(data, i, CURL_YES);
  }
}

#ifndef CURL_DISABLE_VERBOSE_STRINGS
static void printoption(struct Curl_easy *data,
                        const char *direction, int cmd, int option)
{
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
      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;
   struct Curl_easy *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) {
     int 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.p.telnet;
  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:







|

|
|
|

|
|
|

|
|
|
|
|

|



|

|




|







293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
      else
        infof(data, "%s %d %d\n", direction, cmd, option);
    }
  }
}
#endif

static void send_negotiation(struct Curl_easy *data, int cmd, int option)
{
  unsigned char buf[3];
  ssize_t bytes_written;
  struct connectdata *conn = data->conn;

  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) {
    int err = SOCKERRNO;
    failf(data,"Sending data failed (%d)",err);
  }

  printoption(data, "SENT", cmd, option);
}

static
void set_remote_option(struct Curl_easy *data, int option, int newstate)
{
  struct TELNET *tn = data->req.p.telnet;
  if(newstate == CURL_YES) {
    switch(tn->him[option]) {
    case CURL_NO:
      tn->him[option] = CURL_WANTYES;
      send_negotiation(data, CURL_DO, option);
      break;

    case CURL_YES:
      /* Already enabled */
      break;

    case CURL_WANTNO:
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
    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;







|







359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
    switch(tn->him[option]) {
    case CURL_NO:
      /* Already disabled */
      break;

    case CURL_YES:
      tn->him[option] = CURL_WANTNO;
      send_negotiation(data, CURL_DONT, option);
      break;

    case CURL_WANTNO:
      switch(tn->himq[option]) {
      case CURL_EMPTY:
        /* Already negotiating for NO */
        break;
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
      }
      break;
    }
  }
}

static
void rec_will(struct connectdata *conn, int option)
{
  struct TELNET *tn = (struct TELNET *)conn->data->req.p.telnet;
  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;








|

|




|


|







387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
      }
      break;
    }
  }
}

static
void rec_will(struct Curl_easy *data, int option)
{
  struct TELNET *tn = data->req.p.telnet;
  switch(tn->him[option]) {
  case CURL_NO:
    if(tn->him_preferred[option] == CURL_YES) {
      tn->him[option] = CURL_YES;
      send_negotiation(data, CURL_DO, option);
    }
    else
      send_negotiation(data, CURL_DONT, option);

    break;

  case CURL_YES:
    /* Already enabled */
    break;

428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
    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.p.telnet;
  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.p.telnet;
  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:







|







|

|







|











|



















|

|




|







427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
    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(data, CURL_DONT, option);
      break;
    }
    break;
  }
}

static
void rec_wont(struct Curl_easy *data, int option)
{
  struct TELNET *tn = data->req.p.telnet;
  switch(tn->him[option]) {
  case CURL_NO:
    /* Already disabled */
    break;

  case CURL_YES:
    tn->him[option] = CURL_NO;
    send_negotiation(data, 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(data, 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 Curl_easy *data, int option, int newstate)
{
  struct TELNET *tn = data->req.p.telnet;
  if(newstate == CURL_YES) {
    switch(tn->us[option]) {
    case CURL_NO:
      tn->us[option] = CURL_WANTYES;
      send_negotiation(data, CURL_WILL, option);
      break;

    case CURL_YES:
      /* Already enabled */
      break;

    case CURL_WANTNO:
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
    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;







|







523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
    switch(tn->us[option]) {
    case CURL_NO:
      /* Already disabled */
      break;

    case CURL_YES:
      tn->us[option] = CURL_WANTNO;
      send_negotiation(data, CURL_WONT, option);
      break;

    case CURL_WANTNO:
      switch(tn->usq[option]) {
      case CURL_EMPTY:
        /* Already negotiating for NO */
        break;
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
      }
      break;
    }
  }
}

static
void rec_do(struct connectdata *conn, int option)
{
  struct TELNET *tn = (struct TELNET *)conn->data->req.p.telnet;
  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:







|

|




|


|




|
|


|







551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
      }
      break;
    }
  }
}

static
void rec_do(struct Curl_easy *data, int option)
{
  struct TELNET *tn = data->req.p.telnet;
  switch(tn->us[option]) {
  case CURL_NO:
    if(tn->us_preferred[option] == CURL_YES) {
      tn->us[option] = CURL_YES;
      send_negotiation(data, CURL_WILL, option);
      if(tn->subnegotiation[option] == CURL_YES)
        /* transmission of data option */
        sendsuboption(data, option);
    }
    else if(tn->subnegotiation[option] == CURL_YES) {
      /* send information to achieve this option*/
      tn->us[option] = CURL_YES;
      send_negotiation(data, CURL_WILL, option);
      sendsuboption(data, option);
    }
    else
      send_negotiation(data, CURL_WONT, option);
    break;

  case CURL_YES:
    /* Already enabled */
    break;

  case CURL_WANTNO:
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648

  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.p.telnet;
  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:







|





|







|

|







|











|







597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647

  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(data, option);
      }
      break;
    case CURL_OPPOSITE:
      tn->us[option] = CURL_WANTNO;
      tn->himq[option] = CURL_EMPTY;
      send_negotiation(data, CURL_WONT, option);
      break;
    }
    break;
  }
}

static
void rec_dont(struct Curl_easy *data, int option)
{
  struct TELNET *tn = data->req.p.telnet;
  switch(tn->us[option]) {
  case CURL_NO:
    /* Already disabled */
    break;

  case CURL_YES:
    tn->us[option] = CURL_NO;
    send_negotiation(data, 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(data, CURL_WILL, option);
      break;
    }
    break;

  case CURL_WANTYES:
    switch(tn->usq[option]) {
    case CURL_EMPTY:
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780

781
782
783
784
785
786
787
      }
    }
    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 Curl_easy *data = conn->data;
  struct TELNET *tn = (struct TELNET *)conn->data->req.p.telnet;

  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) {
    msnprintf(option_arg, sizeof(option_arg), "USER,%s", conn->user);







|





<
|
>







765
766
767
768
769
770
771
772
773
774
775
776
777

778
779
780
781
782
783
784
785
786
      }
    }
    if(direction)
      infof(data, "\n");
  }
}

static CURLcode check_telnet_options(struct Curl_easy *data)
{
  struct curl_slist *head;
  struct curl_slist *beg;
  char option_keyword[128] = "";
  char option_arg[256] = "";

  struct TELNET *tn = data->req.p.telnet;
  struct connectdata *conn = data->conn;
  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) {
    msnprintf(option_arg, sizeof(option_arg), "USER,%s", conn->user);
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887

888
889
890
891
892
893
894
/*
 * 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;
  int err;
  char varname[128] = "";
  char varval[128] = "";
  struct Curl_easy *data = conn->data;
  struct TELNET *tn = (struct TELNET *)data->req.p.telnet;


  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;
      msnprintf((char *)temp, sizeof(temp),
                "%c%c%c%c%s%c%c", CURL_IAC, CURL_SB, CURL_TELOPT_TTYPE,







|








<
|
>







869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884

885
886
887
888
889
890
891
892
893
/*
 * suboption()
 *
 * Look at the sub-option buffer, and try to be helpful to the other
 * side.
 */

static void suboption(struct Curl_easy *data)
{
  struct curl_slist *v;
  unsigned char temp[2048];
  ssize_t bytes_written;
  size_t len;
  int err;
  char varname[128] = "";
  char varval[128] = "";

  struct TELNET *tn = data->req.p.telnet;
  struct connectdata *conn = data->conn;

  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;
      msnprintf((char *)temp, sizeof(temp),
                "%c%c%c%c%s%c%c", CURL_IAC, CURL_SB, CURL_TELOPT_TTYPE,
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962

963
964
965
966
967
968
969

/*
 * 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 Curl_easy *data = conn->data;
  struct TELNET *tn = (struct TELNET *)data->req.p.telnet;


  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);







|





<
<
|
>







946
947
948
949
950
951
952
953
954
955
956
957
958


959
960
961
962
963
964
965
966
967

/*
 * sendsuboption()
 *
 * Send suboption information to the server side.
 */

static void sendsuboption(struct Curl_easy *data, int option)
{
  ssize_t bytes_written;
  int err;
  unsigned short x, y;
  unsigned char *uc1, *uc2;


  struct TELNET *tn = data->req.p.telnet;
  struct connectdata *conn = data->conn;

  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);
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
    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 Curl_easy *data = conn->data;
  struct TELNET *tn = (struct TELNET *)data->req.p.telnet;

#define startskipping()                                       \
  if(startwrite >= 0) {                                       \
    result = Curl_client_write(conn,                          \
                               CLIENTWRITE_BODY,              \
                               (char *)&inbuf[startwrite],    \
                               in-startwrite);                \
    if(result)                                                \
      return result;                                          \
  }                                                           \
  startwrite = -1







|












|







<
|



|







989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016

1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
    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(data, (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 Curl_easy *data,
                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 TELNET *tn = data->req.p.telnet;

#define startskipping()                                       \
  if(startwrite >= 0) {                                       \
    result = Curl_client_write(data,                          \
                               CLIENTWRITE_BODY,              \
                               (char *)&inbuf[startwrite],    \
                               in-startwrite);                \
    if(result)                                                \
      return result;                                          \
  }                                                           \
  startwrite = -1
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
        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







|






|






|






|







1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
        break;
      }
      break;

      case CURL_TS_WILL:
        printoption(data, "RCVD", CURL_WILL, c);
        tn->please_negotiate = 1;
        rec_will(data, c);
        tn->telrcv_state = CURL_TS_DATA;
        break;

      case CURL_TS_WONT:
        printoption(data, "RCVD", CURL_WONT, c);
        tn->please_negotiate = 1;
        rec_wont(data, c);
        tn->telrcv_state = CURL_TS_DATA;
        break;

      case CURL_TS_DO:
        printoption(data, "RCVD", CURL_DO, c);
        tn->please_negotiate = 1;
        rec_do(data, c);
        tn->telrcv_state = CURL_TS_DATA;
        break;

      case CURL_TS_DONT:
        printoption(data, "RCVD", CURL_DONT, c);
        tn->please_negotiate = 1;
        rec_dont(data, c);
        tn->telrcv_state = CURL_TS_DATA;
        break;

      case CURL_TS_SB:
        if(c == CURL_IAC)
          tn->telrcv_state = CURL_TS_SE;
        else
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180

1181
1182
1183
1184
1185
1186
1187
             */
            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 */
static CURLcode send_telnet_data(struct connectdata *conn,
                                 char *buffer, ssize_t nread)
{
  ssize_t escapes, i, outlen;
  unsigned char *outbuf = NULL;
  CURLcode result = CURLE_OK;
  ssize_t bytes_written, total_written;


  /* Determine size of new buffer after escaping */
  escapes = 0;
  for(i = 0; i < nread; i++)
    if((unsigned char)buffer[i] == CURL_IAC)
      escapes++;
  outlen = nread + escapes;







|











|











|






>







1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
             */
            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(data);   /* 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(data);   /* handle sub-option */
          tn->telrcv_state = CURL_TS_DATA;
        }
        break;
    }
    ++in;
  }
  bufferflush();
  return CURLE_OK;
}

/* Escape and send a telnet data block */
static CURLcode send_telnet_data(struct Curl_easy *data,
                                 char *buffer, ssize_t nread)
{
  ssize_t escapes, i, outlen;
  unsigned char *outbuf = NULL;
  CURLcode result = CURLE_OK;
  ssize_t bytes_written, total_written;
  struct connectdata *conn = data->conn;

  /* Determine size of new buffer after escaping */
  escapes = 0;
  for(i = 0; i < nread; i++)
    if((unsigned char)buffer[i] == CURL_IAC)
      escapes++;
  outlen = nread + escapes;
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
    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,
                            outlen - total_written,
                            &bytes_written);
        total_written += bytes_written;
        break;
    }
  }

  /* Free malloc copy if escaped */
  if(outbuf != (unsigned char *)buffer)
    free(outbuf);

  return result;
}

static CURLcode telnet_done(struct connectdata *conn,
                                 CURLcode status, bool premature)
{
  struct TELNET *tn = (struct TELNET *)conn->data->req.p.telnet;
  (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.p.telnet);

  return CURLE_OK;
}

static CURLcode telnet_do(struct connectdata *conn, bool *done)
{
  CURLcode result;
  struct Curl_easy *data = conn->data;
  curl_socket_t sockfd = conn->sock[FIRSTSOCKET];
#ifdef USE_WINSOCK
  WSAEVENT event_handle;
  WSANETWORKEVENTS events;
  HANDLE stdin_handle;
  HANDLE objs[2];
  DWORD  obj_count;







|















|
|

|









|




|


|







1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
    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(data, conn->sock[FIRSTSOCKET],
                            outbuf + total_written,
                            outlen - total_written,
                            &bytes_written);
        total_written += bytes_written;
        break;
    }
  }

  /* Free malloc copy if escaped */
  if(outbuf != (unsigned char *)buffer)
    free(outbuf);

  return result;
}

static CURLcode telnet_done(struct Curl_easy *data,
                            CURLcode status, bool premature)
{
  struct TELNET *tn = data->req.p.telnet;
  (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(data->req.p.telnet);

  return CURLE_OK;
}

static CURLcode telnet_do(struct Curl_easy *data, bool *done)
{
  CURLcode result;
  struct connectdata *conn = data->conn;
  curl_socket_t sockfd = conn->sock[FIRSTSOCKET];
#ifdef USE_WINSOCK
  WSAEVENT event_handle;
  WSANETWORKEVENTS events;
  HANDLE stdin_handle;
  HANDLE objs[2];
  DWORD  obj_count;
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
  struct curltime now;
  bool keepon = TRUE;
  char *buf = data->state.buffer;
  struct TELNET *tn;

  *done = TRUE; /* unconditionally */

  result = init_telnet(conn);
  if(result)
    return result;

  tn = data->req.p.telnet;

  result = check_telnet_options(conn);
  if(result)
    return result;

#ifdef USE_WINSOCK
  /* 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.







|





|







1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
  struct curltime now;
  bool keepon = TRUE;
  char *buf = data->state.buffer;
  struct TELNET *tn;

  *done = TRUE; /* unconditionally */

  result = init_telnet(data);
  if(result)
    return result;

  tn = data->req.p.telnet;

  result = check_telnet_options(data);
  if(result)
    return result;

#ifdef USE_WINSOCK
  /* 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.
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
                       &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, buf_size,
                   &readfile_read, NULL)) {
        keepon = FALSE;
        result = CURLE_READ_ERROR;
        break;
      }

      result = send_telnet_data(conn, buf, readfile_read);
      if(result) {
        keepon = FALSE;
        break;
      }
    }
    break;








|

















|







1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
                       &readfile_read, NULL)) {
            keepon = FALSE;
            result = CURLE_READ_ERROR;
            break;
          }
        }

        result = send_telnet_data(data, buf, readfile_read);
        if(result) {
          keepon = FALSE;
          break;
        }
      }
    }
    break;

    case WAIT_OBJECT_0 + 1:
    {
      if(!ReadFile(stdin_handle, buf, buf_size,
                   &readfile_read, NULL)) {
        keepon = FALSE;
        result = CURLE_READ_ERROR;
        break;
      }

      result = send_telnet_data(data, buf, readfile_read);
      if(result) {
        keepon = FALSE;
        break;
      }
    }
    break;

1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
          keepon = FALSE;
          result = CURLE_READ_ERROR;
        }
        break;
      }
      if(events.lNetworkEvents & FD_READ) {
        /* read data from network */
        result = Curl_read(conn, sockfd, buf, data->set.buffer_size, &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;
      }
    }







|















|









|







1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
          keepon = FALSE;
          result = CURLE_READ_ERROR;
        }
        break;
      }
      if(events.lNetworkEvents & FD_READ) {
        /* read data from network */
        result = Curl_read(data, sockfd, buf, data->set.buffer_size, &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(data, (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(data);
          tn->already_negotiated = 1;
        }
      }
      if(events.lNetworkEvents & FD_CLOSE) {
        keepon = FALSE;
      }
    }
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
    case 0:                     /* timeout */
      pfd[0].revents = 0;
      pfd[1].revents = 0;
      /* FALLTHROUGH */
    default:                    /* read! */
      if(pfd[0].revents & POLLIN) {
        /* read data from network */
        result = Curl_read(conn, sockfd, buf, data->set.buffer_size, &nread);
        /* read would've blocked. Loop again */
        if(result == CURLE_AGAIN)
          break;
        /* returned not-zero, this an error */
        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 */







|

















|









|







1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
    case 0:                     /* timeout */
      pfd[0].revents = 0;
      pfd[1].revents = 0;
      /* FALLTHROUGH */
    default:                    /* read! */
      if(pfd[0].revents & POLLIN) {
        /* read data from network */
        result = Curl_read(data, sockfd, buf, data->set.buffer_size, &nread);
        /* read would've blocked. Loop again */
        if(result == CURLE_AGAIN)
          break;
        /* returned not-zero, this an error */
        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(data, (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(data);
          tn->already_negotiated = 1;
        }
      }

      nread = 0;
      if(poll_cnt == 2) {
        if(pfd[1].revents & POLLIN) { /* read from in file */
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
          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);
      }







|







1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
          break;
        }
        if(nread == CURL_READFUNC_PAUSE)
          break;
      }

      if(nread > 0) {
        result = send_telnet_data(data, buf, nread);
        if(result) {
          keepon = FALSE;
          break;
        }
        total_ul += nread;
        Curl_pgrsSetUploadCounter(data, total_ul);
      }
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
      if(Curl_timediff(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(data, -1, -1, FALSE, -1);

  return result;
}
#endif







|











1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
      if(Curl_timediff(now, conn->created) >= data->set.timeout) {
        failf(data, "Time-out");
        result = CURLE_OPERATION_TIMEDOUT;
        keepon = FALSE;
      }
    }

    if(Curl_pgrsUpdate(data)) {
      result = CURLE_ABORTED_BY_CALLBACK;
      break;
    }
  }
#endif
  /* mark this as "no further transfer wanted" */
  Curl_setup_transfer(data, -1, -1, FALSE, -1);

  return result;
}
#endif
Changes to jni/curl/lib/tftp.c.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2020, 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 https://curl.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







|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2021, 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 https://curl.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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142

143
144
145
146
147
148
149
150
151
152

153
154
155
156
157

158
159

160
161
162
163
164
165
166
167
};

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;

  struct tftp_packet rpacket;
  struct tftp_packet spacket;
};


/* Forward declarations */
static CURLcode tftp_rx(struct tftp_state_data *state, tftp_event_t event);
static CURLcode tftp_tx(struct tftp_state_data *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);
static CURLcode tftp_translate_code(tftp_error_t error);


/*
 * TFTP protocol handler.
 */








|







<







>








|
|
>

|
|

|
>
|
|
>
|







120
121
122
123
124
125
126
127
128
129
130
131
132
133
134

135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
};

struct tftp_state_data {
  tftp_state_t    state;
  tftp_mode_t     mode;
  tftp_error_t    error;
  tftp_event_t    event;
  struct Curl_easy *data;
  curl_socket_t   sockfd;
  int             retries;
  int             retry_time;
  int             retry_max;
  time_t          start_time;
  time_t          max_time;
  time_t          rx_time;

  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;
  unsigned short  block;
  struct tftp_packet rpacket;
  struct tftp_packet spacket;
};


/* Forward declarations */
static CURLcode tftp_rx(struct tftp_state_data *state, tftp_event_t event);
static CURLcode tftp_tx(struct tftp_state_data *state, tftp_event_t event);
static CURLcode tftp_connect(struct Curl_easy *data, bool *done);
static CURLcode tftp_disconnect(struct Curl_easy *data,
                                struct connectdata *conn,
                                bool dead_connection);
static CURLcode tftp_do(struct Curl_easy *data, bool *done);
static CURLcode tftp_done(struct Curl_easy *data,
                          CURLcode, bool premature);
static CURLcode tftp_setup_connection(struct Curl_easy *data,
                                      struct connectdata *conn);
static CURLcode tftp_multi_statemach(struct Curl_easy *data, bool *done);
static CURLcode tftp_doing(struct Curl_easy *data, bool *dophase_done);
static int tftp_getsock(struct Curl_easy *data, struct connectdata *conn,
                        curl_socket_t *socks);
static CURLcode tftp_translate_code(tftp_error_t error);


/*
 * TFTP protocol handler.
 */

202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
  time_t maxtime, timeout;
  timediff_t 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;







|



|







205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
  time_t maxtime, timeout;
  timediff_t timeout_ms;
  bool start = (state->state == TFTP_STATE_START) ? TRUE : FALSE;

  time(&state->start_time);

  /* Compute drop-dead time */
  timeout_ms = Curl_timeleft(state->data, NULL, start);

  if(timeout_ms < 0) {
    /* time-out, bail out, go home */
    failf(state->data, "Connection time-out");
    return CURLE_OPERATION_TIMEDOUT;
  }

  if(start) {

    maxtime = (time_t)(timeout_ms + 500) / 1000;
    state->max_time = state->start_time + maxtime;
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
    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);








|







260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
    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->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);

299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
}

static unsigned short getrpacketblock(const struct tftp_packet *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(struct tftp_state_data *state,
                                      const char *ptr, int len)
{
  const char *tmp = ptr;
  struct Curl_easy *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;








|










|






|













|







302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
}

static unsigned short getrpacketblock(const struct tftp_packet *packet)
{
  return (unsigned short)((packet->data[2] << 8) | packet->data[3]);
}

static size_t tftp_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 = tftp_strnlen(buf, len);
  loc++; /* NULL term */

  if(loc >= len)
    return NULL;
  *option = buf;

  loc += tftp_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(struct tftp_state_data *state,
                                      const char *ptr, int len)
{
  const char *tmp = ptr;
  struct Curl_easy *data = state->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;

415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
}

static CURLcode tftp_connect_for_tx(struct tftp_state_data *state,
                                    tftp_event_t event)
{
  CURLcode result;
#ifndef CURL_DISABLE_VERBOSE_STRINGS
  struct Curl_easy *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(struct tftp_state_data *state,
                                    tftp_event_t event)
{
  CURLcode result;
#ifndef CURL_DISABLE_VERBOSE_STRINGS
  struct Curl_easy *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(struct tftp_state_data *state,
                                tftp_event_t event)
{
  size_t sbytes;
  ssize_t senddata;
  const char *mode = "octet";
  char *filename;
  struct Curl_easy *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) {







|















|

















|







418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
}

static CURLcode tftp_connect_for_tx(struct tftp_state_data *state,
                                    tftp_event_t event)
{
  CURLcode result;
#ifndef CURL_DISABLE_VERBOSE_STRINGS
  struct Curl_easy *data = state->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(struct tftp_state_data *state,
                                    tftp_event_t event)
{
  CURLcode result;
#ifndef CURL_DISABLE_VERBOSE_STRINGS
  struct Curl_easy *data = state->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(struct tftp_state_data *state,
                                tftp_event_t event)
{
  size_t sbytes;
  ssize_t senddata;
  const char *mode = "octet";
  char *filename;
  struct Curl_easy *data = state->data;
  CURLcode result = CURLE_OK;

  /* Set ascii mode if -B flag was used */
  if(data->set.prefer_ascii)
    mode = "netascii";

  switch(event) {
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
      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. */
    result = Curl_urldecode(data, &state->conn->data->state.up.path[1], 0,
                            &filename, NULL, REJECT_ZERO);
    if(result)
      return result;

    if(strlen(filename) > (state->blksize - strlen(mode) - 4)) {
      failf(data, "TFTP file name too long\n");
      free(filename);
      return CURLE_TFTP_ILLEGAL; /* too long file name field */
    }

    msnprintf((char *)state->spacket.data + 2,
              state->blksize,
              "%s%c%s%c", filename, '\0',  mode, '\0');







|











|





|







474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
      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->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. */
    result = Curl_urldecode(data, &state->data->state.up.path[1], 0,
                            &filename, NULL, REJECT_ZERO);
    if(result)
      return result;

    if(strlen(filename) > (state->blksize - strlen(mode) - 4)) {
      failf(data, "TFTP file name too long");
      free(filename);
      return CURLE_TFTP_ILLEGAL; /* too long file name field */
    }

    msnprintf((char *)state->spacket.data + 2,
              state->blksize,
              "%s%c%s%c", filename, '\0',  mode, '\0');
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
      }
    }

    /* 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) {
      char buffer[STRERROR_LEN];
      failf(data, "%s", Curl_strerror(SOCKERRNO, buffer, sizeof(buffer)));
    }
    free(filename);
    break;








|
|







550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
      }
    }

    /* 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,
                      data->conn->ip_addr->ai_addr,
                      data->conn->ip_addr->ai_addrlen);
    if(senddata != (ssize_t)sbytes) {
      char buffer[STRERROR_LEN];
      failf(data, "%s", Curl_strerror(SOCKERRNO, buffer, sizeof(buffer)));
    }
    free(filename);
    break;

578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
    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







|







581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
    break;

  case TFTP_EVENT_ERROR:
    state->state = TFTP_STATE_FIN;
    break;

  default:
    failf(state->data, "tftp_send_first: internal error");
    break;
  }

  return result;
}

/* the next blocknum is x + 1 but it needs to wrap at an unsigned 16bit
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
 *
 **********************************************************/
static CURLcode tftp_rx(struct tftp_state_data *state,
                        tftp_event_t event)
{
  ssize_t sbytes;
  int rblock;
  struct Curl_easy *data = state->conn->data;
  char buffer[STRERROR_LEN];

  switch(event) {

  case TFTP_EVENT_DATA:
    /* Is this the block we expect? */
    rblock = getrpacketblock(&state->rpacket);







|







604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
 *
 **********************************************************/
static CURLcode tftp_rx(struct tftp_state_data *state,
                        tftp_event_t event)
{
  ssize_t sbytes;
  int rblock;
  struct Curl_easy *data = state->data;
  char buffer[STRERROR_LEN];

  switch(event) {

  case TFTP_EVENT_DATA:
    /* Is this the block we expect? */
    rblock = getrpacketblock(&state->rpacket);
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
 * tftp_tx
 *
 * Event handler for the TX state
 *
 **********************************************************/
static CURLcode tftp_tx(struct tftp_state_data *state, tftp_event_t event)
{
  struct Curl_easy *data = state->conn->data;
  ssize_t sbytes;
  CURLcode result = CURLE_OK;
  struct SingleRequest *k = &data->req;
  size_t cb; /* Bytes currently read */
  char buffer[STRERROR_LEN];

  switch(event) {







|







724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
 * tftp_tx
 *
 * Event handler for the TX state
 *
 **********************************************************/
static CURLcode tftp_tx(struct tftp_state_data *state, tftp_event_t event)
{
  struct Curl_easy *data = state->data;
  ssize_t sbytes;
  CURLcode result = CURLE_OK;
  struct SingleRequest *k = &data->req;
  size_t cb; /* Bytes currently read */
  char buffer[STRERROR_LEN];

  switch(event) {
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
    }

    /* TFTP considers data block size < 512 bytes as an end of session. So
     * in some cases we must wait for additional data to build full (512 bytes)
     * data block.
     * */
    state->sbytes = 0;
    state->conn->data->req.upload_fromhere = (char *)state->spacket.data + 4;
    do {
      result = Curl_fillreadbuffer(state->conn, state->blksize - state->sbytes,
                                   &cb);
      if(result)
        return result;
      state->sbytes += (int)cb;
      state->conn->data->req.upload_fromhere += cb;
    } while(state->sbytes < state->blksize && cb != 0);

    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 */







|

|
<



|







793
794
795
796
797
798
799
800
801
802

803
804
805
806
807
808
809
810
811
812
813
    }

    /* TFTP considers data block size < 512 bytes as an end of session. So
     * in some cases we must wait for additional data to build full (512 bytes)
     * data block.
     * */
    state->sbytes = 0;
    state->data->req.upload_fromhere = (char *)state->spacket.data + 4;
    do {
      result = Curl_fillreadbuffer(data, state->blksize - state->sbytes, &cb);

      if(result)
        return result;
      state->sbytes += (int)cb;
      state->data->req.upload_fromhere += cb;
    } while(state->sbytes < state->blksize && cb != 0);

    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 */
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
 * The tftp state machine event dispatcher
 *
 **********************************************************/
static CURLcode tftp_state_machine(struct tftp_state_data *state,
                                   tftp_event_t event)
{
  CURLcode result = CURLE_OK;
  struct Curl_easy *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:







|







925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
 * The tftp state machine event dispatcher
 *
 **********************************************************/
static CURLcode tftp_state_machine(struct tftp_state_data *state,
                                   tftp_event_t event)
{
  CURLcode result = CURLE_OK;
  struct Curl_easy *data = state->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:
958
959
960
961
962
963
964
965

966
967

968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991

992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
/**********************************************************
 *
 * tftp_disconnect
 *
 * The disconnect callback
 *
 **********************************************************/
static CURLcode tftp_disconnect(struct connectdata *conn, bool dead_connection)

{
  struct tftp_state_data *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)
{
  struct tftp_state_data *state;
  int blksize;
  int need_blksize;


  blksize = TFTP_BLKSIZE_DEFAULT;

  state = conn->proto.tftpc = calloc(1, sizeof(struct tftp_state_data));
  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;
  }

  need_blksize = blksize;
  /* default size is the fallback when no OACK is received */
  if(need_blksize < TFTP_BLKSIZE_DEFAULT)







|
>


>



















|




>








|
|







960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
/**********************************************************
 *
 * tftp_disconnect
 *
 * The disconnect callback
 *
 **********************************************************/
static CURLcode tftp_disconnect(struct Curl_easy *data,
                                struct connectdata *conn, bool dead_connection)
{
  struct tftp_state_data *state = conn->proto.tftpc;
  (void) data;
  (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 Curl_easy *data, bool *done)
{
  struct tftp_state_data *state;
  int blksize;
  int need_blksize;
  struct connectdata *conn = data->conn;

  blksize = TFTP_BLKSIZE_DEFAULT;

  state = conn->proto.tftpc = calloc(1, sizeof(struct tftp_state_data));
  if(!state)
    return CURLE_OUT_OF_MEMORY;

  /* alloc pkt buffers based on specified blksize */
  if(data->set.tftp_blksize) {
    blksize = (int)data->set.tftp_blksize;
    if(blksize > TFTP_BLKSIZE_MAX || blksize < TFTP_BLKSIZE_MIN)
      return CURLE_TFTP_ILLEGAL;
  }

  need_blksize = blksize;
  /* default size is the fallback when no OACK is received */
  if(need_blksize < TFTP_BLKSIZE_DEFAULT)
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
      return CURLE_OUT_OF_MEMORY;
  }

  /* we don't keep TFTP connections up basically 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; /* Unless updated by OACK response */
  state->requested_blksize = blksize;

  ((struct sockaddr *)&state->local_addr)->sa_family =
    (CURL_SA_FAMILY_T)(conn->ip_addr->ai_family);







|
|







1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
      return CURLE_OUT_OF_MEMORY;
  }

  /* we don't keep TFTP connections up basically because there's none or very
   * little gain for UDP */
  connclose(conn, "TFTP");

  state->data = data;
  state->sockfd = conn->sock[FIRSTSOCKET];
  state->state = TFTP_STATE_START;
  state->error = TFTP_ERR_NONE;
  state->blksize = TFTP_BLKSIZE_DEFAULT; /* Unless updated by OACK response */
  state->requested_blksize = blksize;

  ((struct sockaddr *)&state->local_addr)->sa_family =
    (CURL_SA_FAMILY_T)(conn->ip_addr->ai_family);
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083

1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105

1106
1107

1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
     * assume uses the same IP version and thus hopefully this works for both
     * IPv4 and IPv6...
     */
    int rc = bind(state->sockfd, (struct sockaddr *)&state->local_addr,
                  conn->ip_addr->ai_addrlen);
    if(rc) {
      char buffer[STRERROR_LEN];
      failf(conn->data, "bind() failed; %s",
            Curl_strerror(SOCKERRNO, buffer, sizeof(buffer)));
      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;

  struct tftp_state_data *state = 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)
{

  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 Curl_easy  *data = conn->data;
  struct tftp_state_data *state = conn->proto.tftpc;
  struct SingleRequest  *k = &data->req;

  /* Receive the packet */
  fromlen = sizeof(fromaddr);
  state->rbytes = (int)recvfrom(state->sockfd,
                                (void *)state->rpacket.data,







|






|













|



>





|
















>
|

>











|




|







1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
     * assume uses the same IP version and thus hopefully this works for both
     * IPv4 and IPv6...
     */
    int rc = bind(state->sockfd, (struct sockaddr *)&state->local_addr,
                  conn->ip_addr->ai_addrlen);
    if(rc) {
      char buffer[STRERROR_LEN];
      failf(data, "bind() failed; %s",
            Curl_strerror(SOCKERRNO, buffer, sizeof(buffer)));
      return CURLE_COULDNT_CONNECT;
    }
    conn->bits.bound = TRUE;
  }

  Curl_pgrsStartNow(data);

  *done = TRUE;

  return CURLE_OK;
}

/**********************************************************
 *
 * tftp_done
 *
 * The done callback
 *
 **********************************************************/
static CURLcode tftp_done(struct Curl_easy *data, CURLcode status,
                          bool premature)
{
  CURLcode result = CURLE_OK;
  struct connectdata *conn = data->conn;
  struct tftp_state_data *state = conn->proto.tftpc;

  (void)status; /* unused */
  (void)premature; /* not used */

  if(Curl_pgrsDone(data))
    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 Curl_easy *data,
                        struct connectdata *conn, curl_socket_t *socks)
{
  (void)data;
  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 Curl_easy *data)
{
  struct Curl_sockaddr_storage fromaddr;
  curl_socklen_t        fromlen;
  CURLcode              result = CURLE_OK;
  struct connectdata *conn = data->conn;
  struct tftp_state_data *state = conn->proto.tftpc;
  struct SingleRequest  *k = &data->req;

  /* Receive the packet */
  fromlen = sizeof(fromaddr);
  state->rbytes = (int)recvfrom(state->sockfd,
                                (void *)state->rpacket.data,
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212

1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
    state->event = (tftp_event_t)event;

    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:
    {
      unsigned short error = getrpacketblock(&state->rpacket);
      char *str = (char *)state->rpacket.data + 4;
      size_t strn = state->rbytes - 4;
      state->error = (tftp_error_t)error;
      if(Curl_strnlen(str, strn) < strn)
        infof(data, "TFTP error: %s\n", str);
      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;

  struct tftp_state_data *state = 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;
  }
  if(current > state->rx_time + state->retry_time) {
    if(event)







|
















|




















|














|


>







|







1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
    state->event = (tftp_event_t)event;

    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(data, 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:
    {
      unsigned short error = getrpacketblock(&state->rpacket);
      char *str = (char *)state->rpacket.data + 4;
      size_t strn = state->rbytes - 4;
      state->error = (tftp_error_t)error;
      if(tftp_strnlen(str, strn) < strn)
        infof(data, "TFTP error: %s\n", str);
      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(data)) {
      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 Curl_easy *data, tftp_event_t *event)
{
  time_t current;
  struct connectdata *conn = data->conn;
  struct tftp_state_data *state = conn->proto.tftpc;

  if(event)
    *event = TFTP_EVENT_NONE;

  time(&current);
  if(current > state->max_time) {
    DEBUGF(infof(data, "timeout: %ld > %ld\n",
                 (long)current, (long)state->max_time));
    state->error = TFTP_ERR_TIMEOUT;
    state->state = TFTP_STATE_FIN;
    return 0;
  }
  if(current > state->rx_time + state->retry_time) {
    if(event)
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
/**********************************************************
 *
 * tftp_multi_statemach
 *
 * Handle single RX socket event and return
 *
 **********************************************************/
static CURLcode tftp_multi_statemach(struct connectdata *conn, bool *done)
{
  tftp_event_t          event;
  CURLcode              result = CURLE_OK;
  struct Curl_easy  *data = conn->data;
  struct tftp_state_data *state = 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;
  }







|

|
|
|

|







1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
/**********************************************************
 *
 * tftp_multi_statemach
 *
 * Handle single RX socket event and return
 *
 **********************************************************/
static CURLcode tftp_multi_statemach(struct Curl_easy *data, bool *done)
{
  tftp_event_t event;
  CURLcode result = CURLE_OK;
  struct connectdata *conn = data->conn;
  struct tftp_state_data *state = conn->proto.tftpc;
  long timeout_ms = tftp_state_timeout(data, &event);

  *done = FALSE;

  if(timeout_ms <= 0) {
    failf(data, "TFTP response timeout");
    return CURLE_OPERATION_TIMEDOUT;
  }
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
      /* bail out */
      int error = SOCKERRNO;
      char buffer[STRERROR_LEN];
      failf(data, "%s", Curl_strerror(error, buffer, sizeof(buffer)));
      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)







|







1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
      /* bail out */
      int error = SOCKERRNO;
      char buffer[STRERROR_LEN];
      failf(data, "%s", Curl_strerror(error, buffer, sizeof(buffer)));
      state->event = TFTP_EVENT_ERROR;
    }
    else if(rc != 0) {
      result = tftp_receive_packet(data);
      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)
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333

1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365

1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390

1391
1392
1393
1394
1395
1396
1397
1398
1399
/**********************************************************
 *
 * 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_now());
  }
  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;

  struct tftp_state_data *state = 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)
{
  struct tftp_state_data *state;
  CURLcode result;


  *done = FALSE;

  if(!conn->proto.tftpc) {
    result = tftp_connect(conn, done);
    if(result)
      return result;
  }

  state = conn->proto.tftpc;
  if(!state)
    return CURLE_TFTP_ILLEGAL;

  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 Curl_easy *data = conn->data;
  char *type;

  conn->transport = TRNSPRT_UDP;

  /* TFTP URLs support an extension like ";mode=<typecode>" that
   * we'll try to get now! */
  type = strstr(data->state.up.path, ";mode=");







|


|


|





|


|











|

|
>









|


|















|



>




|








|










|
>

<







1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403

1404
1405
1406
1407
1408
1409
1410
/**********************************************************
 *
 * tftp_doing
 *
 * Called from multi.c while DOing
 *
 **********************************************************/
static CURLcode tftp_doing(struct Curl_easy *data, bool *dophase_done)
{
  CURLcode result;
  result = tftp_multi_statemach(data, dophase_done);

  if(*dophase_done) {
    DEBUGF(infof(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(data))
      result = CURLE_ABORTED_BY_CALLBACK;
    else
      result = Curl_speedcheck(data, Curl_now());
  }
  return result;
}

/**********************************************************
 *
 * tftp_peform
 *
 * Entry point for transfer from tftp_do, sarts state mach
 *
 **********************************************************/
static CURLcode tftp_perform(struct Curl_easy *data, bool *dophase_done)
{
  CURLcode result = CURLE_OK;
  struct connectdata *conn = data->conn;
  struct tftp_state_data *state = 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(data, dophase_done);

  if(*dophase_done)
    DEBUGF(infof(data, "DO phase is complete\n"));

  return result;
}


/**********************************************************
 *
 * tftp_do
 *
 * The do callback
 *
 * This callback initiates the TFTP transfer
 *
 **********************************************************/

static CURLcode tftp_do(struct Curl_easy *data, bool *done)
{
  struct tftp_state_data *state;
  CURLcode result;
  struct connectdata *conn = data->conn;

  *done = FALSE;

  if(!conn->proto.tftpc) {
    result = tftp_connect(data, done);
    if(result)
      return result;
  }

  state = conn->proto.tftpc;
  if(!state)
    return CURLE_TFTP_ILLEGAL;

  result = tftp_perform(data, 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 Curl_easy *data,
                                      struct connectdata *conn)
{

  char *type;

  conn->transport = TRNSPRT_UDP;

  /* TFTP URLs support an extension like ";mode=<typecode>" that
   * we'll try to get now! */
  type = strstr(data->state.up.path, ";mode=");
Changes to jni/curl/lib/transfer.c.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2020, 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 https://curl.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







|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2021, 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 https://curl.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
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
    !defined(CURL_DISABLE_IMAP)
/*
 * checkheaders() checks the linked list of custom headers for a
 * particular header (prefix). Provide the prefix without colon!
 *
 * Returns a pointer to the first matching header or NULL if none matched.
 */
char *Curl_checkheaders(const struct connectdata *conn,
                        const char *thisheader)
{
  struct curl_slist *head;
  size_t thislen = strlen(thisheader);
  struct Curl_easy *data = conn->data;

  for(head = data->set.headers; head; head = head->next) {
    if(strncasecompare(head->data, thisheader, thislen) &&
       Curl_headersep(head->data[thislen]) )
      return head->data;
  }








|




<







89
90
91
92
93
94
95
96
97
98
99
100

101
102
103
104
105
106
107
    !defined(CURL_DISABLE_IMAP)
/*
 * checkheaders() checks the linked list of custom headers for a
 * particular header (prefix). Provide the prefix without colon!
 *
 * Returns a pointer to the first matching header or NULL if none matched.
 */
char *Curl_checkheaders(const struct Curl_easy *data,
                        const char *thisheader)
{
  struct curl_slist *head;
  size_t thislen = strlen(thisheader);


  for(head = data->set.headers; head; head = head->next) {
    if(strncasecompare(head->data, thisheader, thislen) &&
       Curl_headersep(head->data[thislen]) )
      return head->data;
  }

121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168

169
170
171
172
173
174
175
}

#ifndef CURL_DISABLE_HTTP
/*
 * This function will be called to loop through the trailers buffer
 * until no more data is available for sending.
 */
static size_t Curl_trailers_read(char *buffer, size_t size, size_t nitems,
                                 void *raw)
{
  struct Curl_easy *data = (struct Curl_easy *)raw;
  struct dynbuf *trailers_buf = &data->state.trailers_buf;
  size_t bytes_left = Curl_dyn_len(trailers_buf) -
    data->state.trailers_bytes_sent;
  size_t to_copy = (size*nitems < bytes_left) ? size*nitems : bytes_left;
  if(to_copy) {
    memcpy(buffer,
           Curl_dyn_ptr(trailers_buf) + data->state.trailers_bytes_sent,
           to_copy);
    data->state.trailers_bytes_sent += to_copy;
  }
  return to_copy;
}

static size_t Curl_trailers_left(void *raw)
{
  struct Curl_easy *data = (struct Curl_easy *)raw;
  struct dynbuf *trailers_buf = &data->state.trailers_buf;
  return Curl_dyn_len(trailers_buf) - data->state.trailers_bytes_sent;
}
#endif

/*
 * This function will call the read callback to fill our buffer with data
 * to upload.
 */
CURLcode Curl_fillreadbuffer(struct connectdata *conn, size_t bytes,
                             size_t *nreadp)
{
  struct Curl_easy *data = conn->data;
  size_t buffersize = bytes;
  size_t nread;

  curl_read_callback readfunc = NULL;
  void *extra_data = NULL;

#ifdef CURL_DOES_CONVERSIONS
  bool sending_http_headers = FALSE;


  if(conn->handler->protocol&(PROTO_FAMILY_HTTP|CURLPROTO_RTSP)) {
    const struct HTTP *http = data->req.p.http;

    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. */







|
|















|











|


<








>







120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158

159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
}

#ifndef CURL_DISABLE_HTTP
/*
 * This function will be called to loop through the trailers buffer
 * until no more data is available for sending.
 */
static size_t trailers_read(char *buffer, size_t size, size_t nitems,
                            void *raw)
{
  struct Curl_easy *data = (struct Curl_easy *)raw;
  struct dynbuf *trailers_buf = &data->state.trailers_buf;
  size_t bytes_left = Curl_dyn_len(trailers_buf) -
    data->state.trailers_bytes_sent;
  size_t to_copy = (size*nitems < bytes_left) ? size*nitems : bytes_left;
  if(to_copy) {
    memcpy(buffer,
           Curl_dyn_ptr(trailers_buf) + data->state.trailers_bytes_sent,
           to_copy);
    data->state.trailers_bytes_sent += to_copy;
  }
  return to_copy;
}

static size_t trailers_left(void *raw)
{
  struct Curl_easy *data = (struct Curl_easy *)raw;
  struct dynbuf *trailers_buf = &data->state.trailers_buf;
  return Curl_dyn_len(trailers_buf) - data->state.trailers_bytes_sent;
}
#endif

/*
 * This function will call the read callback to fill our buffer with data
 * to upload.
 */
CURLcode Curl_fillreadbuffer(struct Curl_easy *data, size_t bytes,
                             size_t *nreadp)
{

  size_t buffersize = bytes;
  size_t nread;

  curl_read_callback readfunc = NULL;
  void *extra_data = NULL;

#ifdef CURL_DOES_CONVERSIONS
  bool sending_http_headers = FALSE;
  struct connectdata *conn = data->conn;

  if(conn->handler->protocol&(PROTO_FAMILY_HTTP|CURLPROTO_RTSP)) {
    const struct HTTP *http = data->req.p.http;

    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. */
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
  if(data->state.trailers_state == TRAILERS_SENDING) {
    /* if we're here then that means that we already sent the last empty chunk
       but we didn't send a final CR LF, so we sent 0 CR LF. We then start
       pulling trailing data until we have no more at which point we
       simply return to the previous point in the state machine as if
       nothing happened.
       */
    readfunc = Curl_trailers_read;
    extra_data = (void *)data;
  }
  else
#endif
  {
    readfunc = data->state.fread_func;
    extra_data = data->state.in;







|







226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
  if(data->state.trailers_state == TRAILERS_SENDING) {
    /* if we're here then that means that we already sent the last empty chunk
       but we didn't send a final CR LF, so we sent 0 CR LF. We then start
       pulling trailing data until we have no more at which point we
       simply return to the previous point in the state machine as if
       nothing happened.
       */
    readfunc = trailers_read;
    extra_data = (void *)data;
  }
  else
#endif
  {
    readfunc = data->state.fread_func;
    extra_data = data->state.in;
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
    failf(data, "operation aborted by callback");
    *nreadp = 0;
    return CURLE_ABORTED_BY_CALLBACK;
  }
  if(nread == CURL_READFUNC_PAUSE) {
    struct SingleRequest *k = &data->req;

    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;
    }








|







249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
    failf(data, "operation aborted by callback");
    *nreadp = 0;
    return CURLE_ABORTED_BY_CALLBACK;
  }
  if(nread == CURL_READFUNC_PAUSE) {
    struct SingleRequest *k = &data->req;

    if(data->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;
    }

363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
          return result;
      }
    }
#endif /* CURL_DOES_CONVERSIONS */

#ifndef CURL_DISABLE_HTTP
    if(data->state.trailers_state == TRAILERS_SENDING &&
       !Curl_trailers_left(data)) {
      Curl_dyn_free(&data->state.trailers_buf);
      data->state.trailers_state = TRAILERS_DONE;
      data->set.trailer_data = NULL;
      data->set.trailer_callback = NULL;
      /* mark the transfer as done */
      data->req.upload_done = TRUE;
      infof(data, "Signaling end of chunked upload after trailers.\n");







|







362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
          return result;
      }
    }
#endif /* CURL_DOES_CONVERSIONS */

#ifndef CURL_DISABLE_HTTP
    if(data->state.trailers_state == TRAILERS_SENDING &&
       !trailers_left(data)) {
      Curl_dyn_free(&data->state.trailers_buf);
      data->state.trailers_state = TRAILERS_DONE;
      data->set.trailer_data = NULL;
      data->set.trailer_callback = NULL;
      /* mark the transfer as done */
      data->req.upload_done = TRUE;
      infof(data, "Signaling end of chunked upload after trailers.\n");
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422


/*
 * 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.
 */
CURLcode Curl_readrewind(struct connectdata *conn)
{
  struct Curl_easy *data = conn->data;
  curl_mimepart *mimepart = &data->set.mimepost;

  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







|

|







405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421


/*
 * 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.
 */
CURLcode Curl_readrewind(struct Curl_easy *data)
{
  struct connectdata *conn = data->conn;
  curl_mimepart *mimepart = &data->set.mimepost;

  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
432
433
434
435
436
437
438
439

440
441
442
443
444
445
446
447
448
    if(http->sendit)
      mimepart = http->sendit;
  }
  if(data->set.postfields)
    ; /* do nothing */
  else if(data->state.httpreq == HTTPREQ_POST_MIME ||
          data->state.httpreq == HTTPREQ_POST_FORM) {
    if(Curl_mime_rewind(mimepart)) {

      failf(data, "Cannot rewind mime/post data");
      return CURLE_SEND_FAIL_REWIND;
    }
  }
  else {
    if(data->set.seek_func) {
      int err;

      Curl_set_in_callback(data, true);







|
>

|







431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
    if(http->sendit)
      mimepart = http->sendit;
  }
  if(data->set.postfields)
    ; /* do nothing */
  else if(data->state.httpreq == HTTPREQ_POST_MIME ||
          data->state.httpreq == HTTPREQ_POST_FORM) {
    CURLcode result = Curl_mime_rewind(mimepart);
    if(result) {
      failf(data, "Cannot rewind mime/post data");
      return result;
    }
  }
  else {
    if(data->set.seek_func) {
      int err;

      Curl_set_in_callback(data, true);
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
      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, buf, bytestoread, &nread);

      /* read would've blocked */
      if(CURLE_AGAIN == result)
        break; /* get out of loop */

      if(result>0)
        return result;







|







595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
      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(data, conn->sockfd, buf, bytestoread, &nread);

      /* read would've blocked */
      if(CURLE_AGAIN == result)
        break; /* get out of loop */

      if(result>0)
        return result;
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775

#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->state.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) {







|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
<
<
<
<
<
<
<
<
|
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







704
705
706
707
708
709
710
711

















712








713
714





























715
716
717
718
719
720
721

#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 */
          result = Curl_http_firstwrite(data, conn, done);

















          if(result || *done)








            return result;
        }





























      } /* 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) {
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820

821
822
823
824
825
826
827
828
         * 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.
         */
        CURLcode extra;
        CHUNKcode res =
          Curl_httpchunk_read(conn, k->str, nread, &nread, &extra);

        if(CHUNKE_OK < res) {
          if(CHUNKE_PASSTHRU_ERROR == res) {
            failf(data, "Failed reading the chunked-encoded stream");
            return extra;
          }
          failf(data, "%s in chunked-encoding", Curl_chunked_strerror(res));
          return CURLE_RECV_ERROR;
        }
        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.
             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 it returned OK, we just keep going */
      }
#endif   /* CURL_DISABLE_HTTP */

      /* Account for body content stored in the header buffer */







|










<



|
|
<
<
|
<
|
>
|







738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755

756
757
758
759
760


761

762
763
764
765
766
767
768
769
770
771
         * 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.
         */
        CURLcode extra;
        CHUNKcode res =
          Curl_httpchunk_read(data, k->str, nread, &nread, &extra);

        if(CHUNKE_OK < res) {
          if(CHUNKE_PASSTHRU_ERROR == res) {
            failf(data, "Failed reading the chunked-encoded stream");
            return extra;
          }
          failf(data, "%s in chunked-encoding", Curl_chunked_strerror(res));
          return CURLE_RECV_ERROR;
        }
        if(CHUNKE_STOP == res) {

          /* we're done reading chunks! */
          k->keepon &= ~KEEP_RECV; /* read no more */

          /* N number of bytes at the end of the str buffer that weren't
             written to the client. */


          if(conn->chunk.datasize) {

            infof(data, "Leftovers after chunking: % "
                  CURL_FORMAT_CURL_OFF_T "u bytes\n",
                  conn->chunk.datasize);
          }
        }
        /* If it returned OK, we just keep going */
      }
#endif   /* CURL_DISABLE_HTTP */

      /* Account for body content stored in the header buffer */
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
        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 */
          size_t headlen = Curl_dyn_len(&data->state.headerb);

          /* Don't let excess data pollute body writes */
          if(k->maxdownload == -1 || (curl_off_t)headlen <= k->maxdownload)
            result = Curl_client_write(conn, CLIENTWRITE_BODY,
                                       Curl_dyn_ptr(&data->state.headerb),
                                       headlen);
          else
            result = Curl_client_write(conn, CLIENTWRITE_BODY,
                                       Curl_dyn_ptr(&data->state.headerb),
                                       (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. */
          if(conn->data->set.http_ce_skip || !k->writer_stack) {
            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);
            }
          }
          else if(!k->ignorebody)
            result = Curl_unencode_write(conn, k->writer_stack, k->str, nread);
        }
        k->badheader = HEADER_NORMAL; /* taken care of now */

        if(result)
          return result;
      }








|



|












|



|


|




|







807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
        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 */
          size_t headlen = Curl_dyn_len(&data->state.headerb);

          /* Don't let excess data pollute body writes */
          if(k->maxdownload == -1 || (curl_off_t)headlen <= k->maxdownload)
            result = Curl_client_write(data, CLIENTWRITE_BODY,
                                       Curl_dyn_ptr(&data->state.headerb),
                                       headlen);
          else
            result = Curl_client_write(data, CLIENTWRITE_BODY,
                                       Curl_dyn_ptr(&data->state.headerb),
                                       (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. */
          if(data->set.http_ce_skip || !k->writer_stack) {
            if(!k->ignorebody) {
#ifndef CURL_DISABLE_POP3
              if(conn->handler->protocol & PROTO_FAMILY_POP3)
                result = Curl_pop3_write(data, k->str, nread);
              else
#endif /* CURL_DISABLE_POP3 */
                result = Curl_client_write(data, CLIENTWRITE_BODY, k->str,
                                           nread);
            }
          }
          else if(!k->ignorebody)
            result = Curl_unencode_write(data, k->writer_stack, k->str, nread);
        }
        k->badheader = HEADER_NORMAL; /* taken care of now */

        if(result)
          return result;
      }

954
955
956
957
958
959
960
961
962
963

964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
    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;
}

CURLcode Curl_done_sending(struct connectdata *conn,
                           struct SingleRequest *k)
{

  k->keepon &= ~KEEP_SEND; /* we're done writing */

  /* These functions should be moved into the handler struct! */
  Curl_http2_done_sending(conn);
  Curl_quic_done_sending(conn);

  if(conn->bits.rewindaftersend) {
    CURLcode result = Curl_readrewind(conn);
    if(result)
      return result;
  }
  return CURLE_OK;
}

#if defined(WIN32) && !defined(USE_LWIPSOCK)







|


>



|
|


|







897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
    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;
}

CURLcode Curl_done_sending(struct Curl_easy *data,
                           struct SingleRequest *k)
{
  struct connectdata *conn = data->conn;
  k->keepon &= ~KEEP_SEND; /* we're done writing */

  /* These functions should be moved into the handler struct! */
  Curl_http2_done_sending(data, conn);
  Curl_quic_done_sending(data);

  if(conn->bits.rewindaftersend) {
    CURLcode result = Curl_readrewind(data);
    if(result)
      return result;
  }
  return CURLE_OK;
}

#if defined(WIN32) && !defined(USE_LWIPSOCK)
1012
1013
1014
1015
1016
1017
1018


1019
1020
1021
1022
1023
1024
1025

  if((k->bytecount == 0) && (k->writebytecount == 0))
    Curl_pgrsTime(data, TIMER_STARTTRANSFER);

  *didwhat |= KEEP_SEND;

  do {


    /* only read more data if there's no upload data already
       present in the upload buffer */
    if(0 == k->upload_present) {
      result = Curl_get_upload_buffer(data);
      if(result)
        return result;
      /* init the "upload from here" pointer */







>
>







956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971

  if((k->bytecount == 0) && (k->writebytecount == 0))
    Curl_pgrsTime(data, TIMER_STARTTRANSFER);

  *didwhat |= KEEP_SEND;

  do {
    curl_off_t nbody;

    /* only read more data if there's no upload data already
       present in the upload buffer */
    if(0 == k->upload_present) {
      result = Curl_get_upload_buffer(data);
      if(result)
        return result;
      /* init the "upload from here" pointer */
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
            /* 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, data->set.upload_buffer_size,
                                     &fillcount);
        if(result)
          return result;

        nread = fillcount;
      }
      else
        nread = 0; /* we're done uploading/reading */

      if(!nread && (k->keepon & KEEP_SEND_PAUSE)) {
        /* this is a paused transfer */
        break;
      }
      if(nread <= 0) {
        result = Curl_done_sending(conn, k);
        if(result)
          return result;
        break;
      }

      /* store number of bytes available for upload */
      k->upload_present = nread;







|














|







996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
            /* 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(data, data->set.upload_buffer_size,
                                     &fillcount);
        if(result)
          return result;

        nread = fillcount;
      }
      else
        nread = 0; /* we're done uploading/reading */

      if(!nread && (k->keepon & KEEP_SEND_PAUSE)) {
        /* this is a paused transfer */
        break;
      }
      if(nread <= 0) {
        result = Curl_done_sending(data, k);
        if(result)
          return result;
        break;
      }

      /* store number of bytes available for upload */
      k->upload_present = nread;
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155



1156









1157

1158
1159
1160
1161

1162
1163
1164
1165
1166
1167
1168
          /* set the new amount too */
          k->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 == k->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 */
                        k->upload_fromhere, /* buffer pointer */
                        k->upload_present,  /* buffer size */
                        &bytes_written);    /* actually sent */
    if(result)
      return result;

    win_update_buffer_size(conn->writesockfd);




    /* show the data before we change the pointer upload_fromhere */









    Curl_debug(data, CURLINFO_DATA_OUT, k->upload_fromhere,

               (size_t)bytes_written);

    k->writebytecount += bytes_written;
    Curl_pgrsSetUploadCounter(data, k->writebytecount);


    if((!k->upload_chunky || k->forbidchunk) &&
       (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");
    }







|











|









>
>
>
|
>
>
>
>
>
>
>
>
>
|
>
|

|
|
>







1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
          /* set the new amount too */
          k->upload_present = nread;
        }
      }

#ifndef CURL_DISABLE_SMTP
      if(conn->handler->protocol & PROTO_FAMILY_SMTP) {
        result = Curl_smtp_escape_eob(data, nread);
        if(result)
          return result;
      }
#endif /* CURL_DISABLE_SMTP */
    } /* if 0 == k->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(data,
                        conn->writesockfd,  /* socket to send to */
                        k->upload_fromhere, /* buffer pointer */
                        k->upload_present,  /* buffer size */
                        &bytes_written);    /* actually sent */
    if(result)
      return result;

    win_update_buffer_size(conn->writesockfd);

    if(k->pendingheader) {
      /* parts of what was sent was header */
      curl_off_t n = CURLMIN(k->pendingheader, bytes_written);
      /* show the data before we change the pointer upload_fromhere */
      Curl_debug(data, CURLINFO_HEADER_OUT, k->upload_fromhere, (size_t)n);
      k->pendingheader -= n;
      nbody = bytes_written - n; /* size of the written body part */
    }
    else
      nbody = bytes_written;

    if(nbody) {
      /* show the data before we change the pointer upload_fromhere */
      Curl_debug(data, CURLINFO_DATA_OUT,
                 &k->upload_fromhere[bytes_written - nbody],
                 (size_t)nbody);

      k->writebytecount += nbody;
      Curl_pgrsSetUploadCounter(data, k->writebytecount);
    }

    if((!k->upload_chunky || k->forbidchunk) &&
       (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");
    }
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
      result = Curl_get_upload_buffer(data);
      if(result)
        return result;
      k->upload_fromhere = data->state.ulbuf;
      k->upload_present = 0; /* no more bytes left */

      if(k->upload_done) {
        result = Curl_done_sending(conn, k);
        if(result)
          return result;
      }
    }


  } while(0); /* just to break out from! */







|







1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
      result = Curl_get_upload_buffer(data);
      if(result)
        return result;
      k->upload_fromhere = data->state.ulbuf;
      k->upload_present = 0; /* no more bytes left */

      if(k->upload_done) {
        result = Curl_done_sending(data, k);
        if(result)
          return result;
      }
    }


  } while(0); /* just to break out from! */
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249




1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
    fd_read = CURL_SOCKET_BAD;

  if((k->keepon & KEEP_SENDBITS) == KEEP_SEND)
    fd_write = conn->writesockfd;
  else
    fd_write = CURL_SOCKET_BAD;

  if(conn->data->state.drain) {
    select_res |= CURL_CSELECT_IN;
    DEBUGF(infof(data, "Curl_readwrite: forcibly told to drain data\n"));
  }

  if(!select_res) /* Call for select()/poll() only, if read/write/error
                     status is not known. */
    select_res = Curl_socket_check(fd_read, CURL_SOCKET_BAD, 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)) {
    result = readwrite_data(data, conn, k, &didwhat, done, comeback);
    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, &didwhat);
    if(result)
      return result;
  }

  k->now = Curl_now();
  if(didwhat) {
    ;
  }
  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":







|













>
>
>
>



















|
<
<
<







1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233



1234
1235
1236
1237
1238
1239
1240
    fd_read = CURL_SOCKET_BAD;

  if((k->keepon & KEEP_SENDBITS) == KEEP_SEND)
    fd_write = conn->writesockfd;
  else
    fd_write = CURL_SOCKET_BAD;

  if(data->state.drain) {
    select_res |= CURL_CSELECT_IN;
    DEBUGF(infof(data, "Curl_readwrite: forcibly told to drain data\n"));
  }

  if(!select_res) /* Call for select()/poll() only, if read/write/error
                     status is not known. */
    select_res = Curl_socket_check(fd_read, CURL_SOCKET_BAD, fd_write, 0);

  if(select_res == CURL_CSELECT_ERR) {
    failf(data, "select/poll returned error");
    return CURLE_SEND_ERROR;
  }

#ifdef USE_HYPER
  if(conn->datastream)
    return conn->datastream(data, conn, &didwhat, done, select_res);
#endif
  /* 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)) {
    result = readwrite_data(data, conn, k, &didwhat, done, comeback);
    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, &didwhat);
    if(result)
      return result;
  }

  k->now = Curl_now();
  if(!didwhat) {



    /* 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":
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
        k->keepon |= KEEP_SEND;
        Curl_expire_done(data, EXPIRE_100_TIMEOUT);
        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) {







|







1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
        k->keepon |= KEEP_SEND;
        Curl_expire_done(data, EXPIRE_100_TIMEOUT);
        infof(data, "Done waiting for 100-continue\n");
      }
    }
  }

  if(Curl_pgrsUpdate(data))
    result = CURLE_ABORTED_BY_CALLBACK;
  else
    result = Curl_speedcheck(data, k->now);
  if(result)
    return result;

  if(k->keepon) {
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376

1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
       * 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.
 */
int Curl_single_getsock(const struct connectdata *conn,

                        curl_socket_t *sock)
{
  const struct Curl_easy *data = conn->data;
  int bitmap = GETSOCK_BLANK;
  unsigned sockindex = 0;

  if(conn->handler->perform_getsock)
    return conn->handler->perform_getsock(conn, sock);

  /* 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);







|

















|
>


<




|







1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340

1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
       * 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(data))
      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.
 */
int Curl_single_getsock(struct Curl_easy *data,
                        struct connectdata *conn,
                        curl_socket_t *sock)
{

  int bitmap = GETSOCK_BLANK;
  unsigned sockindex = 0;

  if(conn->handler->perform_getsock)
    return conn->handler->perform_getsock(data, conn, sock);

  /* 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);
1528
1529
1530
1531
1532
1533
1534














1535
1536
1537
1538
1539
1540
1541
      }
    }
#endif
    Curl_http2_init_state(&data->state);
    Curl_hsts_loadcb(data, data->hsts);
  }















  return result;
}

/*
 * Curl_posttransfer() is called immediately after a transfer ends
 */
CURLcode Curl_posttransfer(struct Curl_easy *data)







>
>
>
>
>
>
>
>
>
>
>
>
>
>







1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
      }
    }
#endif
    Curl_http2_init_state(&data->state);
    Curl_hsts_loadcb(data, data->hsts);
  }

  /*
   * 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(data->state.aptr.uagent);
    data->state.aptr.uagent =
      aprintf("User-Agent: %s\r\n", data->set.str[STRING_USERAGENT]);
    if(!data->state.aptr.uagent)
      return CURLE_OUT_OF_MEMORY;
  }

  data->req.headerbytecount = 0;
  return result;
}

/*
 * Curl_posttransfer() is called immediately after a transfer ends
 */
CURLcode Curl_posttransfer(struct Curl_easy *data)
1570
1571
1572
1573
1574
1575
1576


1577
1578
1579
1580
1581
1582
1583
#else

  /* Location: redirect */
  bool disallowport = FALSE;
  bool reachedmax = FALSE;
  CURLUcode uc;



  if(type == FOLLOW_REDIR) {
    if((data->set.maxredirs != -1) &&
       (data->set.followlocation >= data->set.maxredirs)) {
      reachedmax = TRUE;
      type = FOLLOW_FAKE; /* switch to fake to store the would-be-redirected
                             to URL */
    }







>
>







1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
#else

  /* Location: redirect */
  bool disallowport = FALSE;
  bool reachedmax = FALSE;
  CURLUcode uc;

  DEBUGASSERT(type != FOLLOW_NONE);

  if(type == FOLLOW_REDIR) {
    if((data->set.maxredirs != -1) &&
       (data->set.followlocation >= data->set.maxredirs)) {
      reachedmax = TRUE;
      type = FOLLOW_FAKE; /* switch to fake to store the would-be-redirected
                             to URL */
    }
1601
1602
1603
1604
1605
1606
1607


1608

1609
1610
1611
1612
1613
1614
1615
1616
        if(!data->change.referer)
          return CURLE_OUT_OF_MEMORY;
        data->change.referer_alloc = TRUE; /* yes, free this later */
      }
    }
  }



  if(Curl_is_absolute_url(newurl, NULL, MAX_SCHEME_LEN))

    /* This is an absolute URL, don't allow the custom port number */
    disallowport = TRUE;

  DEBUGASSERT(data->state.uh);
  uc = curl_url_set(data->state.uh, CURLUPART_URL, newurl,
                    (type == FOLLOW_FAKE) ? CURLU_NON_SUPPORT_SCHEME :
                    ((type == FOLLOW_REDIR) ? CURLU_URLENCODE : 0) );
  if(uc) {







>
>
|
>
|







1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
        if(!data->change.referer)
          return CURLE_OUT_OF_MEMORY;
        data->change.referer_alloc = TRUE; /* yes, free this later */
      }
    }
  }

  if((type != FOLLOW_RETRY) &&
     (data->req.httpcode != 401) && (data->req.httpcode != 407) &&
     Curl_is_absolute_url(newurl, NULL, MAX_SCHEME_LEN))
    /* If this is not redirect due to a 401 or 407 response and an absolute
       URL: don't allow a custom port number */
    disallowport = TRUE;

  DEBUGASSERT(data->state.uh);
  uc = curl_url_set(data->state.uh, CURLUPART_URL, newurl,
                    (type == FOLLOW_FAKE) ? CURLU_NON_SUPPORT_SCHEME :
                    ((type == FOLLOW_REDIR) ? CURLU_URLENCODE : 0) );
  if(uc) {
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
     *
     * ----
     *
     * 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->state.httpreq == HTTPREQ_POST
        || data->state.httpreq == HTTPREQ_POST_FORM
        || data->state.httpreq == HTTPREQ_POST_MIME)
       && !(data->set.keep_post & CURL_REDIR_POST_301)) {
      infof(data, "Switch from POST to GET\n");







|







1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
     *
     * ----
     *
     * 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 behavior is forbidden by RFC1945 and the obsolete RFC2616, and
     * can be overridden with CURLOPT_POSTREDIR.
     */
    if((data->state.httpreq == HTTPREQ_POST
        || data->state.httpreq == HTTPREQ_POST_FORM
        || data->state.httpreq == HTTPREQ_POST_MIME)
       && !(data->set.keep_post & CURL_REDIR_POST_301)) {
      infof(data, "Switch from POST to GET\n");
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
     *
     * ----
     *
     * 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->state.httpreq == HTTPREQ_POST
        || data->state.httpreq == HTTPREQ_POST_FORM
        || data->state.httpreq == HTTPREQ_POST_MIME)
       && !(data->set.keep_post & CURL_REDIR_POST_302)) {
      infof(data, "Switch from POST to GET\n");







|







1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
     *
     * ----
     *
     * 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 behavior is forbidden by RFC1945 and the obsolete RFC2616, and
     * can be overridden with CURLOPT_POSTREDIR.
     */
    if((data->state.httpreq == HTTPREQ_POST
        || data->state.httpreq == HTTPREQ_POST_FORM
        || data->state.httpreq == HTTPREQ_POST_MIME)
       && !(data->set.keep_post & CURL_REDIR_POST_302)) {
      infof(data, "Switch from POST to GET\n");
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
  return CURLE_OK;
#endif /* CURL_DISABLE_HTTP */
}

/* Returns CURLE_OK *and* sets '*url' if a request retry is wanted.

   NOTE: that the *url is malloc()ed. */
CURLcode Curl_retry_request(struct connectdata *conn,
                            char **url)
{
  struct Curl_easy *data = conn->data;
  bool retry = FALSE;
  *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)))







|
<

|







1742
1743
1744
1745
1746
1747
1748
1749

1750
1751
1752
1753
1754
1755
1756
1757
1758
  return CURLE_OK;
#endif /* CURL_DISABLE_HTTP */
}

/* Returns CURLE_OK *and* sets '*url' if a request retry is wanted.

   NOTE: that the *url is malloc()ed. */
CURLcode Curl_retry_request(struct Curl_easy *data, char **url)

{
  struct connectdata *conn = data->conn;
  bool retry = FALSE;
  *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)))
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
  else if(data->state.refused_stream &&
          (data->req.bytecount + data->req.headerbytecount == 0) ) {
    /* This was sent on a refused stream, safe to rerun. A refused stream
       error can typically only happen on HTTP/2 level if the stream is safe
       to issue again, but the nghttp2 API can deliver the message to other
       streams as well, which is why this adds the check the data counters
       too. */
    infof(conn->data, "REFUSED_STREAM, retrying a fresh connect\n");
    data->state.refused_stream = FALSE; /* clear again */
    retry = TRUE;
  }
  if(retry) {
#define CONN_MAX_RETRIES 5
    if(data->state.retrycount++ >= CONN_MAX_RETRIES) {
      failf(data, "Connection died, tried %d times before giving up",
            CONN_MAX_RETRIES);
      data->state.retrycount = 0;
      return CURLE_SEND_ERROR;
    }
    infof(conn->data, "Connection died, retrying a fresh connect\
(retry count: %d)\n", data->state.retrycount);
    *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) {
      if(data->req.writebytecount) {
        CURLcode result = Curl_readrewind(conn);
        if(result) {
          Curl_safefree(*url);
          return result;
        }
      }
    }
  }







|











|

|













|







1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
  else if(data->state.refused_stream &&
          (data->req.bytecount + data->req.headerbytecount == 0) ) {
    /* This was sent on a refused stream, safe to rerun. A refused stream
       error can typically only happen on HTTP/2 level if the stream is safe
       to issue again, but the nghttp2 API can deliver the message to other
       streams as well, which is why this adds the check the data counters
       too. */
    infof(data, "REFUSED_STREAM, retrying a fresh connect\n");
    data->state.refused_stream = FALSE; /* clear again */
    retry = TRUE;
  }
  if(retry) {
#define CONN_MAX_RETRIES 5
    if(data->state.retrycount++ >= CONN_MAX_RETRIES) {
      failf(data, "Connection died, tried %d times before giving up",
            CONN_MAX_RETRIES);
      data->state.retrycount = 0;
      return CURLE_SEND_ERROR;
    }
    infof(data, "Connection died, retrying a fresh connect\
(retry count: %d)\n", data->state.retrycount);
    *url = strdup(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) {
      if(data->req.writebytecount) {
        CURLcode result = Curl_readrewind(data);
        if(result) {
          Curl_safefree(*url);
          return result;
        }
      }
    }
  }
Changes to jni/curl/lib/transfer.h.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
#ifndef HEADER_CURL_TRANSFER_H
#define HEADER_CURL_TRANSFER_H
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2020, 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 https://curl.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_headersep(x) ((((x)==':') || ((x)==';')))
char *Curl_checkheaders(const struct connectdata *conn,
                        const char *thisheader);

void Curl_init_CONNECT(struct Curl_easy *data);

CURLcode Curl_pretransfer(struct Curl_easy *data);
CURLcode Curl_posttransfer(struct Curl_easy *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;

CURLcode Curl_follow(struct Curl_easy *data, char *newurl,
                     followtype type);
CURLcode Curl_readwrite(struct connectdata *conn,
                        struct Curl_easy *data, bool *done,
                        bool *comeback);
int Curl_single_getsock(const struct connectdata *conn,
                        curl_socket_t *socks);
CURLcode Curl_readrewind(struct connectdata *conn);
CURLcode Curl_fillreadbuffer(struct connectdata *conn, size_t bytes,
                             size_t *nreadp);
CURLcode Curl_retry_request(struct connectdata *conn, char **url);
bool Curl_meets_timecondition(struct Curl_easy *data, time_t timeofdoc);
CURLcode Curl_get_upload_buffer(struct Curl_easy *data);

CURLcode Curl_done_sending(struct connectdata *conn,
                           struct SingleRequest *k);

/* This sets up a forthcoming transfer */
void
Curl_setup_transfer (struct Curl_easy *data,
                     int sockindex,     /* socket index to read from or -1 */
                     curl_off_t size,   /* -1 if unknown at this point */









|















|












|
|
<







|
|
|
|

|



|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40

41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
#ifndef HEADER_CURL_TRANSFER_H
#define HEADER_CURL_TRANSFER_H
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2021, 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 https://curl.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_headersep(x) ((((x)==':') || ((x)==';')))
char *Curl_checkheaders(const struct Curl_easy *data,
                        const char *thisheader);

void Curl_init_CONNECT(struct Curl_easy *data);

CURLcode Curl_pretransfer(struct Curl_easy *data);
CURLcode Curl_posttransfer(struct Curl_easy *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 */

} followtype;

CURLcode Curl_follow(struct Curl_easy *data, char *newurl,
                     followtype type);
CURLcode Curl_readwrite(struct connectdata *conn,
                        struct Curl_easy *data, bool *done,
                        bool *comeback);
int Curl_single_getsock(struct Curl_easy *data,
                        struct connectdata *conn, curl_socket_t *socks);
CURLcode Curl_readrewind(struct Curl_easy *data);
CURLcode Curl_fillreadbuffer(struct Curl_easy *data, size_t bytes,
                             size_t *nreadp);
CURLcode Curl_retry_request(struct Curl_easy *data, char **url);
bool Curl_meets_timecondition(struct Curl_easy *data, time_t timeofdoc);
CURLcode Curl_get_upload_buffer(struct Curl_easy *data);

CURLcode Curl_done_sending(struct Curl_easy *data,
                           struct SingleRequest *k);

/* This sets up a forthcoming transfer */
void
Curl_setup_transfer (struct Curl_easy *data,
                     int sockindex,     /* socket index to read from or -1 */
                     curl_off_t size,   /* -1 if unknown at this point */
Changes to jni/curl/lib/url.c.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2020, 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 https://curl.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







|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2021, 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 https://curl.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
247
248
249
250
251
252
253



254
255
256
257
258
259
260

#ifndef CURL_DISABLE_MQTT
  &Curl_handler_mqtt,
#endif

#ifndef CURL_DISABLE_GOPHER
  &Curl_handler_gopher,



#endif

#ifdef USE_LIBRTMP
  &Curl_handler_rtmp,
  &Curl_handler_rtmpt,
  &Curl_handler_rtmpe,
  &Curl_handler_rtmpte,







>
>
>







247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263

#ifndef CURL_DISABLE_MQTT
  &Curl_handler_mqtt,
#endif

#ifndef CURL_DISABLE_GOPHER
  &Curl_handler_gopher,
#ifdef USE_SSL
  &Curl_handler_gophers,
#endif
#endif

#ifdef USE_LIBRTMP
  &Curl_handler_rtmp,
  &Curl_handler_rtmpt,
  &Curl_handler_rtmpe,
  &Curl_handler_rtmpte,
357
358
359
360
361
362
363



364
365
366
367
368
369
370
    return CURLE_OK;

  data = *datap;
  *datap = NULL;

  Curl_expire_clear(data); /* 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) {







>
>
>







360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
    return CURLE_OK;

  data = *datap;
  *datap = NULL;

  Curl_expire_clear(data); /* shut off timers */

  /* Detach connection if any is left. This should not be normal, but can be
     the case for example with CONNECT_ONLY + recv/send (test 556) */
  Curl_detach_connnection(data);
  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) {
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_CRYPTO_AUTH)
  Curl_http_auth_cleanup_digest(data);
#endif
  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_http2_cleanup_dependencies(data);
  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);







|







423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_CRYPTO_AUTH)
  Curl_http_auth_cleanup_digest(data);
#endif
  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.async.resolver);

  Curl_http2_cleanup_dependencies(data);
  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);
441
442
443
444
445
446
447

448
449
450


451
452
453
454
455
456
457
  Curl_safefree(data->state.aptr.rangeline);
  Curl_safefree(data->state.aptr.ref);
  Curl_safefree(data->state.aptr.host);
  Curl_safefree(data->state.aptr.cookiehost);
  Curl_safefree(data->state.aptr.rtsp_transport);

#ifndef CURL_DISABLE_DOH

  Curl_dyn_free(&data->req.doh.probe[0].serverdoh);
  Curl_dyn_free(&data->req.doh.probe[1].serverdoh);
  curl_slist_free_all(data->req.doh.headers);


#endif

  /* destruct wildcard structures if it is needed */
  Curl_wildcard_dtor(&data->wildcard);
  Curl_freeset(data);
  free(data);
  return CURLE_OK;







>
|
|
|
>
>







447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
  Curl_safefree(data->state.aptr.rangeline);
  Curl_safefree(data->state.aptr.ref);
  Curl_safefree(data->state.aptr.host);
  Curl_safefree(data->state.aptr.cookiehost);
  Curl_safefree(data->state.aptr.rtsp_transport);

#ifndef CURL_DISABLE_DOH
  if(data->req.doh) {
    Curl_dyn_free(&data->req.doh->probe[0].serverdoh);
    Curl_dyn_free(&data->req.doh->probe[1].serverdoh);
    curl_slist_free_all(data->req.doh->headers);
    Curl_safefree(data->req.doh);
  }
#endif

  /* destruct wildcard structures if it is needed */
  Curl_wildcard_dtor(&data->wildcard);
  Curl_freeset(data);
  free(data);
  return CURLE_OK;
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
    /* this is a very serious error */
    DEBUGF(fprintf(stderr, "Error: calloc of Curl_easy failed\n"));
    return CURLE_OUT_OF_MEMORY;
  }

  data->magic = CURLEASY_MAGIC_NUMBER;

  result = Curl_resolver_init(data, &data->state.resolver);
  if(result) {
    DEBUGF(fprintf(stderr, "Error: resolver_init failed\n"));
    free(data);
    return result;
  }

  result = Curl_init_userdefined(data);
  if(!result) {
    Curl_dyn_init(&data->state.headerb, CURL_MAX_HTTP_HEADER);
    Curl_convert_init(data);
    Curl_initinfo(data);

    /* most recent connection is not yet defined */
    data->state.lastconnect_id = -1;

    data->progress.flags |= PGRS_HIDE;
    data->state.current_speed = -1; /* init to negative == impossible */
  }

  if(result) {
    Curl_resolver_cleanup(data->state.resolver);
    Curl_dyn_free(&data->state.headerb);
    Curl_freeset(data);
    free(data);
    data = NULL;
  }
  else
    *curl = data;







|




















|







639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
    /* this is a very serious error */
    DEBUGF(fprintf(stderr, "Error: calloc of Curl_easy failed\n"));
    return CURLE_OUT_OF_MEMORY;
  }

  data->magic = CURLEASY_MAGIC_NUMBER;

  result = Curl_resolver_init(data, &data->state.async.resolver);
  if(result) {
    DEBUGF(fprintf(stderr, "Error: resolver_init failed\n"));
    free(data);
    return result;
  }

  result = Curl_init_userdefined(data);
  if(!result) {
    Curl_dyn_init(&data->state.headerb, CURL_MAX_HTTP_HEADER);
    Curl_convert_init(data);
    Curl_initinfo(data);

    /* most recent connection is not yet defined */
    data->state.lastconnect_id = -1;

    data->progress.flags |= PGRS_HIDE;
    data->state.current_speed = -1; /* init to negative == impossible */
  }

  if(result) {
    Curl_resolver_cleanup(data->state.async.resolver);
    Curl_dyn_free(&data->state.headerb);
    Curl_freeset(data);
    free(data);
    data = NULL;
  }
  else
    *curl = data;
702
703
704
705
706
707
708
709
710
711
712
713

714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
}
#else  /* ! USE_RECV_BEFORE_SEND_WORKAROUND */
/* Use "do-nothing" macro instead of function when workaround not used */
#define conn_reset_all_postponed_data(c) do {} while(0)
#endif /* ! USE_RECV_BEFORE_SEND_WORKAROUND */


static void conn_shutdown(struct connectdata *conn)
{
  DEBUGASSERT(conn);
  infof(conn->data, "Closing connection %ld\n", conn->connection_id);
  DEBUGASSERT(conn->data);


  /* 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]);
}

static void conn_free(struct connectdata *conn)
{
  DEBUGASSERT(conn);

  Curl_free_idnconverted_hostname(&conn->host);







|


<
|
>


|



|
|



|

|

|

|







711
712
713
714
715
716
717
718
719
720

721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
}
#else  /* ! USE_RECV_BEFORE_SEND_WORKAROUND */
/* Use "do-nothing" macro instead of function when workaround not used */
#define conn_reset_all_postponed_data(c) do {} while(0)
#endif /* ! USE_RECV_BEFORE_SEND_WORKAROUND */


static void conn_shutdown(struct Curl_easy *data, struct connectdata *conn)
{
  DEBUGASSERT(conn);

  DEBUGASSERT(data);
  infof(data, "Closing connection %ld\n", conn->connection_id);

  /* possible left-overs from the async name resolvers */
  Curl_resolver_cancel(data);

  /* close the SSL stuff before we close any sockets since they will/may
     write to the sockets */
  Curl_ssl_close(data, conn, FIRSTSOCKET);
  Curl_ssl_close(data, conn, SECONDARYSOCKET);

  /* close possibly still open sockets */
  if(CURL_SOCKET_BAD != conn->sock[SECONDARYSOCKET])
    Curl_closesocket(data, conn, conn->sock[SECONDARYSOCKET]);
  if(CURL_SOCKET_BAD != conn->sock[FIRSTSOCKET])
    Curl_closesocket(data, conn, conn->sock[FIRSTSOCKET]);
  if(CURL_SOCKET_BAD != conn->tempsock[0])
    Curl_closesocket(data, conn, conn->tempsock[0]);
  if(CURL_SOCKET_BAD != conn->tempsock[1])
    Curl_closesocket(data, conn, conn->tempsock[1]);
}

static void conn_free(struct connectdata *conn)
{
  DEBUGASSERT(conn);

  Curl_free_idnconverted_hostname(&conn->host);
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833




834
835
836
837
838




839
840
841
842
843
844
845

  /* Cleanup NTLM connection-related data */
  Curl_http_auth_cleanup_ntlm(conn);

  /* Cleanup NEGOTIATE connection-related data */
  Curl_http_auth_cleanup_negotiate(conn);

  /* the protocol specific disconnect handler and conn_shutdown need a transfer
     for the connection! */
  conn->data = data;

  if(conn->bits.connect_only)
    /* treat the connection as dead in CONNECT_ONLY situations */
    dead_connection = TRUE;





  if(conn->handler->disconnect)
    /* This is set if protocol-specific cleanups should be made */
    conn->handler->disconnect(conn, dead_connection);

  conn_shutdown(conn);




  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







<
<
<
<




>
>
>
>


|

|
>
>
>
>







828
829
830
831
832
833
834




835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858

  /* Cleanup NTLM connection-related data */
  Curl_http_auth_cleanup_ntlm(conn);

  /* Cleanup NEGOTIATE connection-related data */
  Curl_http_auth_cleanup_negotiate(conn);





  if(conn->bits.connect_only)
    /* treat the connection as dead in CONNECT_ONLY situations */
    dead_connection = TRUE;

  /* temporarily attach the connection to this transfer handle for the
     disonnect and shutdown */
  Curl_attach_connnection(data, conn);

  if(conn->handler->disconnect)
    /* This is set if protocol-specific cleanups should be made */
    conn->handler->disconnect(data, conn, dead_connection);

  conn_shutdown(data, conn);

  /* detach it again */
  Curl_detach_connnection(data);

  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
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966

967
968
969
970
971
972
973



974
975
976
977



978
979
980
981
982
983
984
/* A connection has to have been idle for a shorter time than 'maxage_conn' to
   be subject for reuse. The success rate is just too low after this. */

static bool conn_maxage(struct Curl_easy *data,
                        struct connectdata *conn,
                        struct curltime now)
{
  if(!conn->data) {
    timediff_t idletime = Curl_timediff(now, conn->lastused);
    idletime /= 1000; /* integer seconds is fine */

    if(idletime > data->set.maxage_conn) {
      infof(data, "Too old connection (%ld seconds), disconnect it\n",
            idletime);
      return TRUE;
    }
  }
  return FALSE;
}

/*
 * This function checks if the given connection is dead and extracts it from
 * the connection cache if so.
 *
 * When this is called as a Curl_conncache_foreach() callback, the connection
 * cache lock is held!
 *
 * Returns TRUE if the connection was dead and extracted.
 */
static bool extract_if_dead(struct connectdata *conn,
                            struct Curl_easy *data)
{
  if(!CONN_INUSE(conn) && !conn->data) {
    /* The check for a dead socket makes sense only if the connection isn't in
       use */
    bool dead;
    struct curltime now = Curl_now();
    if(conn_maxage(data, conn, now)) {

      dead = TRUE;
    }
    else if(conn->handler->connection_check) {
      /* The protocol has a special method for checking the state of the
         connection. Use it to check if the connection is dead. */
      unsigned int state;
      struct Curl_easy *olddata = conn->data;



      conn->data = data; /* use this transfer for now */
      state = conn->handler->connection_check(conn, CONNCHECK_ISDEAD);
      conn->data = olddata;
      dead = (state & CONNRESULT_DEAD);



    }
    else {
      /* Use the general method for determining the death of a connection */
      dead = SocketIsDead(conn->sock[FIRSTSOCKET]);
    }

    if(dead) {







<
|
|

|
|
|
|
<
















|





>






|
>
>
>
|
|
<

>
>
>







942
943
944
945
946
947
948

949
950
951
952
953
954
955

956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990

991
992
993
994
995
996
997
998
999
1000
1001
/* A connection has to have been idle for a shorter time than 'maxage_conn' to
   be subject for reuse. The success rate is just too low after this. */

static bool conn_maxage(struct Curl_easy *data,
                        struct connectdata *conn,
                        struct curltime now)
{

  timediff_t idletime = Curl_timediff(now, conn->lastused);
  idletime /= 1000; /* integer seconds is fine */

  if(idletime > data->set.maxage_conn) {
    infof(data, "Too old connection (%ld seconds), disconnect it\n",
          idletime);
    return TRUE;

  }
  return FALSE;
}

/*
 * This function checks if the given connection is dead and extracts it from
 * the connection cache if so.
 *
 * When this is called as a Curl_conncache_foreach() callback, the connection
 * cache lock is held!
 *
 * Returns TRUE if the connection was dead and extracted.
 */
static bool extract_if_dead(struct connectdata *conn,
                            struct Curl_easy *data)
{
  if(!CONN_INUSE(conn)) {
    /* The check for a dead socket makes sense only if the connection isn't in
       use */
    bool dead;
    struct curltime now = Curl_now();
    if(conn_maxage(data, conn, now)) {
      /* avoid check if already too old */
      dead = TRUE;
    }
    else if(conn->handler->connection_check) {
      /* The protocol has a special method for checking the state of the
         connection. Use it to check if the connection is dead. */
      unsigned int state;

      /* briefly attach the connection to this transfer for the purpose of
         checking it */
      Curl_attach_connnection(data, conn);
      conn->data = data; /* find the way back if necessary */
      state = conn->handler->connection_check(data, conn, CONNCHECK_ISDEAD);

      dead = (state & CONNRESULT_DEAD);
      /* detach the connection again */
      Curl_detach_connnection(data);
      conn->data = NULL; /* clear it again */
    }
    else {
      /* Use the general method for determining the death of a connection */
      dead = SocketIsDead(conn->sock[FIRSTSOCKET]);
    }

    if(dead) {
995
996
997
998
999
1000
1001
1002

1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016


1017
1018
1019
1020
1021
1022

1023
1024
1025
1026
1027
1028
1029
  struct connectdata *extracted;
};

/*
 * Wrapper to use extract_if_dead() function in Curl_conncache_foreach()
 *
 */
static int call_extract_if_dead(struct connectdata *conn, void *param)

{
  struct prunedead *p = (struct prunedead *)param;
  if(extract_if_dead(conn, p->data)) {
    /* stop the iteration here, pass back the connection that was extracted */
    p->extracted = conn;
    return 1;
  }
  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 Curl_easy *data)
{
  struct curltime now = Curl_now();
  timediff_t elapsed;


  CONNCACHE_LOCK(data);
  elapsed =
    Curl_timediff(now, data->state.conn_cache->last_cleanup);
  CONNCACHE_UNLOCK(data);

  if(elapsed >= 1000L) {
    struct prunedead prune;







|
>


|









|
<
>
>






>







1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033

1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
  struct connectdata *extracted;
};

/*
 * Wrapper to use extract_if_dead() function in Curl_conncache_foreach()
 *
 */
static int call_extract_if_dead(struct Curl_easy *data,
                                struct connectdata *conn, void *param)
{
  struct prunedead *p = (struct prunedead *)param;
  if(extract_if_dead(conn, data)) {
    /* stop the iteration here, pass back the connection that was extracted */
    p->extracted = conn;
    return 1;
  }
  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.

 *
 * When called, this transfer has no connection attached.
 */
static void prune_dead_connections(struct Curl_easy *data)
{
  struct curltime now = Curl_now();
  timediff_t elapsed;

  DEBUGASSERT(!data->conn); /* no connection */
  CONNCACHE_LOCK(data);
  elapsed =
    Curl_timediff(now, data->state.conn_cache->last_cleanup);
  CONNCACHE_UNLOCK(data);

  if(elapsed >= 1000L) {
    struct prunedead prune;
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
#endif

  *force_reuse = FALSE;
  *waitpipe = FALSE;

  /* Look up the bundle with all the connections to this particular host.
     Locks the connection cache, beware of early returns! */
  bundle = Curl_conncache_find_bundle(needle, data->state.conn_cache,
                                      &hostbundle);
  if(bundle) {
    /* Max pipe length is zero (unlimited) for multiplexed connections */
    struct Curl_llist_element *curr;

    infof(data, "Found bundle for host %s: %p [%s]\n",
          hostbundle, (void *)bundle, (bundle->multiuse == BUNDLE_MULTIPLEX ?







|







1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
#endif

  *force_reuse = FALSE;
  *waitpipe = FALSE;

  /* Look up the bundle with all the connections to this particular host.
     Locks the connection cache, beware of early returns! */
  bundle = Curl_conncache_find_bundle(data, needle, data->state.conn_cache,
                                      &hostbundle);
  if(bundle) {
    /* Max pipe length is zero (unlimited) for multiplexed connections */
    struct Curl_llist_element *curr;

    infof(data, "Found bundle for host %s: %p [%s]\n",
          hostbundle, (void *)bundle, (bundle->multiuse == BUNDLE_MULTIPLEX ?
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
        (void)Curl_disconnect(data, check, TRUE);
        continue;
      }

      if(bundle->multiuse == BUNDLE_MULTIPLEX)
        multiplexed = CONN_INUSE(check);

      if(canmultiplex) {
        ;
      }
      else {
        if(multiplexed) {
          /* 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;
          }
        }








|
<
<
<







|

|







1164
1165
1166
1167
1168
1169
1170
1171



1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
        (void)Curl_disconnect(data, check, TRUE);
        continue;
      }

      if(bundle->multiuse == BUNDLE_MULTIPLEX)
        multiplexed = CONN_INUSE(check);

      if(!canmultiplex) {



        if(multiplexed) {
          /* can only happen within multi handles, and means that another easy
             handle is using this connection */
          continue;
        }

        if(Curl_resolver_asynch()) {
          /* primary_ip[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->primary_ip[0]) {
            infof(data,
                  "Connection #%ld is still name resolving, can't reuse\n",
                  check->connection_id);
            continue;
          }
        }

1459
1460
1461
1462
1463
1464
1465
1466

1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
  return FALSE; /* no matching connecting exists */
}

/*
 * verboseconnect() displays verbose information after a connect
 */
#ifndef CURL_DISABLE_VERBOSE_STRINGS
void Curl_verboseconnect(struct connectdata *conn)

{
  if(conn->data->set.verbose)
    infof(conn->data, "Connected to %s (%s) port %ld (#%ld)\n",
#ifndef CURL_DISABLE_PROXY
          conn->bits.socksproxy ? conn->socks_proxy.host.dispname :
          conn->bits.httpproxy ? conn->http_proxy.host.dispname :
#endif
          conn->bits.conn_to_host ? conn->conn_to_host.dispname :
          conn->host.dispname,
          conn->ip_addr_str, conn->port, conn->connection_id);
}
#endif

/*
 * Helpers for IDNA conversions.
 */
bool Curl_is_ASCII_name(const char *hostname)







|
>

|
|






|







1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
  return FALSE; /* no matching connecting exists */
}

/*
 * verboseconnect() displays verbose information after a connect
 */
#ifndef CURL_DISABLE_VERBOSE_STRINGS
void Curl_verboseconnect(struct Curl_easy *data,
                         struct connectdata *conn)
{
  if(data->set.verbose)
    infof(data, "Connected to %s (%s) port %ld (#%ld)\n",
#ifndef CURL_DISABLE_PROXY
          conn->bits.socksproxy ? conn->socks_proxy.host.dispname :
          conn->bits.httpproxy ? conn->http_proxy.host.dispname :
#endif
          conn->bits.conn_to_host ? conn->conn_to_host.dispname :
          conn->host.dispname,
          conn->primary_ip, conn->port, conn->connection_id);
}
#endif

/*
 * Helpers for IDNA conversions.
 */
bool Curl_is_ASCII_name(const char *hostname)
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543





1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
  if(len && (host->name[len-1] == '.'))
    host->name[len-1] = 0;
}

/*
 * Perform any necessary IDN conversion of hostname
 */
CURLcode Curl_idnconvert_hostname(struct connectdata *conn,
                                  struct hostname *host)
{
  struct Curl_easy *data = conn->data;

#ifndef USE_LIBIDN2
  (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;

  /* Check name for non-ASCII and convert hostname to ACE form if we can */
  if(!Curl_is_ASCII_name(host->name)) {
#ifdef USE_LIBIDN2
    if(idn2_check_version(IDN2_VERSION)) {
      char *ace_hostname = NULL;
#if IDN2_VERSION_NUMBER >= 0x00140000
      /* IDN2_NFC_INPUT: Normalize input string using normalization form C.
         IDN2_NONTRANSITIONAL: Perform Unicode TR46 non-transitional
         processing. */
      int flags = IDN2_NFC_INPUT | IDN2_NONTRANSITIONAL;
#else
      int flags = IDN2_NFC_INPUT;
#endif
      int rc = idn2_lookup_ul((const char *)host->name, &ace_hostname, flags);





      if(rc == IDN2_OK) {
        host->encalloc = (char *)ace_hostname;
        /* change the name pointer to point to the encoded hostname */
        host->name = host->encalloc;
      }
      else {
        failf(data, "Failed to convert %s to ACE; %s\n", host->name,
              idn2_strerror(rc));
        return CURLE_URL_MALFORMAT;
      }
    }
#elif defined(USE_WIN32_IDN)
    char *ace_hostname = NULL;

    if(curl_win32_idn_to_ascii(host->name, &ace_hostname)) {
      host->encalloc = ace_hostname;
      /* change the name pointer to point to the encoded hostname */
      host->name = host->encalloc;
    }
    else {
      char buffer[STRERROR_LEN];
      failf(data, "Failed to convert %s to ACE; %s\n", host->name,
            Curl_winapi_strerror(GetLastError(), buffer, sizeof(buffer)));
      return CURLE_URL_MALFORMAT;
    }
#else
    infof(data, "IDN support not present, can't parse Unicode domains\n");
#endif
  }







|


<
<


|

|



















>
>
>
>
>






|














|







1526
1527
1528
1529
1530
1531
1532
1533
1534
1535


1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
  if(len && (host->name[len-1] == '.'))
    host->name[len-1] = 0;
}

/*
 * Perform any necessary IDN conversion of hostname
 */
CURLcode Curl_idnconvert_hostname(struct Curl_easy *data,
                                  struct hostname *host)
{


#ifndef USE_LIBIDN2
  (void)data;
  (void)data;
#elif defined(CURL_DISABLE_VERBOSE_STRINGS)
  (void)data;
#endif

  /* set the name we use to display the host name */
  host->dispname = host->name;

  /* Check name for non-ASCII and convert hostname to ACE form if we can */
  if(!Curl_is_ASCII_name(host->name)) {
#ifdef USE_LIBIDN2
    if(idn2_check_version(IDN2_VERSION)) {
      char *ace_hostname = NULL;
#if IDN2_VERSION_NUMBER >= 0x00140000
      /* IDN2_NFC_INPUT: Normalize input string using normalization form C.
         IDN2_NONTRANSITIONAL: Perform Unicode TR46 non-transitional
         processing. */
      int flags = IDN2_NFC_INPUT | IDN2_NONTRANSITIONAL;
#else
      int flags = IDN2_NFC_INPUT;
#endif
      int rc = idn2_lookup_ul((const char *)host->name, &ace_hostname, flags);
      if(rc != IDN2_OK)
        /* fallback to TR46 Transitional mode for better IDNA2003
           compatibility */
        rc = idn2_lookup_ul((const char *)host->name, &ace_hostname,
                            IDN2_TRANSITIONAL);
      if(rc == IDN2_OK) {
        host->encalloc = (char *)ace_hostname;
        /* change the name pointer to point to the encoded hostname */
        host->name = host->encalloc;
      }
      else {
        failf(data, "Failed to convert %s to ACE; %s", host->name,
              idn2_strerror(rc));
        return CURLE_URL_MALFORMAT;
      }
    }
#elif defined(USE_WIN32_IDN)
    char *ace_hostname = NULL;

    if(curl_win32_idn_to_ascii(host->name, &ace_hostname)) {
      host->encalloc = ace_hostname;
      /* change the name pointer to point to the encoded hostname */
      host->name = host->encalloc;
    }
    else {
      char buffer[STRERROR_LEN];
      failf(data, "Failed to convert %s to ACE; %s", host->name,
            Curl_winapi_strerror(GetLastError(), buffer, sizeof(buffer)));
      return CURLE_URL_MALFORMAT;
    }
#else
    infof(data, "IDN support not present, can't parse Unicode domains\n");
#endif
  }
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665

  /* Store creation time to help future close decision making */
  conn->created = Curl_now();

  /* Store current time to give a baseline to keepalive connection times. */
  conn->keepalive = Curl_now();

  /* Store off the configured connection upkeep time. */
  conn->upkeep_interval_ms = data->set.upkeep_interval_ms;

  conn->data = data; /* Setup the association between this connection
                        and the Curl_easy */

#ifndef CURL_DISABLE_PROXY
  conn->http_proxy.proxytype = data->set.proxytype;
  conn->socks_proxy.proxytype = CURLPROXY_SOCKS4;








<
<
<







1670
1671
1672
1673
1674
1675
1676



1677
1678
1679
1680
1681
1682
1683

  /* Store creation time to help future close decision making */
  conn->created = Curl_now();

  /* Store current time to give a baseline to keepalive connection times. */
  conn->keepalive = Curl_now();




  conn->data = data; /* Setup the association between this connection
                        and the Curl_easy */

#ifndef CURL_DISABLE_PROXY
  conn->http_proxy.proxytype = data->set.proxytype;
  conn->socks_proxy.proxytype = CURLPROXY_SOCKS4;

1807
1808
1809
1810
1811
1812
1813
1814

1815
1816
1817
1818
1819



1820
1821
1822
1823
1824
1825
1826
}

/*
 * If the URL was set with an IPv6 numerical address with a zone id part, set
 * the scope_id based on that!
 */

static void zonefrom_url(CURLU *uh, struct connectdata *conn)

{
  char *zoneid;
  CURLUcode uc;

  uc = curl_url_get(uh, CURLUPART_ZONEID, &zoneid, 0);




  if(!uc && zoneid) {
    char *endp;
    unsigned long scope = strtoul(zoneid, &endp, 10);
    if(!*endp && (scope < UINT_MAX))
      /* A plain number, use it directly as a scope id. */
      conn->scope_id = (unsigned int)scope;







|
>


<
<
|
>
>
>







1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835


1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
}

/*
 * If the URL was set with an IPv6 numerical address with a zone id part, set
 * the scope_id based on that!
 */

static void zonefrom_url(CURLU *uh, struct Curl_easy *data,
                         struct connectdata *conn)
{
  char *zoneid;


  CURLUcode uc = curl_url_get(uh, CURLUPART_ZONEID, &zoneid, 0);
#ifdef CURL_DISABLE_VERBOSE_STRINGS
  (void)data;
#endif

  if(!uc && zoneid) {
    char *endp;
    unsigned long scope = strtoul(zoneid, &endp, 10);
    if(!*endp && (scope < UINT_MAX))
      /* A plain number, use it directly as a scope id. */
      conn->scope_id = (unsigned int)scope;
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
      unsigned int scopeidx = 0;
#if defined(WIN32)
      scopeidx = Curl_if_nametoindex(zoneid);
#else
      scopeidx = if_nametoindex(zoneid);
#endif
      if(!scopeidx)
        infof(conn->data, "Invalid zoneid: %s; %s\n", zoneid,
              strerror(errno));
      else
        conn->scope_id = scopeidx;
    }
#endif /* HAVE_IF_NAMETOINDEX || WIN32 */

    free(zoneid);







|







1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
      unsigned int scopeidx = 0;
#if defined(WIN32)
      scopeidx = Curl_if_nametoindex(zoneid);
#else
      scopeidx = if_nametoindex(zoneid);
#endif
      if(!scopeidx)
        infof(data, "Invalid zoneid: %s; %s\n", zoneid,
              strerror(errno));
      else
        conn->scope_id = scopeidx;
    }
#endif /* HAVE_IF_NAMETOINDEX || WIN32 */

    free(zoneid);
1999
2000
2001
2002
2003
2004
2005
2006


2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
                    CURLU_DEFAULT_PORT);
  if(uc) {
    if(!strcasecompare("file", data->state.up.scheme))
      return CURLE_OUT_OF_MEMORY;
  }
  else {
    unsigned long port = strtoul(data->state.up.port, NULL, 10);
    conn->port = conn->remote_port = curlx_ultous(port);


  }

  (void)curl_url_get(uh, CURLUPART_QUERY, &data->state.up.query, 0);

  hostname = data->state.up.hostname;
  if(hostname && hostname[0] == '[') {
    /* This looks like an IPv6 address literal. See if there is an address
       scope. */
    size_t hlen;
    conn->bits.ipv6_ip = TRUE;
    /* cut off the brackets! */
    hostname++;
    hlen = strlen(hostname);
    hostname[hlen - 1] = 0;

    zonefrom_url(uh, conn);
  }

  /* make sure the connect struct gets its own copy of the host name */
  conn->host.rawalloc = strdup(hostname ? hostname : "");
  if(!conn->host.rawalloc)
    return CURLE_OUT_OF_MEMORY;
  conn->host.name = conn->host.rawalloc;







|
>
>















|







2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
                    CURLU_DEFAULT_PORT);
  if(uc) {
    if(!strcasecompare("file", data->state.up.scheme))
      return CURLE_OUT_OF_MEMORY;
  }
  else {
    unsigned long port = strtoul(data->state.up.port, NULL, 10);
    conn->port = conn->remote_port =
      (data->set.use_port && data->state.allow_port) ?
      (int)data->set.use_port : curlx_ultous(port);
  }

  (void)curl_url_get(uh, CURLUPART_QUERY, &data->state.up.query, 0);

  hostname = data->state.up.hostname;
  if(hostname && hostname[0] == '[') {
    /* This looks like an IPv6 address literal. See if there is an address
       scope. */
    size_t hlen;
    conn->bits.ipv6_ip = TRUE;
    /* cut off the brackets! */
    hostname++;
    hlen = strlen(hostname);
    hostname[hlen - 1] = 0;

    zonefrom_url(uh, data, conn);
  }

  /* make sure the connect struct gets its own copy of the host name */
  conn->host.rawalloc = strdup(hostname ? hostname : "");
  if(!conn->host.rawalloc)
    return CURLE_OUT_OF_MEMORY;
  conn->host.name = conn->host.rawalloc;
2073
2074
2075
2076
2077
2078
2079
2080

2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
 *
 * Setup connection internals specific to the requested protocol in the
 * Curl_easy. 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;

  /* 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. */
  }








|
>








|







2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
 *
 * Setup connection internals specific to the requested protocol in the
 * Curl_easy. 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 Curl_easy *data,
                                           struct connectdata *conn)
{
  const struct Curl_handler *p;
  CURLcode result;

  /* Perform setup complement if some. */
  p = conn->handler;

  if(p->setup_connection) {
    result = (*p->setup_connection)(data, conn);

    if(result)
      return result;

    p = conn->handler;              /* May have changed. */
  }

2109
2110
2111
2112
2113
2114
2115

2116
2117

2118
2119
2120
2121
2122
2123
2124

void Curl_free_request_state(struct Curl_easy *data)
{
  Curl_safefree(data->req.p.http);
  Curl_safefree(data->req.newurl);

#ifndef CURL_DISABLE_DOH

  Curl_close(&data->req.doh.probe[0].easy);
  Curl_close(&data->req.doh.probe[1].easy);

#endif
}


#ifndef CURL_DISABLE_PROXY
/****************************************************************
* Checks if the host is in the noproxy list. returns true if it matches







>
|
|
>







2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149

void Curl_free_request_state(struct Curl_easy *data)
{
  Curl_safefree(data->req.p.http);
  Curl_safefree(data->req.newurl);

#ifndef CURL_DISABLE_DOH
  if(data->req.doh) {
    Curl_close(&data->req.doh->probe[0].easy);
    Curl_close(&data->req.doh->probe[1].easy);
  }
#endif
}


#ifndef CURL_DISABLE_PROXY
/****************************************************************
* Checks if the host is in the noproxy list. returns true if it matches
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
        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) {







|







2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
        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 behavior, 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) {
2200
2201
2202
2203
2204
2205
2206
2207

2208
2209
2210
2211
2212
2213
2214

#ifndef CURL_DISABLE_HTTP
/****************************************************************
* 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;

  /* 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/







|
>







2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240

#ifndef CURL_DISABLE_HTTP
/****************************************************************
* 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 Curl_easy *data,
                          struct connectdata *conn)
{
  char *proxy = NULL;

  /* 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/
2225
2226
2227
2228
2229
2230
2231



2232
2233
2234
2235
2236
2237
2238
   * For compatibility, the all-uppercase versions of these variables are
   * checked if the lowercase versions don't exist.
   */
  char proxy_env[128];
  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");







>
>
>







2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
   * For compatibility, the all-uppercase versions of these variables are
   * checked if the lowercase versions don't exist.
   */
  char proxy_env[128];
  const char *protop = conn->handler->scheme;
  char *envp = proxy_env;
  char *prox;
#ifdef CURL_DISABLE_VERBOSE_STRINGS
  (void)data;
#endif

  /* Now, build <protocol>_proxy and check for such a one to use */
  while(*protop)
    *envp++ = (char)tolower((int)*protop++);

  /* append _proxy */
  strcpy(envp, "_proxy");
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
    proxy = curl_getenv(envp); /* default proxy to use */
    if(!proxy) {
      envp = (char *)"ALL_PROXY";
      proxy = curl_getenv(envp);
    }
  }
  if(proxy)
    infof(conn->data, "Uses proxy env variable %s == '%s'\n", envp, proxy);

  return proxy;
}
#endif /* CURL_DISABLE_HTTP */

/*
 * 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.
 */
static CURLcode parse_proxy(struct Curl_easy *data,
                            struct connectdata *conn, char *proxy,
                            curl_proxytype proxytype)
{
  char *portptr = NULL;
  long port = -1;
  char *proxyuser = NULL;
  char *proxypasswd = NULL;
  char *host;
  bool sockstype;
  CURLUcode uc;
  struct proxy_info *proxyinfo;
  CURLU *uhp = curl_url();







|















|







2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
    proxy = curl_getenv(envp); /* default proxy to use */
    if(!proxy) {
      envp = (char *)"ALL_PROXY";
      proxy = curl_getenv(envp);
    }
  }
  if(proxy)
    infof(data, "Uses proxy env variable %s == '%s'\n", envp, proxy);

  return proxy;
}
#endif /* CURL_DISABLE_HTTP */

/*
 * 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.
 */
static CURLcode parse_proxy(struct Curl_easy *data,
                            struct connectdata *conn, char *proxy,
                            curl_proxytype proxytype)
{
  char *portptr = NULL;
  int port = -1;
  char *proxyuser = NULL;
  char *proxypasswd = NULL;
  char *host;
  bool sockstype;
  CURLUcode uc;
  struct proxy_info *proxyinfo;
  CURLU *uhp = curl_url();
2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
2384
2385
2386
2387
2388
2389
2390
2391
2392
2393
    proxyinfo->passwd = proxypasswd;
    conn->bits.proxy_user_passwd = TRUE; /* enable it */
  }

  curl_url_get(uhp, CURLUPART_PORT, &portptr, 0);

  if(portptr) {
    port = strtol(portptr, NULL, 10);
    free(portptr);
  }
  else {
    if(data->set.proxyport)
      /* None given in the proxy string, then get the default one if it is
         given */
      port = data->set.proxyport;
    else {
      if(proxytype == CURLPROXY_HTTPS)
        port = CURL_DEFAULT_HTTPS_PROXY_PORT;
      else
        port = CURL_DEFAULT_PROXY_PORT;
    }
  }







|






|







2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
    proxyinfo->passwd = proxypasswd;
    conn->bits.proxy_user_passwd = TRUE; /* enable it */
  }

  curl_url_get(uhp, CURLUPART_PORT, &portptr, 0);

  if(portptr) {
    port = (int)strtol(portptr, NULL, 10);
    free(portptr);
  }
  else {
    if(data->set.proxyport)
      /* None given in the proxy string, then get the default one if it is
         given */
      port = (int)data->set.proxyport;
    else {
      if(proxytype == CURLPROXY_HTTPS)
        port = CURL_DEFAULT_HTTPS_PROXY_PORT;
      else
        port = CURL_DEFAULT_PROXY_PORT;
    }
  }
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
  Curl_safefree(proxyinfo->host.rawalloc);
  proxyinfo->host.rawalloc = host;
  if(host[0] == '[') {
    /* this is a numerical IPv6, strip off the brackets */
    size_t len = strlen(host);
    host[len-1] = 0; /* clear the trailing bracket */
    host++;
    zonefrom_url(uhp, conn);
  }
  proxyinfo->host.name = host;

  error:
  free(scheme);
  curl_url_cleanup(uhp);
  return result;







|







2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
  Curl_safefree(proxyinfo->host.rawalloc);
  proxyinfo->host.rawalloc = host;
  if(host[0] == '[') {
    /* this is a numerical IPv6, strip off the brackets */
    size_t len = strlen(host);
    host[len-1] = 0; /* clear the trailing bracket */
    host++;
    zonefrom_url(uhp, data, conn);
  }
  proxyinfo->host.name = host;

  error:
  free(scheme);
  curl_url_cleanup(uhp);
  return result;
2439
2440
2441
2442
2443
2444
2445
2446

2447
2448
2449
2450
2451
2452
2453
2454
2455
2456
2457
2458
2459
    result = Curl_urldecode(data, proxypasswd, 0, &conn->http_proxy.passwd,
                            NULL, REJECT_ZERO);
  return result;
}

/* create_conn helper to parse and init proxy values. to be called after unix
   socket init but before any proxy vars are evaluated. */
static CURLcode create_conn_helper_init_proxy(struct connectdata *conn)

{
  char *proxy = NULL;
  char *socksproxy = NULL;
  char *no_proxy = NULL;
  CURLcode result = CURLE_OK;
  struct Curl_easy *data = conn->data;

  /*************************************************************
   * Extract the user and password from the authentication string
   *************************************************************/
  if(conn->bits.proxy_user_passwd) {
    result = parse_proxy_auth(data, conn);
    if(result)







|
>





<







2468
2469
2470
2471
2472
2473
2474
2475
2476
2477
2478
2479
2480
2481

2482
2483
2484
2485
2486
2487
2488
    result = Curl_urldecode(data, proxypasswd, 0, &conn->http_proxy.passwd,
                            NULL, REJECT_ZERO);
  return result;
}

/* create_conn helper to parse and init proxy values. to be called after unix
   socket init but before any proxy vars are evaluated. */
static CURLcode create_conn_helper_init_proxy(struct Curl_easy *data,
                                              struct connectdata *conn)
{
  char *proxy = NULL;
  char *socksproxy = NULL;
  char *no_proxy = NULL;
  CURLcode result = CURLE_OK;


  /*************************************************************
   * Extract the user and password from the authentication string
   *************************************************************/
  if(conn->bits.proxy_user_passwd) {
    result = parse_proxy_auth(data, conn);
    if(result)
2487
2488
2489
2490
2491
2492
2493
2494
2495
2496
2497
2498
2499
2500
2501
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
    const char *p = "no_proxy";
    no_proxy = curl_getenv(p);
    if(!no_proxy) {
      p = "NO_PROXY";
      no_proxy = curl_getenv(p);
    }
    if(no_proxy) {
      infof(conn->data, "Uses proxy env variable %s == '%s'\n", p, no_proxy);
    }
  }

  if(check_noproxy(conn->host.name, data->set.str[STRING_NOPROXY] ?
      data->set.str[STRING_NOPROXY] : no_proxy)) {
    Curl_safefree(proxy);
    Curl_safefree(socksproxy);
  }
#ifndef CURL_DISABLE_HTTP
  else if(!proxy && !socksproxy)
    /* if the host is not in the noproxy list, detect proxy. */
    proxy = detect_proxy(conn);
#endif /* CURL_DISABLE_HTTP */

  Curl_safefree(no_proxy);

#ifdef USE_UNIX_SOCKETS
  /* For the time being do not mix proxy and unix domain sockets. See #1274 */
  if(proxy && conn->unix_domain_socket) {







|











|







2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
2539
2540
2541
2542
    const char *p = "no_proxy";
    no_proxy = curl_getenv(p);
    if(!no_proxy) {
      p = "NO_PROXY";
      no_proxy = curl_getenv(p);
    }
    if(no_proxy) {
      infof(data, "Uses proxy env variable %s == '%s'\n", p, no_proxy);
    }
  }

  if(check_noproxy(conn->host.name, data->set.str[STRING_NOPROXY] ?
      data->set.str[STRING_NOPROXY] : no_proxy)) {
    Curl_safefree(proxy);
    Curl_safefree(socksproxy);
  }
#ifndef CURL_DISABLE_HTTP
  else if(!proxy && !socksproxy)
    /* if the host is not in the noproxy list, detect proxy. */
    proxy = detect_proxy(data, conn);
#endif /* CURL_DISABLE_HTTP */

  Curl_safefree(no_proxy);

#ifdef USE_UNIX_SOCKETS
  /* For the time being do not mix proxy and unix domain sockets. See #1274 */
  if(proxy && conn->unix_domain_socket) {
3273
3274
3275
3276
3277
3278
3279
3280
3281
3282
3283
3284
3285
3286
3287
      else
        conn->port = conn->remote_port;

      /* Resolve target host right on */
      conn->hostname_resolve = strdup(connhost->name);
      if(!conn->hostname_resolve)
        return CURLE_OUT_OF_MEMORY;
      rc = Curl_resolv_timeout(conn, conn->hostname_resolve, (int)conn->port,
                               &hostaddr, timeout_ms);
      if(rc == CURLRESOLV_PENDING)
        *async = TRUE;

      else if(rc == CURLRESOLV_TIMEDOUT)
        result = CURLE_OPERATION_TIMEDOUT;








|







3302
3303
3304
3305
3306
3307
3308
3309
3310
3311
3312
3313
3314
3315
3316
      else
        conn->port = conn->remote_port;

      /* Resolve target host right on */
      conn->hostname_resolve = strdup(connhost->name);
      if(!conn->hostname_resolve)
        return CURLE_OUT_OF_MEMORY;
      rc = Curl_resolv_timeout(data, conn->hostname_resolve, (int)conn->port,
                               &hostaddr, timeout_ms);
      if(rc == CURLRESOLV_PENDING)
        *async = TRUE;

      else if(rc == CURLRESOLV_TIMEDOUT)
        result = CURLE_OPERATION_TIMEDOUT;

3298
3299
3300
3301
3302
3303
3304
3305
3306
3307
3308
3309
3310
3311
3312
      struct hostname * const host = conn->bits.socksproxy ?
        &conn->socks_proxy.host : &conn->http_proxy.host;

      /* resolve proxy */
      conn->hostname_resolve = strdup(host->name);
      if(!conn->hostname_resolve)
        return CURLE_OUT_OF_MEMORY;
      rc = Curl_resolv_timeout(conn, conn->hostname_resolve, (int)conn->port,
                               &hostaddr, timeout_ms);

      if(rc == CURLRESOLV_PENDING)
        *async = TRUE;

      else if(rc == CURLRESOLV_TIMEDOUT)
        result = CURLE_OPERATION_TIMEDOUT;







|







3327
3328
3329
3330
3331
3332
3333
3334
3335
3336
3337
3338
3339
3340
3341
      struct hostname * const host = conn->bits.socksproxy ?
        &conn->socks_proxy.host : &conn->http_proxy.host;

      /* resolve proxy */
      conn->hostname_resolve = strdup(host->name);
      if(!conn->hostname_resolve)
        return CURLE_OUT_OF_MEMORY;
      rc = Curl_resolv_timeout(data, conn->hostname_resolve, (int)conn->port,
                               &hostaddr, timeout_ms);

      if(rc == CURLRESOLV_PENDING)
        *async = TRUE;

      else if(rc == CURLRESOLV_TIMEDOUT)
        result = CURLE_OPERATION_TIMEDOUT;
3326
3327
3328
3329
3330
3331
3332
3333

3334
3335





3336
3337
3338
3339
3340
3341
3342
3343
3344
3345
3346
3347
3348
3349
3350
3351
3352
3353
3354
3355
}

/*
 * 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)
{





#ifndef CURL_DISABLE_PROXY
  Curl_free_idnconverted_hostname(&old_conn->http_proxy.host);
  Curl_free_idnconverted_hostname(&old_conn->socks_proxy.host);

  free(old_conn->http_proxy.host.rawalloc);
  free(old_conn->socks_proxy.host.rawalloc);
  Curl_free_primary_ssl_config(&old_conn->proxy_ssl_config);
#endif
  /* free the SSL config struct from this connection struct as this was
     allocated in vain and is targeted for destruction */
  Curl_free_primary_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);







|
>


>
>
>
>
>












|







3355
3356
3357
3358
3359
3360
3361
3362
3363
3364
3365
3366
3367
3368
3369
3370
3371
3372
3373
3374
3375
3376
3377
3378
3379
3380
3381
3382
3383
3384
3385
3386
3387
3388
3389
3390
}

/*
 * 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 Curl_easy *data,
                       struct connectdata *old_conn,
                       struct connectdata *conn)
{
  /* '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 = -1;
#ifndef CURL_DISABLE_PROXY
  Curl_free_idnconverted_hostname(&old_conn->http_proxy.host);
  Curl_free_idnconverted_hostname(&old_conn->socks_proxy.host);

  free(old_conn->http_proxy.host.rawalloc);
  free(old_conn->socks_proxy.host.rawalloc);
  Curl_free_primary_ssl_config(&old_conn->proxy_ssl_config);
#endif
  /* free the SSL config struct from this connection struct as this was
     allocated in vain and is targeted for destruction */
  Curl_free_primary_ssl_config(&old_conn->ssl_config);

  conn->data = 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);
3395
3396
3397
3398
3399
3400
3401




3402
3403
3404
3405
3406
3407
3408
3409
  conn->remote_port = old_conn->remote_port;
  Curl_safefree(conn->hostname_resolve);

  conn->hostname_resolve = old_conn->hostname_resolve;
  old_conn->hostname_resolve = NULL;

  /* persist connection info in session handle */




  Curl_persistconninfo(conn);

  conn_reset_all_postponed_data(old_conn); /* free buffers */

  /* re-use init */
  conn->bits.reuse = TRUE; /* yes, we're re-using here */

  Curl_safefree(old_conn->user);







>
>
>
>
|







3430
3431
3432
3433
3434
3435
3436
3437
3438
3439
3440
3441
3442
3443
3444
3445
3446
3447
3448
  conn->remote_port = old_conn->remote_port;
  Curl_safefree(conn->hostname_resolve);

  conn->hostname_resolve = old_conn->hostname_resolve;
  old_conn->hostname_resolve = NULL;

  /* persist connection info in session handle */
  if(conn->transport == TRNSPRT_TCP) {
    Curl_conninfo_local(data, conn->sock[FIRSTSOCKET],
                        local_ip, &local_port);
  }
  Curl_persistconninfo(data, conn, local_ip, local_port);

  conn_reset_all_postponed_data(old_conn); /* free buffers */

  /* re-use init */
  conn->bits.reuse = TRUE; /* yes, we're re-using here */

  Curl_safefree(old_conn->user);
3496
3497
3498
3499
3500
3501
3502
3503
3504
3505
3506
3507
3508
3509
3510
    conn->bits.abstract_unix_socket = data->set.abstract_unix_socket;
  }
#endif

  /* After the unix socket init but before the proxy vars are used, parse and
     initialize the proxy vars */
#ifndef CURL_DISABLE_PROXY
  result = create_conn_helper_init_proxy(conn);
  if(result)
    goto out;

  /*************************************************************
   * If the protocol is using SSL and HTTP proxy is used, we set
   * the tunnel_proxy bit.
   *************************************************************/







|







3535
3536
3537
3538
3539
3540
3541
3542
3543
3544
3545
3546
3547
3548
3549
    conn->bits.abstract_unix_socket = data->set.abstract_unix_socket;
  }
#endif

  /* After the unix socket init but before the proxy vars are used, parse and
     initialize the proxy vars */
#ifndef CURL_DISABLE_PROXY
  result = create_conn_helper_init_proxy(data, conn);
  if(result)
    goto out;

  /*************************************************************
   * If the protocol is using SSL and HTTP proxy is used, we set
   * the tunnel_proxy bit.
   *************************************************************/
3537
3538
3539
3540
3541
3542
3543
3544
3545
3546
3547
3548
3549
3550
3551
3552
3553
3554
3555
3556
3557
3558
3559
3560
3561
3562
3563
3564
3565
3566
  result = parse_connect_to_slist(data, conn, data->set.connect_to);
  if(result)
    goto out;

  /*************************************************************
   * IDN-convert the hostnames
   *************************************************************/
  result = Curl_idnconvert_hostname(conn, &conn->host);
  if(result)
    goto out;
  if(conn->bits.conn_to_host) {
    result = Curl_idnconvert_hostname(conn, &conn->conn_to_host);
    if(result)
      goto out;
  }
#ifndef CURL_DISABLE_PROXY
  if(conn->bits.httpproxy) {
    result = Curl_idnconvert_hostname(conn, &conn->http_proxy.host);
    if(result)
      goto out;
  }
  if(conn->bits.socksproxy) {
    result = Curl_idnconvert_hostname(conn, &conn->socks_proxy.host);
    if(result)
      goto out;
  }
#endif

  /*************************************************************
   * Check whether the host and the "connect to host" are equal.







|



|





|




|







3576
3577
3578
3579
3580
3581
3582
3583
3584
3585
3586
3587
3588
3589
3590
3591
3592
3593
3594
3595
3596
3597
3598
3599
3600
3601
3602
3603
3604
3605
  result = parse_connect_to_slist(data, conn, data->set.connect_to);
  if(result)
    goto out;

  /*************************************************************
   * IDN-convert the hostnames
   *************************************************************/
  result = Curl_idnconvert_hostname(data, &conn->host);
  if(result)
    goto out;
  if(conn->bits.conn_to_host) {
    result = Curl_idnconvert_hostname(data, &conn->conn_to_host);
    if(result)
      goto out;
  }
#ifndef CURL_DISABLE_PROXY
  if(conn->bits.httpproxy) {
    result = Curl_idnconvert_hostname(data, &conn->http_proxy.host);
    if(result)
      goto out;
  }
  if(conn->bits.socksproxy) {
    result = Curl_idnconvert_hostname(data, &conn->socks_proxy.host);
    if(result)
      goto out;
  }
#endif

  /*************************************************************
   * Check whether the host and the "connect to host" are equal.
3589
3590
3591
3592
3593
3594
3595
3596
3597
3598
3599
3600
3601
3602
3603
3604
3605
3606
3607
3608
3609
3610
3611
3612
3613
3614
3615
3616
3617
3618
3619
3620
3621
3622
3623
3624
3625
3626
3627
3628
3629
3630
3631
3632
3633
3634
3635
3636
3637
3638
3639
3640
3641
3642
    conn->bits.tunnel_proxy = TRUE;
#endif

  /*************************************************************
   * 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;

  conn->bits.tcp_fastopen = data->set.tcp_fastopen;

  /***********************************************************************
   * 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);
    Curl_persistconninfo(conn);
    result = conn->handler->connect_it(conn, &done);

    /* Setup a "faked" transfer that'll do nothing */
    if(!result) {
      conn->bits.tcpconnect[FIRSTSOCKET] = TRUE; /* we are "connected */

      Curl_attach_connnection(data, conn);
      result = Curl_conncache_add_conn(data->state.conn_cache, conn);
      if(result)
        goto out;

      /*
       * 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(data, -1, -1, FALSE, -1);
    }

    /* since we skip do_init() */
    Curl_init_do(data, conn);







|



















|
|






|










|







3628
3629
3630
3631
3632
3633
3634
3635
3636
3637
3638
3639
3640
3641
3642
3643
3644
3645
3646
3647
3648
3649
3650
3651
3652
3653
3654
3655
3656
3657
3658
3659
3660
3661
3662
3663
3664
3665
3666
3667
3668
3669
3670
3671
3672
3673
3674
3675
3676
3677
3678
3679
3680
3681
    conn->bits.tunnel_proxy = TRUE;
#endif

  /*************************************************************
   * Setup internals depending on protocol. Needs to be done after
   * we figured out what/if proxy to use.
   *************************************************************/
  result = setup_connection_internals(data, 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;

  conn->bits.tcp_fastopen = data->set.tcp_fastopen;

  /***********************************************************************
   * 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);
    Curl_persistconninfo(data, conn, NULL, -1);
    result = conn->handler->connect_it(data, &done);

    /* Setup a "faked" transfer that'll do nothing */
    if(!result) {
      conn->bits.tcpconnect[FIRSTSOCKET] = TRUE; /* we are "connected */

      Curl_attach_connnection(data, conn);
      result = Curl_conncache_add_conn(data);
      if(result)
        goto out;

      /*
       * 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(data, result, FALSE);
        goto out;
      }
      Curl_setup_transfer(data, -1, -1, FALSE, -1);
    }

    /* since we skip do_init() */
    Curl_init_do(data, conn);
3741
3742
3743
3744
3745
3746
3747
3748
3749
3750
3751
3752
3753
3754
3755
3756
3757
3758
3759
3760
     data->set.connect_only)
    reuse = FALSE;
  else
    reuse = ConnectionExists(data, conn, &conn_temp, &force_reuse, &waitpipe);

  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.
     */
    reuse_conn(conn, conn_temp);
#ifdef USE_SSL
    free(conn->ssl_extra);
#endif
    free(conn);          /* we don't need this anymore */
    conn = conn_temp;
    *in_connect = conn;








|
|
|
<

|







3780
3781
3782
3783
3784
3785
3786
3787
3788
3789

3790
3791
3792
3793
3794
3795
3796
3797
3798
     data->set.connect_only)
    reuse = FALSE;
  else
    reuse = ConnectionExists(data, conn, &conn_temp, &force_reuse, &waitpipe);

  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.

     */
    reuse_conn(data, conn, conn_temp);
#ifdef USE_SSL
    free(conn->ssl_extra);
#endif
    free(conn);          /* we don't need this anymore */
    conn = conn_temp;
    *in_connect = conn;

3788
3789
3790
3791
3792
3793
3794
3795

3796
3797
3798
3799
3800
3801
3802
      /* There is a connection that *might* become usable for multiplexing
         "soon", and we wait for that */
      connections_available = FALSE;
    else {
      /* this gets a lock on the conncache */
      const char *bundlehost;
      struct connectbundle *bundle =
        Curl_conncache_find_bundle(conn, data->state.conn_cache, &bundlehost);


      if(max_host_connections > 0 && bundle &&
         (bundle->num_connections >= max_host_connections)) {
        struct connectdata *conn_candidate;

        /* The bundle is full. Extract the oldest connection. */
        conn_candidate = Curl_conncache_extract_bundle(data, bundle);







|
>







3826
3827
3828
3829
3830
3831
3832
3833
3834
3835
3836
3837
3838
3839
3840
3841
      /* There is a connection that *might* become usable for multiplexing
         "soon", and we wait for that */
      connections_available = FALSE;
    else {
      /* this gets a lock on the conncache */
      const char *bundlehost;
      struct connectbundle *bundle =
        Curl_conncache_find_bundle(data, conn, data->state.conn_cache,
                                   &bundlehost);

      if(max_host_connections > 0 && bundle &&
         (bundle->num_connections >= max_host_connections)) {
        struct connectdata *conn_candidate;

        /* The bundle is full. Extract the oldest connection. */
        conn_candidate = Curl_conncache_extract_bundle(data, bundle);
3841
3842
3843
3844
3845
3846
3847
3848
3849
3850
3851
3852
3853
3854
3855
3856
    }
    else {
      /*
       * This is a brand new connection, so let's store it in the connection
       * cache of ours!
       */
      Curl_attach_connnection(data, conn);

      result = Curl_conncache_add_conn(data->state.conn_cache, conn);
      if(result)
        goto out;
    }

#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







<
|







3880
3881
3882
3883
3884
3885
3886

3887
3888
3889
3890
3891
3892
3893
3894
    }
    else {
      /*
       * This is a brand new connection, so let's store it in the connection
       * cache of ours!
       */
      Curl_attach_connnection(data, conn);

      result = Curl_conncache_add_conn(data);
      if(result)
        goto out;
    }

#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
3914
3915
3916
3917
3918
3919
3920
3921
3922
3923
3924
3925
3926
3927
3928
3929
3930
3931
3932
3933
3934
3935
3936
3937
3938
3939
3940
3941
3942
3943
3944
3945
3946
3947
3948
3949
3950
3951
3952
3953
3954
3955
3956
3957
3958
3959
3960
3961
3962
3963
3964
3965
3966
3967
3968
3969
3970
3971
3972
3973
3974
3975
3976
3977
3978
3979
3980
3981
3982
3983
3984
3985
3986
3987
 * create_conn() is all done.
 *
 * Curl_setup_conn() also handles reused connections
 *
 * conn->data MUST already have been setup fine (in create_conn)
 */

CURLcode Curl_setup_conn(struct connectdata *conn,
                         bool *protocol_done)
{
  CURLcode result = CURLE_OK;
  struct Curl_easy *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 */

#ifndef CURL_DISABLE_PROXY
  /* 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;
#endif
  /*
   * 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(data->state.aptr.uagent);
    data->state.aptr.uagent =
      aprintf("User-Agent: %s\r\n", data->set.str[STRING_USERAGENT]);
    if(!data->state.aptr.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_now();

  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 */
    if(conn->ssl[FIRSTSOCKET].use ||
       (conn->handler->protocol & PROTO_FAMILY_SSH))
      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_now(); /* time this *after* the connect is done, we set
                             this here perhaps a second time */
  return result;
}








|



|

















<
<
<
<
<
<
<
<
<
<
<
<
<
<











|










|
|







3952
3953
3954
3955
3956
3957
3958
3959
3960
3961
3962
3963
3964
3965
3966
3967
3968
3969
3970
3971
3972
3973
3974
3975
3976
3977
3978
3979
3980














3981
3982
3983
3984
3985
3986
3987
3988
3989
3990
3991
3992
3993
3994
3995
3996
3997
3998
3999
4000
4001
4002
4003
4004
4005
4006
4007
4008
4009
4010
4011
 * create_conn() is all done.
 *
 * Curl_setup_conn() also handles reused connections
 *
 * conn->data MUST already have been setup fine (in create_conn)
 */

CURLcode Curl_setup_conn(struct Curl_easy *data,
                         bool *protocol_done)
{
  CURLcode result = CURLE_OK;
  struct connectdata *conn = data->conn;

  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 */

#ifndef CURL_DISABLE_PROXY
  /* 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;
#endif















#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_now();

  if(CURL_SOCKET_BAD == conn->sock[FIRSTSOCKET]) {
    conn->bits.tcpconnect[FIRSTSOCKET] = FALSE;
    result = Curl_connecthost(data, conn, conn->dns_entry);
    if(result)
      return result;
  }
  else {
    Curl_pgrsTime(data, TIMER_CONNECT);    /* we're connected already */
    if(conn->ssl[FIRSTSOCKET].use ||
       (conn->handler->protocol & PROTO_FAMILY_SSH))
      Curl_pgrsTime(data, TIMER_APPCONNECT); /* we're connected already */
    conn->bits.tcpconnect[FIRSTSOCKET] = TRUE;
    *protocol_done = TRUE;
    Curl_updateconninfo(data, conn, conn->sock[FIRSTSOCKET]);
    Curl_verboseconnect(data, conn);
  }

  conn->now = Curl_now(); /* time this *after* the connect is done, we set
                             this here perhaps a second time */
  return result;
}

4006
4007
4008
4009
4010
4011
4012
4013
4014
4015
4016
4017
4018
4019
4020
    if(CONN_INUSE(conn) > 1)
      /* multiplexed */
      *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(conn, protocol_done);
    }
  }

  if(result == CURLE_NO_CONNECTION_AVAILABLE) {
    return result;
  }
  else if(result && conn) {







|







4030
4031
4032
4033
4034
4035
4036
4037
4038
4039
4040
4041
4042
4043
4044
    if(CONN_INUSE(conn) > 1)
      /* multiplexed */
      *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(data, protocol_done);
    }
  }

  if(result == CURLE_NO_CONNECTION_AVAILABLE) {
    return result;
  }
  else if(result && conn) {
Changes to jni/curl/lib/url.h.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
#ifndef HEADER_CURL_URL_H
#define HEADER_CURL_URL_H
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2020, 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 https://curl.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"

#define READBUFFER_SIZE CURL_MAX_WRITE_SIZE
#define READBUFFER_MAX  CURL_MAX_READ_SIZE
#define READBUFFER_MIN  1024

/* The default upload buffer size, should not be smaller than
   CURL_MAX_WRITE_SIZE, as it needs to hold a full buffer as could be sent in
   a write callback.

   The size was 16KB for many years but was bumped to 64KB because it makes
   libcurl able to do significantly faster uploads in some circumstances. Even
   larger buffers can help further, but this is deemed a fair memory/speed
   compromise. */
#define UPLOADBUFFER_DEFAULT 65536
#define UPLOADBUFFER_MAX (2*1024*1024)
#define UPLOADBUFFER_MIN CURL_MAX_WRITE_SIZE

/*
 * Prototypes for library-wide functions provided by url.c
 */

CURLcode Curl_init_do(struct Curl_easy *data, struct connectdata *conn);
CURLcode Curl_open(struct Curl_easy **curl);
CURLcode Curl_init_userdefined(struct Curl_easy *data);

void Curl_freeset(struct Curl_easy *data);
CURLcode Curl_uc_to_curlcode(CURLUcode uc);
CURLcode Curl_close(struct Curl_easy **datap); /* opposite of curl_open() */
CURLcode Curl_connect(struct Curl_easy *, bool *async, bool *protocol_connect);
CURLcode Curl_disconnect(struct Curl_easy *data,
                         struct connectdata *, bool dead_connection);
CURLcode Curl_setup_conn(struct connectdata *conn,
                         bool *protocol_done);
void Curl_free_request_state(struct Curl_easy *data);
CURLcode Curl_parse_login_details(const char *login, const size_t len,
                                  char **userptr, char **passwdptr,
                                  char **optionsptr);

const struct Curl_handler *Curl_builtin_scheme(const char *scheme);

bool Curl_is_ASCII_name(const char *hostname);
CURLcode Curl_idnconvert_hostname(struct connectdata *conn,
                                  struct hostname *host);
void Curl_free_idnconverted_hostname(struct hostname *host);

#define CURL_DEFAULT_PROXY_PORT 1080 /* default proxy port unless specified */
#define CURL_DEFAULT_HTTPS_PROXY_PORT 443 /* default https proxy port unless
                                             specified */

#ifdef CURL_DISABLE_VERBOSE_STRINGS
#define Curl_verboseconnect(x)  Curl_nop_stmt
#else
void Curl_verboseconnect(struct connectdata *conn);
#endif

#ifdef CURL_DISABLE_PROXY
#define CONNECT_PROXY_SSL() FALSE
#else

#define CONNECT_PROXY_SSL()\









|















<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<














|









|








|

|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
















26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
#ifndef HEADER_CURL_URL_H
#define HEADER_CURL_URL_H
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2021, 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 https://curl.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
 */

CURLcode Curl_init_do(struct Curl_easy *data, struct connectdata *conn);
CURLcode Curl_open(struct Curl_easy **curl);
CURLcode Curl_init_userdefined(struct Curl_easy *data);

void Curl_freeset(struct Curl_easy *data);
CURLcode Curl_uc_to_curlcode(CURLUcode uc);
CURLcode Curl_close(struct Curl_easy **datap); /* opposite of curl_open() */
CURLcode Curl_connect(struct Curl_easy *, bool *async, bool *protocol_connect);
CURLcode Curl_disconnect(struct Curl_easy *data,
                         struct connectdata *, bool dead_connection);
CURLcode Curl_setup_conn(struct Curl_easy *data,
                         bool *protocol_done);
void Curl_free_request_state(struct Curl_easy *data);
CURLcode Curl_parse_login_details(const char *login, const size_t len,
                                  char **userptr, char **passwdptr,
                                  char **optionsptr);

const struct Curl_handler *Curl_builtin_scheme(const char *scheme);

bool Curl_is_ASCII_name(const char *hostname);
CURLcode Curl_idnconvert_hostname(struct Curl_easy *data,
                                  struct hostname *host);
void Curl_free_idnconverted_hostname(struct hostname *host);

#define CURL_DEFAULT_PROXY_PORT 1080 /* default proxy port unless specified */
#define CURL_DEFAULT_HTTPS_PROXY_PORT 443 /* default https proxy port unless
                                             specified */

#ifdef CURL_DISABLE_VERBOSE_STRINGS
#define Curl_verboseconnect(x,y)  Curl_nop_stmt
#else
void Curl_verboseconnect(struct Curl_easy *data, struct connectdata *conn);
#endif

#ifdef CURL_DISABLE_PROXY
#define CONNECT_PROXY_SSL() FALSE
#else

#define CONNECT_PROXY_SSL()\
Changes to jni/curl/lib/urlapi.c.
979
980
981
982
983
984
985
986

987
988
989
990

991
992
993
994
995
996
997
998
{
  if(u) {
    free_urlhandle(u);
    free(u);
  }
}

#define DUP(dest, src, name)         \

  if(src->name) {                    \
    dest->name = strdup(src->name);  \
    if(!dest->name)                  \
      goto fail;                     \

  }

CURLU *curl_url_dup(CURLU *in)
{
  struct Curl_URL *u = calloc(sizeof(struct Curl_URL), 1);
  if(u) {
    DUP(u, in, scheme);
    DUP(u, in, user);







|
>
|
|
|
|
>
|







979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
{
  if(u) {
    free_urlhandle(u);
    free(u);
  }
}

#define DUP(dest, src, name)                    \
  do {                                          \
    if(src->name) {                             \
      dest->name = strdup(src->name);           \
      if(!dest->name)                           \
        goto fail;                              \
    }                                           \
  } while(0)

CURLU *curl_url_dup(CURLU *in)
{
  struct Curl_URL *u = calloc(sizeof(struct Curl_URL), 1);
  if(u) {
    DUP(u, in, scheme);
    DUP(u, in, user);
Changes to jni/curl/lib/urldata.h.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#ifndef HEADER_CURL_URLDATA_H
#define HEADER_CURL_URLDATA_H
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2020, 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 https://curl.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









|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#ifndef HEADER_CURL_URLDATA_H
#define HEADER_CURL_URLDATA_H
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2021, 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 https://curl.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
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119








120
121
122
123
124
125
126
127
128
129
130
131
132
133
134

135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
















154
155
156
157
158
159
160
#include "http_chunks.h" /* for the structs and enum stuff */
#include "hostip.h"
#include "hash.h"
#include "splay.h"
#include "dynbuf.h"

/* 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 */









#include "mime.h"
#include "imap.h"
#include "pop3.h"
#include "smtp.h"
#include "ftp.h"
#include "file.h"
#include "vssh/ssh.h"
#include "http.h"
#include "rtsp.h"
#include "smb.h"
#include "mqtt.h"
#include "wildcard.h"
#include "multihandle.h"
#include "quic.h"


#ifdef HAVE_GSSAPI
# ifdef HAVE_GSSGNU
#  include <gss.h>
# elif defined HAVE_GSSAPI_GSSAPI_H
#  include <gssapi/gssapi.h>
# else
#  include <gssapi.h>
# endif
# ifdef HAVE_GSSAPI_GSSAPI_GENERIC_H
#  include <gssapi/gssapi_generic.h>
# endif
#endif

#ifdef HAVE_LIBSSH2_H
#include <libssh2.h>
#include <libssh2_sftp.h>
#endif /* HAVE_LIBSSH2_H */

















#define CURLEASY_MAGIC_NUMBER 0xc0dedbadU
#define GOOD_EASY_HANDLE(x) \
  ((x) && ((x)->magic == CURLEASY_MAGIC_NUMBER))

/* the type we use for storing a single boolean bit */
#ifdef _MSC_VER
typedef bool bit;







|






|




>
>
>
>
>
>
>
>















>



















>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
#include "http_chunks.h" /* for the structs and enum stuff */
#include "hostip.h"
#include "hash.h"
#include "splay.h"
#include "dynbuf.h"

/* return the count of bytes sent, or -1 on error */
typedef ssize_t (Curl_send)(struct Curl_easy *data,   /* transfer */
                            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 Curl_easy *data,   /* transfer */
                            int sockindex,            /* socketindex */
                            char *buf,                /* store data here */
                            size_t len,               /* max amount to read */
                            CURLcode *err);           /* error to return */

#ifdef USE_HYPER
typedef CURLcode (*Curl_datastream)(struct Curl_easy *data,
                                    struct connectdata *conn,
                                    int *didwhat,
                                    bool *done,
                                    int select_res);
#endif

#include "mime.h"
#include "imap.h"
#include "pop3.h"
#include "smtp.h"
#include "ftp.h"
#include "file.h"
#include "vssh/ssh.h"
#include "http.h"
#include "rtsp.h"
#include "smb.h"
#include "mqtt.h"
#include "wildcard.h"
#include "multihandle.h"
#include "quic.h"
#include "c-hyper.h"

#ifdef HAVE_GSSAPI
# ifdef HAVE_GSSGNU
#  include <gss.h>
# elif defined HAVE_GSSAPI_GSSAPI_H
#  include <gssapi/gssapi.h>
# else
#  include <gssapi.h>
# endif
# ifdef HAVE_GSSAPI_GSSAPI_GENERIC_H
#  include <gssapi/gssapi_generic.h>
# endif
#endif

#ifdef HAVE_LIBSSH2_H
#include <libssh2.h>
#include <libssh2_sftp.h>
#endif /* HAVE_LIBSSH2_H */

#define READBUFFER_SIZE CURL_MAX_WRITE_SIZE
#define READBUFFER_MAX  CURL_MAX_READ_SIZE
#define READBUFFER_MIN  1024

/* The default upload buffer size, should not be smaller than
   CURL_MAX_WRITE_SIZE, as it needs to hold a full buffer as could be sent in
   a write callback.

   The size was 16KB for many years but was bumped to 64KB because it makes
   libcurl able to do significantly faster uploads in some circumstances. Even
   larger buffers can help further, but this is deemed a fair memory/speed
   compromise. */
#define UPLOADBUFFER_DEFAULT 65536
#define UPLOADBUFFER_MAX (2*1024*1024)
#define UPLOADBUFFER_MIN CURL_MAX_WRITE_SIZE

#define CURLEASY_MAGIC_NUMBER 0xc0dedbadU
#define GOOD_EASY_HANDLE(x) \
  ((x) && ((x)->magic == CURLEASY_MAGIC_NUMBER))

/* the type we use for storing a single boolean bit */
#ifdef _MSC_VER
typedef bool bit;
364
365
366
367
368
369
370
371
372

373
374
375
376
377
378
379
  BYTE *output_token;
  BYTE *input_token;
  size_t input_token_len;
  TCHAR *spn;
#else
  unsigned int flags;
  unsigned char nonce[8];
  void *target_info; /* TargetInfo received in the ntlm type-2 message */
  unsigned int target_info_len;


#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; /* The received base64 encoded ntlm type-2 message */
  char *response;  /* The generated base64 ntlm type-1/type-3 message */







<

>







389
390
391
392
393
394
395

396
397
398
399
400
401
402
403
404
  BYTE *output_token;
  BYTE *input_token;
  size_t input_token_len;
  TCHAR *spn;
#else
  unsigned int flags;
  unsigned char nonce[8];

  unsigned int target_info_len;
  void *target_info; /* TargetInfo received in the ntlm type-2 message */

#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; /* The received base64 encoded ntlm type-2 message */
  char *response;  /* The generated base64 ntlm type-1/type-3 message */
510
511
512
513
514
515
516


517
518
519
520
521
522




523
524


525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
                                  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)



struct Curl_async {
  char *hostname;
  int port;
  struct Curl_dns_entry *dns;
  int status; /* if done is TRUE, this is the status from the callback */
  struct thread_data *tdata;




  BIT(done);  /* set TRUE when the lookup is complete */
};



#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 */
};







>
>


<

<

>
>
>
>


>
>




<
<
<
<
<
<







535
536
537
538
539
540
541
542
543
544
545

546

547
548
549
550
551
552
553
554
555
556
557
558
559






560
561
562
563
564
565
566
                                  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)

#if defined(CURLRES_ASYNCH) || !defined(CURL_DISABLE_DOH)
#define USE_CURL_ASYNC
struct Curl_async {
  char *hostname;

  struct Curl_dns_entry *dns;

  struct thread_data *tdata;
  void *resolver; /* resolver state, if it is used in the URL state -
                     ares_channel f.e. */
  int port;
  int status; /* if done is TRUE, this is the status from the callback */
  BIT(done);  /* set TRUE when the lookup is complete */
};

#endif

#define FIRSTSOCKET     0
#define SECONDARYSOCKET 1







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 */
};
574
575
576
577
578
579
580
581
582

583
584
585
586
587
588
589
  struct dynbuf serverdoh;
};

struct dohdata {
  struct curl_slist *headers;
  struct dnsprobe probe[DOH_PROBE_SLOTS];
  unsigned int pending; /* still outstanding requests */
  const char *host;
  int port;

};

/*
 * Request specific data in the easy handle (Curl_easy).  Previously,
 * these members were on the connectdata struct but since a conn struct may
 * now be shared between different Curl_easys, we store connection-specific
 * data here. This struct only keeps stuff that's interesting for *this*







<

>







599
600
601
602
603
604
605

606
607
608
609
610
611
612
613
614
  struct dynbuf serverdoh;
};

struct dohdata {
  struct curl_slist *headers;
  struct dnsprobe probe[DOH_PROBE_SLOTS];
  unsigned int pending; /* still outstanding requests */

  int port;
  const char *host;
};

/*
 * Request specific data in the easy handle (Curl_easy).  Previously,
 * these members were on the connectdata struct but since a conn struct may
 * now be shared between different Curl_easys, we store connection-specific
 * data here. This struct only keeps stuff that's interesting for *this*
600
601
602
603
604
605
606


607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622

623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
  curl_off_t 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 curltime start;         /* transfer started at this time */
  struct curltime now;           /* current time */
  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 *str;                    /* within buf */
  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 curltime start100;      /* time stamp to wait for the 100 code from */
  enum expect100 exp100;        /* expect 100 continue state */
  enum upgrade101 upgr101;      /* 101 upgrade state */

  /* Content unencoding stack. See sec 3.5, RFC2616. */
  struct contenc_writer *writer_stack;
  time_t timeofdoc;
  long bodywrites;
  int keepon;
  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. */







>
>
















>








<







625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658

659
660
661
662
663
664
665
  curl_off_t 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 */

  curl_off_t pendingheader;      /* this many bytes left to send is actually
                                    header and not body */
  struct curltime start;         /* transfer started at this time */
  struct curltime now;           /* current time */
  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 *str;                    /* within buf */
  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 */
  int keepon;
  struct curltime start100;      /* time stamp to wait for the 100 code from */
  enum expect100 exp100;        /* expect 100 continue state */
  enum upgrade101 upgr101;      /* 101 upgrade state */

  /* Content unencoding stack. See sec 3.5, RFC2616. */
  struct contenc_writer *writer_stack;
  time_t timeofdoc;
  long bodywrites;

  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. */
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
    struct RTSP *rtsp;
    struct smb_request *smb;
    struct SMTP *smtp;
    struct SSHPROTO *ssh;
    struct TELNET *telnet;
  } p;
#ifndef CURL_DISABLE_DOH
  struct dohdata doh; /* DoH specific data for this request */
#endif
  BIT(header);       /* incoming data has HTTP header */
  BIT(content_range); /* set TRUE if Content-Range: was found */
  BIT(upload_done);  /* set to TRUE when doing chunked transfer-encoding
                        upload and we're uploading the last chunk */
  BIT(ignorebody);   /* we read a response-body but we ignore it! */
  BIT(http_bodyless); /* HTTP response status code is between 100 and 199,







|







684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
    struct RTSP *rtsp;
    struct smb_request *smb;
    struct SMTP *smtp;
    struct SSHPROTO *ssh;
    struct TELNET *telnet;
  } p;
#ifndef CURL_DISABLE_DOH
  struct dohdata *doh; /* DoH specific data for this request */
#endif
  BIT(header);       /* incoming data has HTTP header */
  BIT(content_range); /* set TRUE if Content-Range: was found */
  BIT(upload_done);  /* set to TRUE when doing chunked transfer-encoding
                        upload and we're uploading the last chunk */
  BIT(ignorebody);   /* we read a response-body but we ignore it! */
  BIT(http_bodyless); /* HTTP response status code is between 100 and 199,
682
683
684
685
686
687
688
689

690

691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738

739

740
741
742
743
744
745
746
747
748
749
750

751
752
753
754
755
756
757
758
759
760
/*
 * 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. */
  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);

  /* 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);

  /* 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);

  /* 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);

  /* 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 Curl_easy *data, struct connectdata *conn,
                        ssize_t *nread, bool *readmore);

  /* This function can perform various checks on the connection. See
     CONNCHECK_* for more information about the checks that can be performed,
     and CONNRESULT_* for the results that can be returned. */
  unsigned int (*connection_check)(struct connectdata *conn,

                                   unsigned int checks_to_perform);

  long defport;           /* Default port. */
  unsigned int protocol;  /* See CURLPROTO_* - this needs to be the single
                             specific protocol bit */
  unsigned int family;    /* single bit for protocol family; basically the
                             non-TLS name of the protocol this is */
  unsigned int flags;     /* Extra particular characteristics, see PROTOPT_* */
};








|
>
|
>


|
|





|







|


|
|



|
|



|
|



|
|




|
|



|
|
>

>
|









|
>


|







709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
/*
 * Specific protocol handler.
 */

struct Curl_handler {
  const char *scheme;        /* URL scheme name. */

  /* Complement to setup_connection_internals(). This is done before the
     transfer "owns" the connection. */
  CURLcode (*setup_connection)(struct Curl_easy *data,
                               struct connectdata *conn);

  /* These two functions MUST be set to be protocol dependent */
  CURLcode (*do_it)(struct Curl_easy *data, bool *done);
  CURLcode (*done)(struct Curl_easy *, CURLcode, bool);

  /* 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.
   */
  CURLcode (*do_more)(struct Curl_easy *, int *);

  /* 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 Curl_easy *data, bool *done);

  /* See above. */
  CURLcode (*connecting)(struct Curl_easy *data, bool *done);
  CURLcode (*doing)(struct Curl_easy *data, bool *done);

  /* Called from the multi interface during the PROTOCONNECT phase, and it
     should then return a proper fd set */
  int (*proto_getsock)(struct Curl_easy *data,
                       struct connectdata *conn, curl_socket_t *socks);

  /* Called from the multi interface during the DOING phase, and it should
     then return a proper fd set */
  int (*doing_getsock)(struct Curl_easy *data,
                       struct connectdata *conn, curl_socket_t *socks);

  /* Called from the multi interface during the DO_MORE phase, and it should
     then return a proper fd set */
  int (*domore_getsock)(struct Curl_easy *data,
                        struct connectdata *conn, curl_socket_t *socks);

  /* 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)(struct Curl_easy *data,
                         struct connectdata *conn, curl_socket_t *socks);

  /* 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. The connection is already disassociated
   * from the transfer here.
   */
  CURLcode (*disconnect)(struct Curl_easy *, 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 Curl_easy *data, struct connectdata *conn,
                        ssize_t *nread, bool *readmore);

  /* This function can perform various checks on the connection. See
     CONNCHECK_* for more information about the checks that can be performed,
     and CONNRESULT_* for the results that can be returned. */
  unsigned int (*connection_check)(struct Curl_easy *data,
                                   struct connectdata *conn,
                                   unsigned int checks_to_perform);

  int defport;            /* Default port. */
  unsigned int protocol;  /* See CURLPROTO_* - this needs to be the single
                             specific protocol bit */
  unsigned int family;    /* single bit for protocol family; basically the
                             non-TLS name of the protocol this is */
  unsigned int flags;     /* Extra particular characteristics, see PROTOPT_* */
};

854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
  CONNECT_REQ_READ,  /* 15 */
  CONNECT_REQ_READ_MORE, /* 16 */
  CONNECT_DONE /* 17 connected fine to the remote or the SOCKS proxy */
};

#define SOCKS_STATE(x) (((x) >= CONNECT_SOCKS_INIT) &&  \
                        ((x) < CONNECT_DONE))
#define SOCKS_REQUEST_BUFSIZE 600  /* room for large user/pw (255 max each) */

struct connstate {
  enum connect_t state;
  unsigned char socksreq[SOCKS_REQUEST_BUFSIZE];

  /* CONNECT_SOCKS_SEND */
  ssize_t outstanding;  /* send this many bytes more */
  unsigned char *outp; /* send from this pointer */
};

/*
 * The connectdata struct contains all fields and variables that should be
 * unique for an entire connection.







<



<
<
<







886
887
888
889
890
891
892

893
894
895



896
897
898
899
900
901
902
  CONNECT_REQ_READ,  /* 15 */
  CONNECT_REQ_READ_MORE, /* 16 */
  CONNECT_DONE /* 17 connected fine to the remote or the SOCKS proxy */
};

#define SOCKS_STATE(x) (((x) >= CONNECT_SOCKS_INIT) &&  \
                        ((x) < CONNECT_DONE))


struct connstate {
  enum connect_t state;



  ssize_t outstanding;  /* send this many bytes more */
  unsigned char *outp; /* send from this pointer */
};

/*
 * The connectdata struct contains all fields and variables that should be
 * unique for an entire connection.
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925

  /* '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 multi_done() */
  struct Curl_addrinfo *ip_addr;
  struct 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 */

  enum {
    TRNSPRT_TCP = 3,
    TRNSPRT_UDP = 4,
    TRNSPRT_QUIC = 5
  } transport;







<
<
<
<
<







935
936
937
938
939
940
941





942
943
944
945
946
947
948

  /* '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 multi_done() */
  struct Curl_addrinfo *ip_addr;
  struct Curl_addrinfo *tempaddr[2]; /* for happy eyeballs */






  unsigned int scope_id;  /* Scope id for IPv6 */

  enum {
    TRNSPRT_TCP = 3,
    TRNSPRT_UDP = 4,
    TRNSPRT_QUIC = 5
  } transport;
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
  char *secondaryhostname; /* secondary socket host name (ftp) */
  struct hostname conn_to_host; /* the host to connect to. valid only if
                                   bits.conn_to_host is set */
#ifndef CURL_DISABLE_PROXY
  struct proxy_info socks_proxy;
  struct proxy_info http_proxy;
#endif
  long port;       /* which port to use locally */
  int remote_port; /* the remote port, not the proxy port! */
  int conn_to_port; /* the remote port to connect to. valid only if
                       bits.conn_to_port is set */
  unsigned short secondary_port; /* secondary socket remote port to connect to
                                    (ftp) */

  /* '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 *sasl_authzid;     /* authorisation identity string, allocated */








|














<
|
<
<
<
<
<
<







957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978

979






980
981
982
983
984
985
986
  char *secondaryhostname; /* secondary socket host name (ftp) */
  struct hostname conn_to_host; /* the host to connect to. valid only if
                                   bits.conn_to_host is set */
#ifndef CURL_DISABLE_PROXY
  struct proxy_info socks_proxy;
  struct proxy_info http_proxy;
#endif
  int port;        /* which port to use locally - to connect to */
  int remote_port; /* the remote port, not the proxy port! */
  int conn_to_port; /* the remote port to connect to. valid only if
                       bits.conn_to_port is set */
  unsigned short secondary_port; /* secondary socket remote port to connect to
                                    (ftp) */

  /* '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];

  unsigned char ip_version; /* copied from the Curl_easy at creation time */







  char *user;    /* user name string, allocated */
  char *passwd;  /* password string, allocated */
  char *options; /* options string, allocated */

  char *sasl_authzid;     /* authorisation identity string, allocated */

993
994
995
996
997
998
999


1000
1001
1002
1003
1004
1005
1006

1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
#endif
  struct ssl_primary_config ssl_config;
#ifndef CURL_DISABLE_PROXY
  struct ssl_primary_config proxy_ssl_config;
#endif
  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 curltime connecttime;
  /* The two fields below get set in Curl_connecthost */
  int num_addr; /* number of addresses to try to connect to */


  /* how long time in milliseconds to spend on trying to connect to each IP
     address, per family */
  timediff_t timeoutms_per_addr[2];

  const struct Curl_handler *handler; /* Connection's protocol handler */
  const struct Curl_handler *given;   /* The protocol first given */

  long ip_version; /* copied from the Curl_easy at creation time */

  /* Protocols can use a custom keepalive mechanism to keep connections alive.
     This allows those protocols to track the last time the keepalive mechanism
     was used on this connection. */
  struct curltime keepalive;

  long upkeep_interval_ms;      /* Time between calls for connection upkeep. */

  /**** 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 */








>
>




<
<

>







<
<





<
<







1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021


1022
1023
1024
1025
1026
1027
1028
1029
1030


1031
1032
1033
1034
1035


1036
1037
1038
1039
1040
1041
1042
#endif
  struct ssl_primary_config ssl_config;
#ifndef CURL_DISABLE_PROXY
  struct ssl_primary_config proxy_ssl_config;
#endif
  struct ConnectBits bits;    /* various state-flags for this connection */

  /* The field below gets set in Curl_connecthost */
  int num_addr; /* number of addresses to try to connect to */
 /* 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 curltime connecttime;



  /* The field below gets set in Curl_connecthost */
  /* how long time in milliseconds to spend on trying to connect to each IP
     address, per family */
  timediff_t timeoutms_per_addr[2];

  const struct Curl_handler *handler; /* Connection's protocol handler */
  const struct Curl_handler *given;   /* The protocol first given */



  /* Protocols can use a custom keepalive mechanism to keep connections alive.
     This allows those protocols to track the last time the keepalive mechanism
     was used on this connection. */
  struct curltime keepalive;



  /**** 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 */

1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100



1101
1102
1103
1104
1105
1106
1107
1108

1109
1110
1111
1112

1113
1114

1115
1116
1117
1118
1119
1120
1121
  curlnegotiate http_negotiate_state;
  curlnegotiate proxy_negotiate_state;

  struct negotiatedata negotiate; /* state data for host Negotiate auth */
  struct negotiatedata proxyneg; /* state data for proxy Negotiate auth */
#endif

  /* data used for the asynch name resolve callback */
  struct Curl_async async;

  /* for chunked-encoded trailer */
  struct dynbuf trailer;

  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 *rtmp;
    struct ldapconninfo *ldapc;
    struct mqtt_conn mqtt;
  } 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




  /* 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;

  struct http_connect_state *connect_state; /* for HTTP CONNECT */
  struct connectbundle *bundle; /* The bundle we are member of */
  int negnpn; /* APLN or NPN TLS negotiated protocol, CURL_HTTP_VERSION* */
#ifdef USE_UNIX_SOCKETS

  char *unix_domain_socket;
#endif

};

/* The end of connectdata. */

/*
 * Struct to keep statistical and informational data.
 * All variables in this struct must be initialized/reset in Curl_initinfo().







<
<
<


















|
<
|
|
|

|
>
>
>






<

>
|
<

|
>
|

>







1079
1080
1081
1082
1083
1084
1085



1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104

1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118

1119
1120
1121

1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
  curlnegotiate http_negotiate_state;
  curlnegotiate proxy_negotiate_state;

  struct negotiatedata negotiate; /* state data for host Negotiate auth */
  struct negotiatedata proxyneg; /* state data for proxy Negotiate auth */
#endif




  /* for chunked-encoded trailer */
  struct dynbuf trailer;

  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 *rtmp;
    struct ldapconninfo *ldapc;
    struct mqtt_conn mqtt;
  } proto;

  struct http_connect_state *connect_state; /* for HTTP CONNECT */

  struct connectbundle *bundle; /* The bundle we are member of */
#ifdef USE_UNIX_SOCKETS
  char *unix_domain_socket;
#endif
#ifdef USE_HYPER
  /* if set, an alternative data transfer function */
  Curl_datastream datastream;
#endif
  /* 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;

  int localportrange;
  int cselect_bits; /* bitmask of socket events */
  int waitfor;      /* current READ/WRITE bits to wait for */

  int negnpn; /* APLN or NPN TLS negotiated protocol, CURL_HTTP_VERSION* */

#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI)
  int socks5_gssapi_enctype;
#endif
  unsigned short localport;
};

/* The end of connectdata. */

/*
 * Struct to keep statistical and informational data.
 * All variables in this struct must be initialized/reset in Curl_initinfo().
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
  curl_off_t speeder[ CURR_TIME ];
  struct curltime speeder_time[ CURR_TIME ];
  int speeder_c;
  BIT(callback);  /* set when progress callback is used */
  BIT(is_t_startransfer_set);
};

typedef enum {
  HTTPREQ_NONE, /* first in list */
  HTTPREQ_GET,
  HTTPREQ_POST,
  HTTPREQ_POST_FORM, /* we make a difference internally */
  HTTPREQ_POST_MIME, /* we make a difference internally */
  HTTPREQ_PUT,
  HTTPREQ_HEAD,
  HTTPREQ_LAST /* last in list */
} Curl_HttpReq;

typedef enum {
    RTSPREQ_NONE, /* first in list */
    RTSPREQ_OPTIONS,
    RTSPREQ_DESCRIBE,
    RTSPREQ_ANNOUNCE,
    RTSPREQ_SETUP,
    RTSPREQ_PLAY,







<
<
<
<
<
<
<
<
<
<
<







1215
1216
1217
1218
1219
1220
1221











1222
1223
1224
1225
1226
1227
1228
  curl_off_t speeder[ CURR_TIME ];
  struct curltime speeder_time[ CURR_TIME ];
  int speeder_c;
  BIT(callback);  /* set when progress callback is used */
  BIT(is_t_startransfer_set);
};












typedef enum {
    RTSPREQ_NONE, /* first in list */
    RTSPREQ_OPTIONS,
    RTSPREQ_DESCRIBE,
    RTSPREQ_ANNOUNCE,
    RTSPREQ_SETUP,
    RTSPREQ_PLAY,
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
  char *path;
  char *query;
};

struct UrlState {
  /* Points to the connection cache */
  struct conncache *conn_cache;

  int retrycount; /* number of retries on a new connection */

  /* buffers to store authentication data in, as parsed from input options */
  struct curltime keeps_speed; /* for the progress meter really */

  long lastconnect_id; /* The last connection, -1 if undefined */
  struct dynbuf headerb; /* buffer to store headers in */







<







1312
1313
1314
1315
1316
1317
1318

1319
1320
1321
1322
1323
1324
1325
  char *path;
  char *query;
};

struct UrlState {
  /* Points to the connection cache */
  struct conncache *conn_cache;

  int retrycount; /* number of retries on a new connection */

  /* buffers to store authentication data in, as parsed from input options */
  struct curltime keeps_speed; /* for the progress meter really */

  long lastconnect_id; /* The last connection, -1 if undefined */
  struct dynbuf headerb; /* buffer to store headers in */
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341

1342

1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353

1354
1355
1356
1357
1358
1359
1360
                       sent authorization to, no else. Used to make Location:
                       following not keep sending user+password... This is
                       strdup() data.
                    */
  int first_remote_port; /* remote port of the first (not followed) request */
  struct Curl_ssl_session *session; /* array of 'max_ssl_sessions' size */
  long sessionage;                  /* number of the most recent session */
  unsigned int tempcount; /* number of entries in use in tempwrite, 0 - 3 */
  struct tempbuf tempwrite[3]; /* BOTH, HEADER, BODY */
  char *scratch; /* huge buffer[set.buffer_size*2] for upload CRLF replacing */

  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
  struct digestdata digest;      /* state data for host Digest auth */
  struct digestdata proxydigest; /* state data for proxy Digest auth */

  struct auth authhost;  /* auth details for host */
  struct auth authproxy; /* auth details for proxy */
  void *resolver; /* resolver state, if it is used in the URL state -
                     ares_channel f.e. */


#if defined(USE_OPENSSL)
  /* void instead of ENGINE to avoid bleeding OpenSSL into this header */
  void *engine;
#endif /* USE_OPENSSL */
  struct curltime expiretime; /* set this with Curl_expire() only */
  struct Curl_tree timenode; /* for the splay stuff */







<

<
>

>









|
|
>







1333
1334
1335
1336
1337
1338
1339

1340

1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
                       sent authorization to, no else. Used to make Location:
                       following not keep sending user+password... This is
                       strdup() data.
                    */
  int first_remote_port; /* remote port of the first (not followed) request */
  struct Curl_ssl_session *session; /* array of 'max_ssl_sessions' size */
  long sessionage;                  /* number of the most recent session */

  struct tempbuf tempwrite[3]; /* BOTH, HEADER, BODY */

  unsigned int tempcount; /* number of entries in use in tempwrite, 0 - 3 */
  int os_errno;  /* filled in with errno whenever an error occurs */
  char *scratch; /* huge buffer[set.buffer_size*2] for upload CRLF replacing */
#ifdef HAVE_SIGNAL
  /* storage for the previous bag^H^H^HSIGPIPE signal handler :-) */
  void (*prev_signal)(int sig);
#endif
  struct digestdata digest;      /* state data for host Digest auth */
  struct digestdata proxydigest; /* state data for proxy Digest auth */

  struct auth authhost;  /* auth details for host */
  struct auth authproxy; /* auth details for proxy */
#ifdef USE_CURL_ASYNC
  struct Curl_async async;  /* asynchronous name resolver data */
#endif

#if defined(USE_OPENSSL)
  /* void instead of ENGINE to avoid bleeding OpenSSL into this header */
  void *engine;
#endif /* USE_OPENSSL */
  struct curltime expiretime; /* set this with Curl_expire() only */
  struct Curl_tree timenode; /* for the splay stuff */
1394
1395
1396
1397
1398
1399
1400

1401

1402
1403
1404
1405
1406
1407
1408



1409
1410
1411
1412
1413
1414
1415
  curl_read_callback fread_func; /* read callback/function */
  void *in;                      /* CURLOPT_READDATA */

  struct Curl_easy *stream_depends_on;
  int stream_weight;
  CURLU *uh; /* URL handle for the current parsed URL */
  struct urlpieces up;

  Curl_HttpReq httpreq; /* what kind of HTTP request (if any) is this */

#ifndef CURL_DISABLE_HTTP
  size_t trailers_bytes_sent;
  struct dynbuf trailers_buf; /* a buffer containing the compiled trailing
                                 headers */
#endif
  trailers_state trailers_state; /* whether we are sending trailers
                                       and what stage are we at */




  /* Dynamically allocated strings, MUST be freed before this struct is
     killed. */
  struct dynamically_allocated_data {
    char *proxyuserpwd;
    char *uagent;
    char *accept_encoding;







>

>







>
>
>







1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
  curl_read_callback fread_func; /* read callback/function */
  void *in;                      /* CURLOPT_READDATA */

  struct Curl_easy *stream_depends_on;
  int stream_weight;
  CURLU *uh; /* URL handle for the current parsed URL */
  struct urlpieces up;
#if !defined(CURL_DISABLE_HTTP) || !defined(CURL_DISABLE_MQTT)
  Curl_HttpReq httpreq; /* what kind of HTTP request (if any) is this */
#endif
#ifndef CURL_DISABLE_HTTP
  size_t trailers_bytes_sent;
  struct dynbuf trailers_buf; /* a buffer containing the compiled trailing
                                 headers */
#endif
  trailers_state trailers_state; /* whether we are sending trailers
                                       and what stage are we at */
#ifdef USE_HYPER
  CURLcode hresult; /* used to pass return codes back from hyper callbacks */
#endif

  /* Dynamically allocated strings, MUST be freed before this struct is
     killed. */
  struct dynamically_allocated_data {
    char *proxyuserpwd;
    char *uagent;
    char *accept_encoding;
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586

1587
1588
1589
1590
1591
1592
1593
  STRING_BEARER,                /* <bearer>, if used */
  STRING_UNIX_SOCKET_PATH,      /* path to Unix socket, if used */
  STRING_TARGET,                /* CURLOPT_REQUEST_TARGET */
  STRING_DOH,                   /* CURLOPT_DOH_URL */
  STRING_ALTSVC,                /* CURLOPT_ALTSVC */
  STRING_HSTS,                  /* CURLOPT_HSTS */
  STRING_SASL_AUTHZID,          /* CURLOPT_SASL_AUTHZID */
  STRING_TEMP_URL,              /* temp URL storage for proxy use */
  STRING_DNS_SERVERS,
  STRING_DNS_INTERFACE,
  STRING_DNS_LOCAL_IP4,
  STRING_DNS_LOCAL_IP6,
  STRING_SSL_EC_CURVES,

  /* -- end of null-terminated strings -- */

  STRING_LASTZEROTERMINATED,

  /* -- below this are pointers to binary data that cannot be strdup'ed. --- */

  STRING_COPYPOSTFIELDS,  /* if POST, set the fields' values here */



  STRING_LAST /* not used, just an end-of-list marker */
};

enum dupblob {
  BLOB_CERT_ORIG,
  BLOB_CERT_PROXY,







<














>







1572
1573
1574
1575
1576
1577
1578

1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
  STRING_BEARER,                /* <bearer>, if used */
  STRING_UNIX_SOCKET_PATH,      /* path to Unix socket, if used */
  STRING_TARGET,                /* CURLOPT_REQUEST_TARGET */
  STRING_DOH,                   /* CURLOPT_DOH_URL */
  STRING_ALTSVC,                /* CURLOPT_ALTSVC */
  STRING_HSTS,                  /* CURLOPT_HSTS */
  STRING_SASL_AUTHZID,          /* CURLOPT_SASL_AUTHZID */

  STRING_DNS_SERVERS,
  STRING_DNS_INTERFACE,
  STRING_DNS_LOCAL_IP4,
  STRING_DNS_LOCAL_IP6,
  STRING_SSL_EC_CURVES,

  /* -- end of null-terminated strings -- */

  STRING_LASTZEROTERMINATED,

  /* -- below this are pointers to binary data that cannot be strdup'ed. --- */

  STRING_COPYPOSTFIELDS,  /* if POST, set the fields' values here */

  STRING_AWS_SIGV4, /* Parameters for V4 signature */

  STRING_LAST /* not used, just an end-of-list marker */
};

enum dupblob {
  BLOB_CERT_ORIG,
  BLOB_CERT_PROXY,
1695
1696
1697
1698
1699
1700
1701

1702

1703

1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
                                          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 */
  struct curl_slist *connect_to; /* list of host:port mappings to override
                                    the hostname and port to connect to */
  curl_TimeCond timecondition; /* kind of time/date comparison */

  time_t timevalue;       /* what time to compare with */

  Curl_HttpReq method;   /* 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 */
#ifndef CURL_DISABLE_PROXY
  struct ssl_config_data proxy_ssl;  /* user defined SSL stuff for proxy */
#endif
  struct ssl_general_config general_ssl; /* general 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 */
  size_t upload_buffer_size; /* size of upload buffer to use,
                                keep it >= CURL_MAX_WRITE_SIZE */
  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 */
#ifndef CURL_DISABLE_FTP
  curl_ftpfile ftp_filemethod; /* how to get to a file when FTP is used  */
  curl_ftpauth ftpsslauth; /* what AUTH XXX to be attempted */
  curl_ftpccc ftp_ccc;   /* FTP CCC options */
#endif
  int ftp_create_missing_dirs; /* 1 - create directories that don't exist







>

>

>







<






|
|







1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720

1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
                                          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 */
  struct curl_slist *connect_to; /* list of host:port mappings to override
                                    the hostname and port to connect to */
  curl_TimeCond timecondition; /* kind of time/date comparison */
  curl_proxytype proxytype; /* what kind of proxy that is in use */
  time_t timevalue;       /* what time to compare with */
#if !defined(CURL_DISABLE_HTTP) || !defined(CURL_DISABLE_MQTT)
  Curl_HttpReq method;   /* what kind of HTTP request (if any) is this */
#endif
  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 */
#ifndef CURL_DISABLE_PROXY
  struct ssl_config_data proxy_ssl;  /* user defined SSL stuff for proxy */
#endif
  struct ssl_general_config general_ssl; /* general user defined SSL stuff */

  long dns_cache_timeout; /* DNS cache timeout */
  long buffer_size;      /* size of receive buffer to use */
  size_t upload_buffer_size; /* size of upload buffer to use,
                                keep it >= CURL_MAX_WRITE_SIZE */
  void *private_data; /* application-private data */
  struct curl_slist *http200aliases; /* linked list of aliases for http200 */
  unsigned char 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 */
#ifndef CURL_DISABLE_FTP
  curl_ftpfile ftp_filemethod; /* how to get to a file when FTP is used  */
  curl_ftpauth ftpsslauth; /* what AUTH XXX to be attempted */
  curl_ftpccc ftp_ccc;   /* FTP CCC options */
#endif
  int ftp_create_missing_dirs; /* 1 - create directories that don't exist
1870
1871
1872
1873
1874
1875
1876




1877
1878
1879
1880
1881
1882
1883
 * 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 Curl_easy {




  /* first, two fields for the linked list of these */
  struct Curl_easy *next;
  struct Curl_easy *prev;

  struct connectdata *conn;
  struct Curl_llist_element connect_queue;
  struct Curl_llist_element conn_queue; /* list per connectdata */







>
>
>
>







1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
 * 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 Curl_easy {
  /* First a simple identifier to easier detect if a user mix up this easy
     handle with a multi handle. Set this to CURLEASY_MAGIC_NUMBER */
  unsigned int magic;

  /* first, two fields for the linked list of these */
  struct Curl_easy *next;
  struct Curl_easy *prev;

  struct connectdata *conn;
  struct Curl_llist_element connect_queue;
  struct Curl_llist_element conn_queue; /* list per connectdata */
1930
1931
1932
1933
1934
1935
1936
1937


1938
1939
1940
1941
1942
  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 */







|
>
>





1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
  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 */
#ifdef USE_HYPER
  struct hyptransfer hyp;
#endif
};

#define LIBCURL_NAME "libcurl"

#endif /* HEADER_CURL_URLDATA_H */
Changes to jni/curl/lib/vauth/digest.c.
57
58
59
60
61
62
63
64

65
66
67
68

69
70
71
72
73
74
75
76
#define DIGEST_QOP_VALUE_STRING_AUTH_INT  "auth-int"
#define DIGEST_QOP_VALUE_STRING_AUTH_CONF "auth-conf"

/* 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, b, strlen(b)); \
  if(result) { \
    free(b); \
    return result; \

  }
#endif /* !USE_WINDOWS_SSPI */

bool Curl_auth_digest_get_pair(const char *str, char *value, char *content,
                               const char **endptr)
{
  int c;
  bool starts_with_quote = FALSE;







|
>
|
|
|
|
>
|







57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
#define DIGEST_QOP_VALUE_STRING_AUTH_INT  "auth-int"
#define DIGEST_QOP_VALUE_STRING_AUTH_CONF "auth-conf"

/* 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)                  \
  do {                                                 \
    result = Curl_convert_to_network(a, b, strlen(b)); \
    if(result) {                                       \
      free(b);                                         \
      return result;                                   \
    }                                                  \
  } while(0)
#endif /* !USE_WINDOWS_SSPI */

bool Curl_auth_digest_get_pair(const char *str, char *value, char *content,
                               const char **endptr)
{
  int c;
  bool starts_with_quote = FALSE;
Changes to jni/curl/lib/vauth/digest_sspi.c.
34
35
36
37
38
39
40

41
42
43
44
45
46
47
#include "urldata.h"
#include "curl_base64.h"
#include "warnless.h"
#include "curl_multibyte.h"
#include "sendf.h"
#include "strdup.h"
#include "strcase.h"


/* The last #include files should be: */
#include "curl_memory.h"
#include "memdebug.h"

/*
* Curl_auth_is_digest_supported()







>







34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
#include "urldata.h"
#include "curl_base64.h"
#include "warnless.h"
#include "curl_multibyte.h"
#include "sendf.h"
#include "strdup.h"
#include "strcase.h"
#include "strerror.h"

/* The last #include files should be: */
#include "curl_memory.h"
#include "memdebug.h"

/*
* Curl_auth_is_digest_supported()
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144

  /* Query the security package for DigestSSP */
  status = s_pSecFn->QuerySecurityPackageInfo((TCHAR *) TEXT(SP_NAME_DIGEST),
                                              &SecurityPackage);
  if(status != SEC_E_OK) {
    free(input_token);

    failf(data, "SSPI: couldn't get auth info\n");
    return CURLE_AUTH_ERROR;
  }

  token_max = SecurityPackage->cbMaxToken;

  /* Release the package buffer as it is not required anymore */
  s_pSecFn->FreeContextBuffer(SecurityPackage);







|







131
132
133
134
135
136
137
138
139
140
141
142
143
144
145

  /* Query the security package for DigestSSP */
  status = s_pSecFn->QuerySecurityPackageInfo((TCHAR *) TEXT(SP_NAME_DIGEST),
                                              &SecurityPackage);
  if(status != SEC_E_OK) {
    free(input_token);

    failf(data, "SSPI: couldn't get auth info");
    return CURLE_AUTH_ERROR;
  }

  token_max = SecurityPackage->cbMaxToken;

  /* Release the package buffer as it is not required anymore */
  s_pSecFn->FreeContextBuffer(SecurityPackage);
216
217
218
219
220
221
222


223
224
225
226
227
228
229
230



231
232
233
234
235
236
237
                                               &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);

    if(status == SEC_E_INSUFFICIENT_MEMORY)
      return CURLE_OUT_OF_MEMORY;




    return CURLE_AUTH_ERROR;
  }

  /* Base64 encode the response */
  result = Curl_base64_encode(data, (char *) output_token, resp_buf.cbBuffer,
                              outptr, outlen);







>
>








>
>
>







217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
                                               &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) {
    char buffer[STRERROR_LEN];

    s_pSecFn->FreeCredentialsHandle(&credentials);
    Curl_sspi_free_identity(p_identity);
    free(spn);
    free(output_token);
    free(input_token);

    if(status == SEC_E_INSUFFICIENT_MEMORY)
      return CURLE_OUT_OF_MEMORY;

    infof(data, "schannel: InitializeSecurityContext failed: %s\n",
          Curl_sspi_strerror(status, buffer, sizeof(buffer)));

    return CURLE_AUTH_ERROR;
  }

  /* Base64 encode the response */
  result = Curl_base64_encode(data, (char *) output_token, resp_buf.cbBuffer,
                              outptr, outlen);
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443

  (void) data;

  /* Query the security package for DigestSSP */
  status = s_pSecFn->QuerySecurityPackageInfo((TCHAR *) TEXT(SP_NAME_DIGEST),
                                              &SecurityPackage);
  if(status != SEC_E_OK) {
    failf(data, "SSPI: couldn't get auth info\n");
    return CURLE_AUTH_ERROR;
  }

  token_max = SecurityPackage->cbMaxToken;

  /* Release the package buffer as it is not required anymore */
  s_pSecFn->FreeContextBuffer(SecurityPackage);







|







435
436
437
438
439
440
441
442
443
444
445
446
447
448
449

  (void) data;

  /* Query the security package for DigestSSP */
  status = s_pSecFn->QuerySecurityPackageInfo((TCHAR *) TEXT(SP_NAME_DIGEST),
                                              &SecurityPackage);
  if(status != SEC_E_OK) {
    failf(data, "SSPI: couldn't get auth info");
    return CURLE_AUTH_ERROR;
  }

  token_max = SecurityPackage->cbMaxToken;

  /* Release the package buffer as it is not required anymore */
  s_pSecFn->FreeContextBuffer(SecurityPackage);
607
608
609
610
611
612
613


614
615
616
617
618
619
620
621
622



623
624
625
626
627
628
629
                                                 &resp_desc, &attrs, &expiry);
    curlx_unicodefree(spn);

    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(output_token);

      Curl_safefree(digest->http_context);

      if(status == SEC_E_INSUFFICIENT_MEMORY)
        return CURLE_OUT_OF_MEMORY;




      return CURLE_AUTH_ERROR;
    }

    output_token_len = resp_buf.cbBuffer;

    s_pSecFn->FreeCredentialsHandle(&credentials);







>
>









>
>
>







613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
                                                 &resp_desc, &attrs, &expiry);
    curlx_unicodefree(spn);

    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) {
      char buffer[STRERROR_LEN];

      s_pSecFn->FreeCredentialsHandle(&credentials);

      Curl_sspi_free_identity(p_identity);
      free(output_token);

      Curl_safefree(digest->http_context);

      if(status == SEC_E_INSUFFICIENT_MEMORY)
        return CURLE_OUT_OF_MEMORY;

      infof(data, "schannel: InitializeSecurityContext failed: %s\n",
            Curl_sspi_strerror(status, buffer, sizeof(buffer)));

      return CURLE_AUTH_ERROR;
    }

    output_token_len = resp_buf.cbBuffer;

    s_pSecFn->FreeCredentialsHandle(&credentials);
Changes to jni/curl/lib/vauth/krb5_sspi.c.
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135

  if(!krb5->output_token) {
    /* Query the security package for Kerberos */
    status = s_pSecFn->QuerySecurityPackageInfo((TCHAR *)
                                                TEXT(SP_NAME_KERBEROS),
                                                &SecurityPackage);
    if(status != SEC_E_OK) {
      failf(data, "SSPI: couldn't get auth info\n");
      return CURLE_AUTH_ERROR;
    }

    krb5->token_max = SecurityPackage->cbMaxToken;

    /* Release the package buffer as it is not required anymore */
    s_pSecFn->FreeContextBuffer(SecurityPackage);







|







121
122
123
124
125
126
127
128
129
130
131
132
133
134
135

  if(!krb5->output_token) {
    /* Query the security package for Kerberos */
    status = s_pSecFn->QuerySecurityPackageInfo((TCHAR *)
                                                TEXT(SP_NAME_KERBEROS),
                                                &SecurityPackage);
    if(status != SEC_E_OK) {
      failf(data, "SSPI: couldn't get auth info");
      return CURLE_AUTH_ERROR;
    }

    krb5->token_max = SecurityPackage->cbMaxToken;

    /* Release the package buffer as it is not required anymore */
    s_pSecFn->FreeContextBuffer(SecurityPackage);
Changes to jni/curl/lib/vauth/ntlm_sspi.c.
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
  /* Clean up any former leftovers and initialise to defaults */
  Curl_auth_cleanup_ntlm(ntlm);

  /* Query the security package for NTLM */
  status = s_pSecFn->QuerySecurityPackageInfo((TCHAR *) TEXT(SP_NAME_NTLM),
                                              &SecurityPackage);
  if(status != SEC_E_OK) {
    failf(data, "SSPI: couldn't get auth info\n");
    return CURLE_AUTH_ERROR;
  }

  ntlm->token_max = SecurityPackage->cbMaxToken;

  /* Release the package buffer as it is not required anymore */
  s_pSecFn->FreeContextBuffer(SecurityPackage);







|







102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
  /* Clean up any former leftovers and initialise to defaults */
  Curl_auth_cleanup_ntlm(ntlm);

  /* Query the security package for NTLM */
  status = s_pSecFn->QuerySecurityPackageInfo((TCHAR *) TEXT(SP_NAME_NTLM),
                                              &SecurityPackage);
  if(status != SEC_E_OK) {
    failf(data, "SSPI: couldn't get auth info");
    return CURLE_AUTH_ERROR;
  }

  ntlm->token_max = SecurityPackage->cbMaxToken;

  /* Release the package buffer as it is not required anymore */
  s_pSecFn->FreeContextBuffer(SecurityPackage);
Changes to jni/curl/lib/vauth/spnego_sspi.c.
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140

  if(!nego->output_token) {
    /* Query the security package for Negotiate */
    nego->status = s_pSecFn->QuerySecurityPackageInfo((TCHAR *)
                                                      TEXT(SP_NAME_NEGOTIATE),
                                                      &SecurityPackage);
    if(nego->status != SEC_E_OK) {
      failf(data, "SSPI: couldn't get auth info\n");
      return CURLE_AUTH_ERROR;
    }

    nego->token_max = SecurityPackage->cbMaxToken;

    /* Release the package buffer as it is not required anymore */
    s_pSecFn->FreeContextBuffer(SecurityPackage);







|







126
127
128
129
130
131
132
133
134
135
136
137
138
139
140

  if(!nego->output_token) {
    /* Query the security package for Negotiate */
    nego->status = s_pSecFn->QuerySecurityPackageInfo((TCHAR *)
                                                      TEXT(SP_NAME_NEGOTIATE),
                                                      &SecurityPackage);
    if(nego->status != SEC_E_OK) {
      failf(data, "SSPI: couldn't get auth info");
      return CURLE_AUTH_ERROR;
    }

    nego->token_max = SecurityPackage->cbMaxToken;

    /* Release the package buffer as it is not required anymore */
    s_pSecFn->FreeContextBuffer(SecurityPackage);
Changes to jni/curl/lib/version.c.
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
 * curl_version() returns a pointer to a static buffer.
 *
 * It is implemented to work multi-threaded by making sure repeated invokes
 * generate the exact same string and never write any temporary data like
 * zeros in the data.
 */

#define VERSION_PARTS 14 /* number of substrings we can concatenate */

char *curl_version(void)
{
  static char out[300];
  char *outp;
  size_t outlen;
  const char *src[VERSION_PARTS];







|







96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
 * curl_version() returns a pointer to a static buffer.
 *
 * It is implemented to work multi-threaded by making sure repeated invokes
 * generate the exact same string and never write any temporary data like
 * zeros in the data.
 */

#define VERSION_PARTS 15 /* number of substrings we can concatenate */

char *curl_version(void)
{
  static char out[300];
  char *outp;
  size_t outlen;
  const char *src[VERSION_PARTS];
140
141
142
143
144
145
146



147
148
149
150
151
152
153
#endif
#ifdef ENABLE_QUIC
  char h3_version[40];
#endif
#ifdef USE_LIBRTMP
  char rtmp_version[40];
#endif



  int i = 0;
  int j;

#ifdef DEBUGBUILD
  /* Override version string when environment variable CURL_VERSION is set */
  const char *debugversion = getenv("CURL_VERSION");
  if(debugversion) {







>
>
>







140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
#endif
#ifdef ENABLE_QUIC
  char h3_version[40];
#endif
#ifdef USE_LIBRTMP
  char rtmp_version[40];
#endif
#ifdef USE_HYPER
  char hyper_buf[30];
#endif
  int i = 0;
  int j;

#ifdef DEBUGBUILD
  /* Override version string when environment variable CURL_VERSION is set */
  const char *debugversion = getenv("CURL_VERSION");
  if(debugversion) {
224
225
226
227
228
229
230




231
232
233
234
235
236
237

    msnprintf(rtmp_version, sizeof(rtmp_version), "librtmp/%d.%d%s",
              RTMP_LIB_VERSION >> 16, (RTMP_LIB_VERSION >> 8) & 0xff,
              suff);
    src[i++] = rtmp_version;
  }
#endif





  DEBUGASSERT(i <= VERSION_PARTS);

  outp = &out[0];
  outlen = sizeof(out);
  for(j = 0; j < i; j++) {
    size_t n = strlen(src[j]);







>
>
>
>







227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244

    msnprintf(rtmp_version, sizeof(rtmp_version), "librtmp/%d.%d%s",
              RTMP_LIB_VERSION >> 16, (RTMP_LIB_VERSION >> 8) & 0xff,
              suff);
    src[i++] = rtmp_version;
  }
#endif
#ifdef USE_HYPER
  msnprintf(hyper_buf, sizeof(hyper_buf), "Hyper/%s", hyper_version());
  src[i++] = hyper_buf;
#endif

  DEBUGASSERT(i <= VERSION_PARTS);

  outp = &out[0];
  outlen = sizeof(out);
  for(j = 0; j < i; j++) {
    size_t n = strlen(src[j]);
269
270
271
272
273
274
275



276
277
278
279
280
281
282
  "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







>
>
>







276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
  "ftp",
#endif
#if defined(USE_SSL) && !defined(CURL_DISABLE_FTP)
  "ftps",
#endif
#ifndef CURL_DISABLE_GOPHER
  "gopher",
#endif
#if defined(USE_SSL) && !defined(CURL_DISABLE_GOPHER)
  "gophers",
#endif
#ifndef CURL_DISABLE_HTTP
  "http",
#endif
#if defined(USE_SSL) && !defined(CURL_DISABLE_HTTP)
  "https",
#endif
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
#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(ENABLE_QUIC)
  | CURL_VERSION_HTTP3
#endif
#if defined(USE_UNIX_SOCKETS)
  | CURL_VERSION_UNIX_SOCKETS







|







400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
#endif
#if defined(CURL_DOES_CONVERSIONS)
  | CURL_VERSION_CONV
#endif
#if defined(USE_TLS_SRP)
  | CURL_VERSION_TLSAUTH_SRP
#endif
#if defined(USE_NGHTTP2) || defined(USE_HYPER)
  | CURL_VERSION_HTTP2
#endif
#if defined(ENABLE_QUIC)
  | CURL_VERSION_HTTP3
#endif
#if defined(USE_UNIX_SOCKETS)
  | CURL_VERSION_UNIX_SOCKETS
443
444
445
446
447
448
449
450

451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
#endif
#ifdef CURL_CA_PATH
  CURL_CA_PATH,  /* capath */
#else
  NULL,
#endif
  0,    /* zstd_ver_num */
  NULL  /* zstd version */

};

curl_version_info_data *curl_version_info(CURLversion stamp)
{
#if defined(USE_SSH)
  static char ssh_buffer[80];
#endif
#ifdef USE_SSL
#ifdef CURL_WITH_MULTI_SSL
  static char ssl_buffer[200];
#else
  static char ssl_buffer[80];
#endif
#endif
#ifdef HAVE_BROTLI
  static char brotli_buffer[80];
#endif
#ifdef HAVE_ZSTD
  static char zstd_buffer[80];
#endif


#ifdef USE_SSL
  Curl_ssl_version(ssl_buffer, sizeof(ssl_buffer));
  version_info.ssl_version = ssl_buffer;
#ifndef CURL_DISABLE_PROXY
  if(Curl_ssl->supports & SSLSUPP_HTTPS_PROXY)
    version_info.features |= CURL_VERSION_HTTPS_PROXY;







|
>




















<







453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481

482
483
484
485
486
487
488
#endif
#ifdef CURL_CA_PATH
  CURL_CA_PATH,  /* capath */
#else
  NULL,
#endif
  0,    /* zstd_ver_num */
  NULL, /* zstd version */
  NULL  /* Hyper version */
};

curl_version_info_data *curl_version_info(CURLversion stamp)
{
#if defined(USE_SSH)
  static char ssh_buffer[80];
#endif
#ifdef USE_SSL
#ifdef CURL_WITH_MULTI_SSL
  static char ssl_buffer[200];
#else
  static char ssl_buffer[80];
#endif
#endif
#ifdef HAVE_BROTLI
  static char brotli_buffer[80];
#endif
#ifdef HAVE_ZSTD
  static char zstd_buffer[80];
#endif


#ifdef USE_SSL
  Curl_ssl_version(ssl_buffer, sizeof(ssl_buffer));
  version_info.ssl_version = ssl_buffer;
#ifndef CURL_DISABLE_PROXY
  if(Curl_ssl->supports & SSLSUPP_HTTPS_PROXY)
    version_info.features |= CURL_VERSION_HTTPS_PROXY;
539
540
541
542
543
544
545








546
547
548
549
#ifdef ENABLE_QUIC
  {
    static char quicbuffer[80];
    Curl_quic_ver(quicbuffer, sizeof(quicbuffer));
    version_info.quic_version = quicbuffer;
  }
#endif









  (void)stamp; /* avoid compiler warnings, we don't use this */
  return &version_info;
}







>
>
>
>
>
>
>
>




549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
#ifdef ENABLE_QUIC
  {
    static char quicbuffer[80];
    Curl_quic_ver(quicbuffer, sizeof(quicbuffer));
    version_info.quic_version = quicbuffer;
  }
#endif

#ifdef USE_HYPER
  {
    static char hyper_buffer[30];
    msnprintf(hyper_buffer, sizeof(hyper_buffer), "Hyper/%s", hyper_version());
    version_info.hyper_version = hyper_buffer;
  }
#endif

  (void)stamp; /* avoid compiler warnings, we don't use this */
  return &version_info;
}
Changes to jni/curl/lib/vquic/ngtcp2.c.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2020, 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 https://curl.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







|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2021, 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 https://curl.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
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
#elif defined(USE_GNUTLS)
#define QUIC_PRIORITY \
  "NORMAL:-VERS-ALL:+VERS-TLS1.3:-CIPHER-ALL:+AES-128-GCM:+AES-256-GCM:" \
  "+CHACHA20-POLY1305:+AES-128-CCM:-GROUP-ALL:+GROUP-SECP256R1:" \
  "+GROUP-X25519:+GROUP-SECP384R1:+GROUP-SECP521R1"
#endif

static CURLcode ng_process_ingress(struct connectdata *conn,
                                   curl_socket_t sockfd,
                                   struct quicsocket *qs);
static CURLcode ng_flush_egress(struct connectdata *conn, int sockfd,
                                struct quicsocket *qs);
static int cb_h3_acked_stream_data(nghttp3_conn *conn, int64_t stream_id,
                                   size_t datalen, void *user_data,
                                   void *stream_user_data);

static ngtcp2_tstamp timestamp(void)
{







|


|







83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
#elif defined(USE_GNUTLS)
#define QUIC_PRIORITY \
  "NORMAL:-VERS-ALL:+VERS-TLS1.3:-CIPHER-ALL:+AES-128-GCM:+AES-256-GCM:" \
  "+CHACHA20-POLY1305:+AES-128-CCM:-GROUP-ALL:+GROUP-SECP256R1:" \
  "+GROUP-X25519:+GROUP-SECP384R1:+GROUP-SECP521R1"
#endif

static CURLcode ng_process_ingress(struct Curl_easy *data,
                                   curl_socket_t sockfd,
                                   struct quicsocket *qs);
static CURLcode ng_flush_egress(struct Curl_easy *data, int sockfd,
                                struct quicsocket *qs);
static int cb_h3_acked_stream_data(nghttp3_conn *conn, int64_t stream_id,
                                   size_t datalen, void *user_data,
                                   void *stream_user_data);

static ngtcp2_tstamp timestamp(void)
{
166
167
168
169
170
171
172

173

174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193

}

static void quic_settings(struct quicsocket *qs,
                          uint64_t stream_buffer_size)
{
  ngtcp2_settings *s = &qs->settings;

  ngtcp2_settings_default(s);

#ifdef DEBUG_NGTCP2
  s->log_printf = quic_printf;
#else
  s->log_printf = NULL;
#endif
  s->initial_ts = timestamp();
  s->transport_params.initial_max_stream_data_bidi_local = stream_buffer_size;
  s->transport_params.initial_max_stream_data_bidi_remote = QUIC_MAX_STREAMS;
  s->transport_params.initial_max_stream_data_uni = QUIC_MAX_STREAMS;
  s->transport_params.initial_max_data = QUIC_MAX_DATA;
  s->transport_params.initial_max_streams_bidi = 1;
  s->transport_params.initial_max_streams_uni = 3;
  s->transport_params.max_idle_timeout = QUIC_IDLE_TIMEOUT;
  if(qs->qlogfd != -1) {
    s->qlog.write = qlog_callback;
  }
}

#ifdef USE_OPENSSL
static void keylog_callback(const SSL *ssl, const char *line)







>

>






|
|
|
|
|
|
|







166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195

}

static void quic_settings(struct quicsocket *qs,
                          uint64_t stream_buffer_size)
{
  ngtcp2_settings *s = &qs->settings;
  ngtcp2_transport_params *t = &qs->transport_params;
  ngtcp2_settings_default(s);
  ngtcp2_transport_params_default(t);
#ifdef DEBUG_NGTCP2
  s->log_printf = quic_printf;
#else
  s->log_printf = NULL;
#endif
  s->initial_ts = timestamp();
  t->initial_max_stream_data_bidi_local = stream_buffer_size;
  t->initial_max_stream_data_bidi_remote = QUIC_MAX_STREAMS;
  t->initial_max_stream_data_uni = QUIC_MAX_STREAMS;
  t->initial_max_data = QUIC_MAX_DATA;
  t->initial_max_streams_bidi = 1;
  t->initial_max_streams_uni = 3;
  t->max_idle_timeout = QUIC_IDLE_TIMEOUT;
  if(qs->qlogfd != -1) {
    s->qlog.write = qlog_callback;
  }
}

#ifdef USE_OPENSSL
static void keylog_callback(const SSL *ssl, const char *line)
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
    return NGTCP2_ERR_CRYPTO;

  return 0;
}

static int cb_handshake_completed(ngtcp2_conn *tconn, void *user_data)
{
  struct quicsocket *qs = (struct quicsocket *)user_data;
  (void)tconn;
  infof(qs->conn->data, "QUIC handshake is completed\n");

  return 0;
}

static void extend_stream_window(ngtcp2_conn *tconn,
                                 struct HTTP *stream)
{
  size_t thismuch = stream->unacked_window;







|

<
<







554
555
556
557
558
559
560
561
562


563
564
565
566
567
568
569
    return NGTCP2_ERR_CRYPTO;

  return 0;
}

static int cb_handshake_completed(ngtcp2_conn *tconn, void *user_data)
{
  (void)user_data;
  (void)tconn;


  return 0;
}

static void extend_stream_window(ngtcp2_conn *tconn,
                                 struct HTTP *stream)
{
  size_t thismuch = stream->unacked_window;
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
  int fin = flags & NGTCP2_STREAM_DATA_FLAG_FIN ? 1 : 0;
  (void)offset;
  (void)stream_user_data;

  nconsumed =
    nghttp3_conn_read_stream(qs->h3conn, stream_id, buf, buflen, fin);
  if(nconsumed < 0) {
    failf(qs->conn->data, "nghttp3_conn_read_stream returned error: %s\n",
          nghttp3_strerror((int)nconsumed));
    return NGTCP2_ERR_CALLBACK_FAILURE;
  }

  /* number of bytes inside buflen which consists of framing overhead
   * including QPACK HEADERS. In other words, it does not consume payload of
   * DATA frame. */
  ngtcp2_conn_extend_max_stream_offset(tconn, stream_id, nconsumed);







<
<







583
584
585
586
587
588
589


590
591
592
593
594
595
596
  int fin = flags & NGTCP2_STREAM_DATA_FLAG_FIN ? 1 : 0;
  (void)offset;
  (void)stream_user_data;

  nconsumed =
    nghttp3_conn_read_stream(qs->h3conn, stream_id, buf, buflen, fin);
  if(nconsumed < 0) {


    return NGTCP2_ERR_CALLBACK_FAILURE;
  }

  /* number of bytes inside buflen which consists of framing overhead
   * including QPACK HEADERS. In other words, it does not consume payload of
   * DATA frame. */
  ngtcp2_conn_extend_max_stream_offset(tconn, stream_id, nconsumed);
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
  (void)tconn;
  (void)offset;
  (void)datalen;
  (void)stream_user_data;

  rv = nghttp3_conn_add_ack_offset(qs->h3conn, stream_id, datalen);
  if(rv != 0) {
    failf(qs->conn->data, "nghttp3_conn_add_ack_offset returned error: %s\n",
          nghttp3_strerror(rv));
    return NGTCP2_ERR_CALLBACK_FAILURE;
  }

  return 0;
}

static int cb_stream_close(ngtcp2_conn *tconn, int64_t stream_id,
                           uint64_t app_error_code,
                           void *user_data, void *stream_user_data)
{
  struct quicsocket *qs = (struct quicsocket *)user_data;
  int rv;
  (void)tconn;
  (void)stream_user_data;
  /* stream is closed... */

  rv = nghttp3_conn_close_stream(qs->h3conn, stream_id,
                                 app_error_code);
  if(rv != 0) {
    failf(qs->conn->data, "nghttp3_conn_close_stream returned error: %s\n",
          nghttp3_strerror(rv));
    return NGTCP2_ERR_CALLBACK_FAILURE;
  }

  return 0;
}

static int cb_stream_reset(ngtcp2_conn *tconn, int64_t stream_id,
                           uint64_t final_size, uint64_t app_error_code,
                           void *user_data, void *stream_user_data)
{
  struct quicsocket *qs = (struct quicsocket *)user_data;
  int rv;
  (void)tconn;
  (void)final_size;
  (void)app_error_code;
  (void)stream_user_data;

  rv = nghttp3_conn_reset_stream(qs->h3conn, stream_id);
  if(rv != 0) {
    failf(qs->conn->data, "nghttp3_conn_reset_stream returned error: %s\n",
          nghttp3_strerror(rv));
    return NGTCP2_ERR_CALLBACK_FAILURE;
  }

  return 0;
}

static int cb_extend_max_local_streams_bidi(ngtcp2_conn *tconn,







<
<



















<
<



















<
<







610
611
612
613
614
615
616


617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635


636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654


655
656
657
658
659
660
661
  (void)tconn;
  (void)offset;
  (void)datalen;
  (void)stream_user_data;

  rv = nghttp3_conn_add_ack_offset(qs->h3conn, stream_id, datalen);
  if(rv != 0) {


    return NGTCP2_ERR_CALLBACK_FAILURE;
  }

  return 0;
}

static int cb_stream_close(ngtcp2_conn *tconn, int64_t stream_id,
                           uint64_t app_error_code,
                           void *user_data, void *stream_user_data)
{
  struct quicsocket *qs = (struct quicsocket *)user_data;
  int rv;
  (void)tconn;
  (void)stream_user_data;
  /* stream is closed... */

  rv = nghttp3_conn_close_stream(qs->h3conn, stream_id,
                                 app_error_code);
  if(rv != 0) {


    return NGTCP2_ERR_CALLBACK_FAILURE;
  }

  return 0;
}

static int cb_stream_reset(ngtcp2_conn *tconn, int64_t stream_id,
                           uint64_t final_size, uint64_t app_error_code,
                           void *user_data, void *stream_user_data)
{
  struct quicsocket *qs = (struct quicsocket *)user_data;
  int rv;
  (void)tconn;
  (void)final_size;
  (void)app_error_code;
  (void)stream_user_data;

  rv = nghttp3_conn_reset_stream(qs->h3conn, stream_id);
  if(rv != 0) {


    return NGTCP2_ERR_CALLBACK_FAILURE;
  }

  return 0;
}

static int cb_extend_max_local_streams_bidi(ngtcp2_conn *tconn,
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706

707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
  int rv;
  (void)tconn;
  (void)max_data;
  (void)stream_user_data;

  rv = nghttp3_conn_unblock_stream(qs->h3conn, stream_id);
  if(rv != 0) {
    failf(qs->conn->data, "nghttp3_conn_unblock_stream returned error: %s\n",
          nghttp3_strerror(rv));
    return NGTCP2_ERR_CALLBACK_FAILURE;
  }

  return 0;
}

static int cb_get_new_connection_id(ngtcp2_conn *tconn, ngtcp2_cid *cid,
                                    uint8_t *token, size_t cidlen,
                                    void *user_data)
{
  struct quicsocket *qs = (struct quicsocket *)user_data;
  CURLcode result;
  (void)tconn;


  result = Curl_rand(qs->conn->data, cid->data, cidlen);
  if(result)
    return NGTCP2_ERR_CALLBACK_FAILURE;
  cid->datalen = cidlen;

  result = Curl_rand(qs->conn->data, token, NGTCP2_STATELESS_RESET_TOKENLEN);
  if(result)
    return NGTCP2_ERR_CALLBACK_FAILURE;

  return 0;
}

static ngtcp2_conn_callbacks ng_callbacks = {
  ngtcp2_crypto_client_initial_cb,
  NULL, /* recv_client_initial */
  cb_recv_crypto_data,
  cb_handshake_completed,
  NULL, /* recv_version_negotiation */
  ngtcp2_crypto_encrypt_cb,
  ngtcp2_crypto_decrypt_cb,







<
<










<


>

|




|






|







677
678
679
680
681
682
683


684
685
686
687
688
689
690
691
692
693

694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
  int rv;
  (void)tconn;
  (void)max_data;
  (void)stream_user_data;

  rv = nghttp3_conn_unblock_stream(qs->h3conn, stream_id);
  if(rv != 0) {


    return NGTCP2_ERR_CALLBACK_FAILURE;
  }

  return 0;
}

static int cb_get_new_connection_id(ngtcp2_conn *tconn, ngtcp2_cid *cid,
                                    uint8_t *token, size_t cidlen,
                                    void *user_data)
{

  CURLcode result;
  (void)tconn;
  (void)user_data;

  result = Curl_rand(NULL, cid->data, cidlen);
  if(result)
    return NGTCP2_ERR_CALLBACK_FAILURE;
  cid->datalen = cidlen;

  result = Curl_rand(NULL, token, NGTCP2_STATELESS_RESET_TOKENLEN);
  if(result)
    return NGTCP2_ERR_CALLBACK_FAILURE;

  return 0;
}

static ngtcp2_callbacks ng_callbacks = {
  ngtcp2_crypto_client_initial_cb,
  NULL, /* recv_client_initial */
  cb_recv_crypto_data,
  cb_handshake_completed,
  NULL, /* recv_version_negotiation */
  ngtcp2_crypto_encrypt_cb,
  ngtcp2_crypto_decrypt_cb,
751
752
753
754
755
756
757
758

759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
  ngtcp2_crypto_delete_crypto_aead_ctx_cb,
  ngtcp2_crypto_delete_crypto_cipher_ctx_cb
};

/*
 * Might be called twice for happy eyeballs.
 */
CURLcode Curl_quic_connect(struct connectdata *conn,

                           curl_socket_t sockfd,
                           int sockindex,
                           const struct sockaddr *addr,
                           socklen_t addrlen)
{
  int rc;
  int rv;
  CURLcode result;
  ngtcp2_path path; /* TODO: this must be initialized properly */
  struct Curl_easy *data = conn->data;
  struct quicsocket *qs = &conn->hequic[sockindex];
  char ipbuf[40];
  long port;
  int qfd;

  if(qs->conn)
    Curl_quic_disconnect(conn, sockindex);
  qs->conn = conn;

  /* extract the used address as a string */
  if(!Curl_addr2string((struct sockaddr*)addr, addrlen, ipbuf, &port)) {
    char buffer[STRERROR_LEN];
    failf(data, "ssrem inet_ntop() failed with errno %d: %s",
          SOCKERRNO, Curl_strerror(SOCKERRNO, buffer, sizeof(buffer)));







|
>









<






|







741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758

759
760
761
762
763
764
765
766
767
768
769
770
771
772
  ngtcp2_crypto_delete_crypto_aead_ctx_cb,
  ngtcp2_crypto_delete_crypto_cipher_ctx_cb
};

/*
 * Might be called twice for happy eyeballs.
 */
CURLcode Curl_quic_connect(struct Curl_easy *data,
                           struct connectdata *conn,
                           curl_socket_t sockfd,
                           int sockindex,
                           const struct sockaddr *addr,
                           socklen_t addrlen)
{
  int rc;
  int rv;
  CURLcode result;
  ngtcp2_path path; /* TODO: this must be initialized properly */

  struct quicsocket *qs = &conn->hequic[sockindex];
  char ipbuf[40];
  long port;
  int qfd;

  if(qs->conn)
    Curl_quic_disconnect(data, conn, sockindex);
  qs->conn = conn;

  /* extract the used address as a string */
  if(!Curl_addr2string((struct sockaddr*)addr, addrlen, ipbuf, &port)) {
    char buffer[STRERROR_LEN];
    failf(data, "ssrem inet_ntop() failed with errno %d: %s",
          SOCKERRNO, Curl_strerror(SOCKERRNO, buffer, sizeof(buffer)));
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845

846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876

  ngtcp2_addr_init(&path.local, (struct sockaddr *)&qs->local_addr,
                   qs->local_addrlen, NULL);
  ngtcp2_addr_init(&path.remote, addr, addrlen, NULL);

  rc = ngtcp2_conn_client_new(&qs->qconn, &qs->dcid, &qs->scid, &path,
                              NGTCP2_PROTO_VER_MIN, &ng_callbacks,
                              &qs->settings, NULL, qs);
  if(rc)
    return CURLE_QUIC_CONNECT_ERROR;

  ngtcp2_conn_set_tls_native_handle(qs->qconn, qs->ssl);

  return CURLE_OK;
}

/*
 * Store ngtp2 version info in this buffer, Prefix with a space.  Return total
 * length written.
 */
int Curl_quic_ver(char *p, size_t len)
{
  ngtcp2_info *ng2 = ngtcp2_version(0);
  nghttp3_info *ht3 = nghttp3_version(0);
  return msnprintf(p, len, "ngtcp2/%s nghttp3/%s",
                   ng2->version_str, ht3->version_str);
}


static int ng_getsock(struct connectdata *conn, curl_socket_t *socks)
{
  struct SingleRequest *k = &conn->data->req;
  int bitmap = GETSOCK_BLANK;

  socks[0] = conn->sock[FIRSTSOCKET];

  /* in a HTTP/2 connection we can basically always get a frame so we should
     always be ready for one */
  bitmap |= GETSOCK_READSOCK(FIRSTSOCKET);

  /* we're still uploading or the HTTP/2 layer wants to send data */
  if((k->keepon & (KEEP_SEND|KEEP_SEND_PAUSE)) == KEEP_SEND)
    bitmap |= GETSOCK_WRITESOCK(FIRSTSOCKET);

  return bitmap;
}

static int ng_perform_getsock(const struct connectdata *conn,
                              curl_socket_t *socks)
{
  return ng_getsock((struct connectdata *)conn, socks);
}

static void qs_disconnect(struct quicsocket *qs)
{
  int i;
  if(!qs->conn) /* already closed */
    return;
  qs->conn = NULL;
  if(qs->qlogfd != -1) {







|




















>
|

|















<
<
<
<
<
<







808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854






855
856
857
858
859
860
861

  ngtcp2_addr_init(&path.local, (struct sockaddr *)&qs->local_addr,
                   qs->local_addrlen, NULL);
  ngtcp2_addr_init(&path.remote, addr, addrlen, NULL);

  rc = ngtcp2_conn_client_new(&qs->qconn, &qs->dcid, &qs->scid, &path,
                              NGTCP2_PROTO_VER_MIN, &ng_callbacks,
                              &qs->settings, &qs->transport_params, NULL, qs);
  if(rc)
    return CURLE_QUIC_CONNECT_ERROR;

  ngtcp2_conn_set_tls_native_handle(qs->qconn, qs->ssl);

  return CURLE_OK;
}

/*
 * Store ngtp2 version info in this buffer, Prefix with a space.  Return total
 * length written.
 */
int Curl_quic_ver(char *p, size_t len)
{
  ngtcp2_info *ng2 = ngtcp2_version(0);
  nghttp3_info *ht3 = nghttp3_version(0);
  return msnprintf(p, len, "ngtcp2/%s nghttp3/%s",
                   ng2->version_str, ht3->version_str);
}

static int ng_getsock(struct Curl_easy *data, struct connectdata *conn,
                      curl_socket_t *socks)
{
  struct SingleRequest *k = &data->req;
  int bitmap = GETSOCK_BLANK;

  socks[0] = conn->sock[FIRSTSOCKET];

  /* in a HTTP/2 connection we can basically always get a frame so we should
     always be ready for one */
  bitmap |= GETSOCK_READSOCK(FIRSTSOCKET);

  /* we're still uploading or the HTTP/2 layer wants to send data */
  if((k->keepon & (KEEP_SEND|KEEP_SEND_PAUSE)) == KEEP_SEND)
    bitmap |= GETSOCK_WRITESOCK(FIRSTSOCKET);

  return bitmap;
}







static void qs_disconnect(struct quicsocket *qs)
{
  int i;
  if(!qs->conn) /* already closed */
    return;
  qs->conn = NULL;
  if(qs->qlogfd != -1) {
893
894
895
896
897
898
899
900

901
902

903
904
905
906
907

908
909
910
911
912
913
914
915
916

917
918

919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
  nghttp3_conn_del(qs->h3conn);
  ngtcp2_conn_del(qs->qconn);
#ifdef USE_OPENSSL
  SSL_CTX_free(qs->sslctx);
#endif
}

void Curl_quic_disconnect(struct connectdata *conn,

                          int tempindex)
{

  if(conn->transport == TRNSPRT_QUIC)
    qs_disconnect(&conn->hequic[tempindex]);
}

static CURLcode ng_disconnect(struct connectdata *conn,

                              bool dead_connection)
{
  (void)dead_connection;
  Curl_quic_disconnect(conn, 0);
  Curl_quic_disconnect(conn, 1);
  return CURLE_OK;
}

static unsigned int ng_conncheck(struct connectdata *conn,

                                 unsigned int checks_to_perform)
{

  (void)conn;
  (void)checks_to_perform;
  return CONNRESULT_NONE;
}

static const struct Curl_handler Curl_handler_http3 = {
  "HTTPS",                              /* 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 */
  ng_getsock,                           /* proto_getsock */
  ng_getsock,                           /* doing_getsock */
  ZERO_NULL,                            /* domore_getsock */
  ng_perform_getsock,                   /* perform_getsock */
  ng_disconnect,                        /* disconnect */
  ZERO_NULL,                            /* readwrite */
  ng_conncheck,                         /* connection_check */
  PORT_HTTP,                            /* defport */
  CURLPROTO_HTTPS,                      /* protocol */
  CURLPROTO_HTTP,                       /* family */
  PROTOPT_SSL | PROTOPT_STREAM          /* flags */







|
>


>




|
>



|
|



|
>


>

















|







878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
  nghttp3_conn_del(qs->h3conn);
  ngtcp2_conn_del(qs->qconn);
#ifdef USE_OPENSSL
  SSL_CTX_free(qs->sslctx);
#endif
}

void Curl_quic_disconnect(struct Curl_easy *data,
                          struct connectdata *conn,
                          int tempindex)
{
  (void)data;
  if(conn->transport == TRNSPRT_QUIC)
    qs_disconnect(&conn->hequic[tempindex]);
}

static CURLcode ng_disconnect(struct Curl_easy *data,
                              struct connectdata *conn,
                              bool dead_connection)
{
  (void)dead_connection;
  Curl_quic_disconnect(data, conn, 0);
  Curl_quic_disconnect(data, conn, 1);
  return CURLE_OK;
}

static unsigned int ng_conncheck(struct Curl_easy *data,
                                 struct connectdata *conn,
                                 unsigned int checks_to_perform)
{
  (void)data;
  (void)conn;
  (void)checks_to_perform;
  return CONNRESULT_NONE;
}

static const struct Curl_handler Curl_handler_http3 = {
  "HTTPS",                              /* 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 */
  ng_getsock,                           /* proto_getsock */
  ng_getsock,                           /* doing_getsock */
  ZERO_NULL,                            /* domore_getsock */
  ng_getsock,                           /* perform_getsock */
  ng_disconnect,                        /* disconnect */
  ZERO_NULL,                            /* readwrite */
  ng_conncheck,                         /* connection_check */
  PORT_HTTP,                            /* defport */
  CURLPROTO_HTTPS,                      /* protocol */
  CURLPROTO_HTTP,                       /* family */
  PROTOPT_SSL | PROTOPT_STREAM          /* flags */
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
  (void)stream_id;
  (void)app_error_code;
  (void)user_data;
  (void)stream_user_data;
  return 0;
}

static nghttp3_conn_callbacks ngh3_callbacks = {
  cb_h3_acked_stream_data, /* acked_stream_data */
  cb_h3_stream_close,
  cb_h3_recv_data,
  cb_h3_deferred_consume,
  NULL, /* begin_headers */
  cb_h3_recv_header,
  cb_h3_end_headers,







|







1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
  (void)stream_id;
  (void)app_error_code;
  (void)user_data;
  (void)stream_user_data;
  return 0;
}

static nghttp3_callbacks ngh3_callbacks = {
  cb_h3_acked_stream_data, /* acked_stream_data */
  cb_h3_stream_close,
  cb_h3_recv_data,
  cb_h3_deferred_consume,
  NULL, /* begin_headers */
  cb_h3_recv_header,
  cb_h3_end_headers,
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
static int init_ngh3_conn(struct quicsocket *qs)
{
  CURLcode result;
  int rc;
  int64_t ctrl_stream_id, qpack_enc_stream_id, qpack_dec_stream_id;

  if(ngtcp2_conn_get_max_local_streams_uni(qs->qconn) < 3) {
    failf(qs->conn->data, "too few available QUIC streams");
    return CURLE_QUIC_CONNECT_ERROR;
  }

  nghttp3_conn_settings_default(&qs->h3settings);

  rc = nghttp3_conn_client_new(&qs->h3conn,
                               &ngh3_callbacks,
                               &qs->h3settings,
                               nghttp3_mem_default(),
                               qs);
  if(rc) {







<



|







1148
1149
1150
1151
1152
1153
1154

1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
static int init_ngh3_conn(struct quicsocket *qs)
{
  CURLcode result;
  int rc;
  int64_t ctrl_stream_id, qpack_enc_stream_id, qpack_dec_stream_id;

  if(ngtcp2_conn_get_max_local_streams_uni(qs->qconn) < 3) {

    return CURLE_QUIC_CONNECT_ERROR;
  }

  nghttp3_settings_default(&qs->h3settings);

  rc = nghttp3_conn_client_new(&qs->h3conn,
                               &ngh3_callbacks,
                               &qs->h3settings,
                               nghttp3_mem_default(),
                               qs);
  if(rc) {
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243

1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313







1314
1315
1316
1317
1318
1319
1320
      /* make the buffer only keep the tail */
      (void)Curl_dyn_tail(&stream->overflow, overlen - ncopy);
  }
  return ncopy;
}

/* incoming data frames on the h3 stream */
static ssize_t ngh3_stream_recv(struct connectdata *conn,
                                int sockindex,
                                char *buf,
                                size_t buffersize,
                                CURLcode *curlcode)
{

  curl_socket_t sockfd = conn->sock[sockindex];
  struct HTTP *stream = conn->data->req.p.http;
  struct quicsocket *qs = conn->quic;

  if(!stream->memlen) {
    /* remember where to store incoming data for this stream and how big the
       buffer is */
    stream->mem = buf;
    stream->len = buffersize;
  }
  /* else, there's data in the buffer already */

  /* if there's data in the overflow buffer from a previous call, copy as much
     as possible to the receive buffer before receiving more */
  drain_overflow_buffer(stream);

  if(ng_process_ingress(conn, sockfd, qs)) {
    *curlcode = CURLE_RECV_ERROR;
    return -1;
  }
  if(ng_flush_egress(conn, sockfd, qs)) {
    *curlcode = CURLE_SEND_ERROR;
    return -1;
  }

  if(stream->memlen) {
    ssize_t memlen = stream->memlen;
    /* data arrived */
    *curlcode = CURLE_OK;
    /* reset to allow more data to come */
    stream->memlen = 0;
    stream->mem = buf;
    stream->len = buffersize;
    /* extend the stream window with the data we're consuming and send out
       any additional packets to tell the server that we can receive more */
    extend_stream_window(qs->qconn, stream);
    if(ng_flush_egress(conn, sockfd, qs)) {
      *curlcode = CURLE_SEND_ERROR;
      return -1;
    }
    return memlen;
  }

  if(stream->closed) {
    *curlcode = CURLE_OK;
    return 0;
  }

  infof(conn->data, "ngh3_stream_recv returns 0 bytes and EAGAIN\n");
  *curlcode = CURLE_AGAIN;
  return -1;
}

/* this amount of data has now been acked on this stream */
static int cb_h3_acked_stream_data(nghttp3_conn *conn, int64_t stream_id,
                                   size_t datalen, void *user_data,
                                   void *stream_user_data)
{
  struct Curl_easy *data = stream_user_data;
  struct HTTP *stream = data->req.p.http;
  (void)conn;
  (void)stream_id;
  (void)user_data;

  if(!data->set.postfields) {
    stream->h3out->used -= datalen;
    H3BUGF(infof(data,
                 "cb_h3_acked_stream_data, %zd bytes, %zd left unacked\n",
                 datalen, stream->h3out->used));
    DEBUGASSERT(stream->h3out->used < H3_SEND_SIZE);







  }
  return 0;
}

static ssize_t cb_h3_readfunction(nghttp3_conn *conn, int64_t stream_id,
                                  nghttp3_vec *vec, size_t veccnt,
                                  uint32_t *pflags, void *user_data,







|





>

|














|



|















|











|











|
<








>
>
>
>
>
>
>







1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294

1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
      /* make the buffer only keep the tail */
      (void)Curl_dyn_tail(&stream->overflow, overlen - ncopy);
  }
  return ncopy;
}

/* incoming data frames on the h3 stream */
static ssize_t ngh3_stream_recv(struct Curl_easy *data,
                                int sockindex,
                                char *buf,
                                size_t buffersize,
                                CURLcode *curlcode)
{
  struct connectdata *conn = data->conn;
  curl_socket_t sockfd = conn->sock[sockindex];
  struct HTTP *stream = data->req.p.http;
  struct quicsocket *qs = conn->quic;

  if(!stream->memlen) {
    /* remember where to store incoming data for this stream and how big the
       buffer is */
    stream->mem = buf;
    stream->len = buffersize;
  }
  /* else, there's data in the buffer already */

  /* if there's data in the overflow buffer from a previous call, copy as much
     as possible to the receive buffer before receiving more */
  drain_overflow_buffer(stream);

  if(ng_process_ingress(data, sockfd, qs)) {
    *curlcode = CURLE_RECV_ERROR;
    return -1;
  }
  if(ng_flush_egress(data, sockfd, qs)) {
    *curlcode = CURLE_SEND_ERROR;
    return -1;
  }

  if(stream->memlen) {
    ssize_t memlen = stream->memlen;
    /* data arrived */
    *curlcode = CURLE_OK;
    /* reset to allow more data to come */
    stream->memlen = 0;
    stream->mem = buf;
    stream->len = buffersize;
    /* extend the stream window with the data we're consuming and send out
       any additional packets to tell the server that we can receive more */
    extend_stream_window(qs->qconn, stream);
    if(ng_flush_egress(data, sockfd, qs)) {
      *curlcode = CURLE_SEND_ERROR;
      return -1;
    }
    return memlen;
  }

  if(stream->closed) {
    *curlcode = CURLE_OK;
    return 0;
  }

  infof(data, "ngh3_stream_recv returns 0 bytes and EAGAIN\n");
  *curlcode = CURLE_AGAIN;
  return -1;
}

/* this amount of data has now been acked on this stream */
static int cb_h3_acked_stream_data(nghttp3_conn *conn, int64_t stream_id,
                                   size_t datalen, void *user_data,
                                   void *stream_user_data)
{
  struct Curl_easy *data = stream_user_data;
  struct HTTP *stream = data->req.p.http;
  int rv;

  (void)user_data;

  if(!data->set.postfields) {
    stream->h3out->used -= datalen;
    H3BUGF(infof(data,
                 "cb_h3_acked_stream_data, %zd bytes, %zd left unacked\n",
                 datalen, stream->h3out->used));
    DEBUGASSERT(stream->h3out->used < H3_SEND_SIZE);

    if(stream->h3out->used == 0) {
      rv = nghttp3_conn_resume_stream(conn, stream_id);
      if(rv != 0) {
        return NGTCP2_ERR_CALLBACK_FAILURE;
      }
    }
  }
  return 0;
}

static ssize_t cb_h3_readfunction(nghttp3_conn *conn, int64_t stream_id,
                                  nghttp3_vec *vec, size_t veccnt,
                                  uint32_t *pflags, void *user_data,
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354



1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387

1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
       only return consecutive data, copy the amount that fits and the next
       part comes in next invoke. */
    struct h3out *out = stream->h3out;
    if(nread + out->windex > H3_SEND_SIZE)
      nread = H3_SEND_SIZE - out->windex;

    memcpy(&out->buf[out->windex], stream->upload_mem, nread);
    out->windex += nread;
    out->used += nread;

    /* that's the chunk we return to nghttp3 */
    vec[0].base = &out->buf[out->windex];
    vec[0].len = nread;




    if(out->windex == H3_SEND_SIZE)
      out->windex = 0; /* wrap */
    stream->upload_mem += nread;
    stream->upload_len -= nread;
    if(data->state.infilesize != -1) {
      stream->upload_left -= nread;
      if(!stream->upload_left)
        *pflags = NGHTTP3_DATA_FLAG_EOF;
    }
    H3BUGF(infof(data, "cb_h3_readfunction %zd bytes%s (at %zd unacked)\n",
                 nread, *pflags == NGHTTP3_DATA_FLAG_EOF?" EOF":"",
                 out->used));
  }
  if(stream->upload_done && !stream->upload_len &&
     (stream->upload_left <= 0)) {
    H3BUGF(infof(data, "!!!!!!!!! cb_h3_readfunction sets EOF\n"));
    *pflags = NGHTTP3_DATA_FLAG_EOF;
    return 0;
  }
  else if(!nread) {
    return NGHTTP3_ERR_WOULDBLOCK;
  }
  return 1;
}

/* Index where :authority header field will appear in request header
   field list. */
#define AUTHORITY_DST_IDX 3

static CURLcode http_request(struct connectdata *conn, const void *mem,
                             size_t len)
{

  struct HTTP *stream = conn->data->req.p.http;
  size_t nheader;
  size_t i;
  size_t authority_idx;
  char *hdbuf = (char *)mem;
  char *end, *line_end;
  struct quicsocket *qs = conn->quic;
  CURLcode result = CURLE_OK;
  struct Curl_easy *data = conn->data;
  nghttp3_nv *nva = NULL;
  int64_t stream3_id;
  int rc;
  struct h3out *h3out = NULL;

  rc = ngtcp2_conn_open_bidi_stream(qs->qconn, &stream3_id, NULL);
  if(rc) {
    failf(conn->data, "can get bidi streams");
    result = CURLE_SEND_ERROR;
    goto fail;
  }

  stream->stream3_id = stream3_id;
  stream->h3req = TRUE; /* senf off! */
  Curl_dyn_init(&stream->overflow, CURL_MAX_READ_SIZE);







<
<




>
>
>


















|











|


>
|







<







|







1338
1339
1340
1341
1342
1343
1344


1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393

1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
       only return consecutive data, copy the amount that fits and the next
       part comes in next invoke. */
    struct h3out *out = stream->h3out;
    if(nread + out->windex > H3_SEND_SIZE)
      nread = H3_SEND_SIZE - out->windex;

    memcpy(&out->buf[out->windex], stream->upload_mem, nread);



    /* that's the chunk we return to nghttp3 */
    vec[0].base = &out->buf[out->windex];
    vec[0].len = nread;

    out->windex += nread;
    out->used += nread;

    if(out->windex == H3_SEND_SIZE)
      out->windex = 0; /* wrap */
    stream->upload_mem += nread;
    stream->upload_len -= nread;
    if(data->state.infilesize != -1) {
      stream->upload_left -= nread;
      if(!stream->upload_left)
        *pflags = NGHTTP3_DATA_FLAG_EOF;
    }
    H3BUGF(infof(data, "cb_h3_readfunction %zd bytes%s (at %zd unacked)\n",
                 nread, *pflags == NGHTTP3_DATA_FLAG_EOF?" EOF":"",
                 out->used));
  }
  if(stream->upload_done && !stream->upload_len &&
     (stream->upload_left <= 0)) {
    H3BUGF(infof(data, "!!!!!!!!! cb_h3_readfunction sets EOF\n"));
    *pflags = NGHTTP3_DATA_FLAG_EOF;
    return nread ? 1 : 0;
  }
  else if(!nread) {
    return NGHTTP3_ERR_WOULDBLOCK;
  }
  return 1;
}

/* Index where :authority header field will appear in request header
   field list. */
#define AUTHORITY_DST_IDX 3

static CURLcode http_request(struct Curl_easy *data, const void *mem,
                             size_t len)
{
  struct connectdata *conn = data->conn;
  struct HTTP *stream = data->req.p.http;
  size_t nheader;
  size_t i;
  size_t authority_idx;
  char *hdbuf = (char *)mem;
  char *end, *line_end;
  struct quicsocket *qs = conn->quic;
  CURLcode result = CURLE_OK;

  nghttp3_nv *nva = NULL;
  int64_t stream3_id;
  int rc;
  struct h3out *h3out = NULL;

  rc = ngtcp2_conn_open_bidi_stream(qs->qconn, &stream3_id, NULL);
  if(rc) {
    failf(data, "can get bidi streams");
    result = CURLE_SEND_ERROR;
    goto fail;
  }

  stream->stream3_id = stream3_id;
  stream->h3req = TRUE; /* senf off! */
  Curl_dyn_init(&stream->overflow, CURL_MAX_READ_SIZE);
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628

1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680

1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
    if(!h3out) {
      result = CURLE_OUT_OF_MEMORY;
      goto fail;
    }
    stream->h3out = h3out;

    rc = nghttp3_conn_submit_request(qs->h3conn, stream->stream3_id,
                                     nva, nheader, &data_reader,
                                     conn->data);
    if(rc) {
      result = CURLE_SEND_ERROR;
      goto fail;
    }
    break;
  }
  default:
    stream->upload_left = 0; /* nothing left to send */
    rc = nghttp3_conn_submit_request(qs->h3conn, stream->stream3_id,
                                     nva, nheader,
                                     NULL, /* no body! */
                                     conn->data);
    if(rc) {
      result = CURLE_SEND_ERROR;
      goto fail;
    }
    break;
  }

  Curl_safefree(nva);

  infof(data, "Using HTTP/3 Stream ID: %x (easy handle %p)\n",
        stream3_id, (void *)data);

  return CURLE_OK;

fail:
  free(nva);
  return result;
}
static ssize_t ngh3_stream_send(struct connectdata *conn,
                                int sockindex,
                                const void *mem,
                                size_t len,
                                CURLcode *curlcode)
{
  ssize_t sent;

  struct quicsocket *qs = conn->quic;
  curl_socket_t sockfd = conn->sock[sockindex];
  struct HTTP *stream = conn->data->req.p.http;

  if(!stream->h3req) {
    CURLcode result = http_request(conn, mem, len);
    if(result) {
      *curlcode = CURLE_SEND_ERROR;
      return -1;
    }
    sent = len;
  }
  else {
    H3BUGF(infof(conn->data, "ngh3_stream_send() wants to send %zd bytes\n",
                 len));
    if(!stream->upload_len) {
      stream->upload_mem = mem;
      stream->upload_len = len;
      (void)nghttp3_conn_resume_stream(qs->h3conn, stream->stream3_id);
      sent = len;
    }
    else {
      *curlcode = CURLE_AGAIN;
      return -1;
    }
  }

  if(ng_flush_egress(conn, sockfd, qs)) {
    *curlcode = CURLE_SEND_ERROR;
    return -1;
  }

  *curlcode = CURLE_OK;
  return sent;
}

static void ng_has_connected(struct connectdata *conn, int tempindex)
{
  conn->recv[FIRSTSOCKET] = ngh3_stream_recv;
  conn->send[FIRSTSOCKET] = ngh3_stream_send;
  conn->handler = &Curl_handler_http3;
  conn->bits.multiplex = TRUE; /* at least potentially multiplexed */
  conn->httpversion = 30;
  conn->bundle->multiuse = BUNDLE_MULTIPLEX;
  conn->quic = &conn->hequic[tempindex];
  DEBUGF(infof(conn->data, "ngtcp2 established connection!\n"));
}

/*
 * There can be multiple connection attempts going on in parallel.
 */
CURLcode Curl_quic_is_connected(struct connectdata *conn,

                                int sockindex,
                                bool *done)
{
  CURLcode result;
  struct quicsocket *qs = &conn->hequic[sockindex];
  curl_socket_t sockfd = conn->tempsock[sockindex];

  result = ng_process_ingress(conn, sockfd, qs);
  if(result)
    goto error;

  result = ng_flush_egress(conn, sockfd, qs);
  if(result)
    goto error;

  if(ngtcp2_conn_get_handshake_completed(qs->qconn)) {
    *done = TRUE;
    ng_has_connected(conn, sockindex);
  }

  return result;
  error:
  (void)qs_disconnect(qs);
  return result;

}

static CURLcode ng_process_ingress(struct connectdata *conn,
                                   curl_socket_t sockfd,
                                   struct quicsocket *qs)
{
  ssize_t recvd;
  int rv;
  uint8_t buf[65536];
  size_t bufsize = sizeof(buf);







|
<









|
<
<


















|






>


|


|







|













|

















<





|
>







|



|















|







1580
1581
1582
1583
1584
1585
1586
1587

1588
1589
1590
1591
1592
1593
1594
1595
1596
1597


1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668

1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
    if(!h3out) {
      result = CURLE_OUT_OF_MEMORY;
      goto fail;
    }
    stream->h3out = h3out;

    rc = nghttp3_conn_submit_request(qs->h3conn, stream->stream3_id,
                                     nva, nheader, &data_reader, data);

    if(rc) {
      result = CURLE_SEND_ERROR;
      goto fail;
    }
    break;
  }
  default:
    stream->upload_left = 0; /* nothing left to send */
    rc = nghttp3_conn_submit_request(qs->h3conn, stream->stream3_id,
                                     nva, nheader, NULL, data);


    if(rc) {
      result = CURLE_SEND_ERROR;
      goto fail;
    }
    break;
  }

  Curl_safefree(nva);

  infof(data, "Using HTTP/3 Stream ID: %x (easy handle %p)\n",
        stream3_id, (void *)data);

  return CURLE_OK;

fail:
  free(nva);
  return result;
}
static ssize_t ngh3_stream_send(struct Curl_easy *data,
                                int sockindex,
                                const void *mem,
                                size_t len,
                                CURLcode *curlcode)
{
  ssize_t sent;
  struct connectdata *conn = data->conn;
  struct quicsocket *qs = conn->quic;
  curl_socket_t sockfd = conn->sock[sockindex];
  struct HTTP *stream = data->req.p.http;

  if(!stream->h3req) {
    CURLcode result = http_request(data, mem, len);
    if(result) {
      *curlcode = CURLE_SEND_ERROR;
      return -1;
    }
    sent = len;
  }
  else {
    H3BUGF(infof(data, "ngh3_stream_send() wants to send %zd bytes\n",
                 len));
    if(!stream->upload_len) {
      stream->upload_mem = mem;
      stream->upload_len = len;
      (void)nghttp3_conn_resume_stream(qs->h3conn, stream->stream3_id);
      sent = len;
    }
    else {
      *curlcode = CURLE_AGAIN;
      return -1;
    }
  }

  if(ng_flush_egress(data, sockfd, qs)) {
    *curlcode = CURLE_SEND_ERROR;
    return -1;
  }

  *curlcode = CURLE_OK;
  return sent;
}

static void ng_has_connected(struct connectdata *conn, int tempindex)
{
  conn->recv[FIRSTSOCKET] = ngh3_stream_recv;
  conn->send[FIRSTSOCKET] = ngh3_stream_send;
  conn->handler = &Curl_handler_http3;
  conn->bits.multiplex = TRUE; /* at least potentially multiplexed */
  conn->httpversion = 30;
  conn->bundle->multiuse = BUNDLE_MULTIPLEX;
  conn->quic = &conn->hequic[tempindex];

}

/*
 * There can be multiple connection attempts going on in parallel.
 */
CURLcode Curl_quic_is_connected(struct Curl_easy *data,
                                struct connectdata *conn,
                                int sockindex,
                                bool *done)
{
  CURLcode result;
  struct quicsocket *qs = &conn->hequic[sockindex];
  curl_socket_t sockfd = conn->tempsock[sockindex];

  result = ng_process_ingress(data, sockfd, qs);
  if(result)
    goto error;

  result = ng_flush_egress(data, sockfd, qs);
  if(result)
    goto error;

  if(ngtcp2_conn_get_handshake_completed(qs->qconn)) {
    *done = TRUE;
    ng_has_connected(conn, sockindex);
  }

  return result;
  error:
  (void)qs_disconnect(qs);
  return result;

}

static CURLcode ng_process_ingress(struct Curl_easy *data,
                                   curl_socket_t sockfd,
                                   struct quicsocket *qs)
{
  ssize_t recvd;
  int rv;
  uint8_t buf[65536];
  size_t bufsize = sizeof(buf);
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752

1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769

1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794




1795
1796
1797
1798
1799
1800
1801
1802

1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899


1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
                            &remote_addrlen)) == -1 &&
          SOCKERRNO == EINTR)
      ;
    if(recvd == -1) {
      if(SOCKERRNO == EAGAIN || SOCKERRNO == EWOULDBLOCK)
        break;

      failf(conn->data, "ngtcp2: recvfrom() unexpectedly returned %zd", recvd);
      return CURLE_RECV_ERROR;
    }

    ngtcp2_addr_init(&path.local, (struct sockaddr *)&qs->local_addr,
                     qs->local_addrlen, NULL);
    ngtcp2_addr_init(&path.remote, (struct sockaddr *)&remote_addr,
                     remote_addrlen, NULL);

    rv = ngtcp2_conn_read_pkt(qs->qconn, &path, &pi, buf, recvd, ts);
    if(rv != 0) {
      /* TODO Send CONNECTION_CLOSE if possible */
      return CURLE_RECV_ERROR;
    }
  }

  return CURLE_OK;
}

static CURLcode ng_flush_egress(struct connectdata *conn, int sockfd,

                                struct quicsocket *qs)
{
  int rv;
  ssize_t sent;
  ssize_t outlen;
  uint8_t out[NGTCP2_MAX_PKTLEN_IPV4];
  size_t pktlen;
  ngtcp2_path_storage ps;
  ngtcp2_tstamp ts = timestamp();
  struct sockaddr_storage remote_addr;
  ngtcp2_tstamp expiry;
  ngtcp2_duration timeout;
  int64_t stream_id;
  ssize_t veccnt;
  int fin;
  nghttp3_vec vec[16];
  ssize_t ndatalen;


  switch(qs->local_addr.ss_family) {
  case AF_INET:
    pktlen = NGTCP2_MAX_PKTLEN_IPV4;
    break;
#ifdef ENABLE_IPV6
  case AF_INET6:
    pktlen = NGTCP2_MAX_PKTLEN_IPV6;
    break;
#endif
  default:
    assert(0);
  }

  rv = ngtcp2_conn_handle_expiry(qs->qconn, ts);
  if(rv != 0) {
    failf(conn->data, "ngtcp2_conn_handle_expiry returned error: %s\n",
          ngtcp2_strerror(rv));
    return CURLE_SEND_ERROR;
  }

  ngtcp2_path_storage_zero(&ps);

  for(;;) {
    outlen = -1;




    if(qs->h3conn && ngtcp2_conn_get_max_data_left(qs->qconn)) {
      veccnt = nghttp3_conn_writev_stream(qs->h3conn, &stream_id, &fin, vec,
                                          sizeof(vec) / sizeof(vec[0]));
      if(veccnt < 0) {
        failf(conn->data, "nghttp3_conn_writev_stream returned error: %s\n",
              nghttp3_strerror((int)veccnt));
        return CURLE_SEND_ERROR;
      }

      else if(veccnt > 0) {
        uint32_t flags = NGTCP2_WRITE_STREAM_FLAG_MORE |
          (fin ? NGTCP2_WRITE_STREAM_FLAG_FIN : 0);
        outlen =
          ngtcp2_conn_writev_stream(qs->qconn, &ps.path, NULL,
                                    out, pktlen, &ndatalen,
                                    flags, stream_id,
                                    (const ngtcp2_vec *)vec, veccnt, ts);
        if(outlen == 0) {
          break;
        }
        if(outlen < 0) {
          if(outlen == NGTCP2_ERR_STREAM_DATA_BLOCKED ||
             outlen == NGTCP2_ERR_STREAM_SHUT_WR) {
            assert(ndatalen == -1);
            rv = nghttp3_conn_block_stream(qs->h3conn, stream_id);
            if(rv != 0) {
              failf(conn->data,
                    "nghttp3_conn_block_stream returned error: %s\n",
                    nghttp3_strerror(rv));
              return CURLE_SEND_ERROR;
            }
            continue;
          }
          else if(outlen == NGTCP2_ERR_WRITE_MORE) {
            assert(ndatalen > 0);
            rv = nghttp3_conn_add_write_offset(qs->h3conn, stream_id,
                                               ndatalen);
            if(rv != 0) {
              failf(conn->data,
                    "nghttp3_conn_add_write_offset returned error: %s\n",
                    nghttp3_strerror(rv));
              return CURLE_SEND_ERROR;
            }
            continue;
          }
          else {
            assert(ndatalen == -1);
            failf(conn->data, "ngtcp2_conn_writev_stream returned error: %s\n",
                  ngtcp2_strerror((int)outlen));
            return CURLE_SEND_ERROR;
          }
        }
        else {
          assert(ndatalen == -1);
        }
      }
    }
    if(outlen < 0) {
      outlen = ngtcp2_conn_write_pkt(qs->qconn, &ps.path, NULL,
                                     out, pktlen, ts);
      if(outlen < 0) {
        failf(conn->data, "ngtcp2_conn_write_pkt returned error: %s\n",
              ngtcp2_strerror((int)outlen));
        return CURLE_SEND_ERROR;
      }
      if(outlen == 0)
        break;
    }

    memcpy(&remote_addr, ps.path.remote.addr, ps.path.remote.addrlen);
    while((sent = send(sockfd, (const char *)out, outlen, 0)) == -1 &&
          SOCKERRNO == EINTR)
      ;

    if(sent == -1) {
      if(SOCKERRNO == EAGAIN || SOCKERRNO == EWOULDBLOCK) {
        /* TODO Cache packet */
        break;
      }
      else {
        failf(conn->data, "send() returned %zd (errno %d)\n", sent,
              SOCKERRNO);
        return CURLE_SEND_ERROR;
      }
    }
  }

  expiry = ngtcp2_conn_get_expiry(qs->qconn);
  if(expiry != UINT64_MAX) {
    if(expiry <= ts) {
      timeout = NGTCP2_MILLISECONDS;
    }
    else {
      timeout = expiry - ts;
    }
    Curl_expire(conn->data, timeout / NGTCP2_MILLISECONDS, EXPIRE_QUIC);
  }

  return CURLE_OK;
}

/*
 * Called from transfer.c:done_sending when we stop HTTP/3 uploading.
 */
CURLcode Curl_quic_done_sending(struct connectdata *conn)
{


  if(conn->handler == &Curl_handler_http3) {
    /* only for HTTP/3 transfers */
    struct HTTP *stream = conn->data->req.p.http;
    struct quicsocket *qs = conn->quic;
    stream->upload_done = TRUE;
    (void)nghttp3_conn_resume_stream(qs->h3conn, stream->stream3_id);
  }

  return CURLE_OK;
}







|


















|
>

















>
















|








>
>
>
>




|



>
|
|
|
<
|
<
|
|
|
|
|
|
|
|
|
|
|
<
|
|
|
|
|
|
|
|
|
<
|
<
|
|
|
|
|
|
|
|
|
|
|
|
|
<
|
<
<
<
<
|
<
|
|
|


<
<













|














|








|

>
>


|







1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807

1808

1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819

1820
1821
1822
1823
1824
1825
1826
1827
1828

1829

1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842

1843




1844

1845
1846
1847
1848
1849


1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
                            &remote_addrlen)) == -1 &&
          SOCKERRNO == EINTR)
      ;
    if(recvd == -1) {
      if(SOCKERRNO == EAGAIN || SOCKERRNO == EWOULDBLOCK)
        break;

      failf(data, "ngtcp2: recvfrom() unexpectedly returned %zd", recvd);
      return CURLE_RECV_ERROR;
    }

    ngtcp2_addr_init(&path.local, (struct sockaddr *)&qs->local_addr,
                     qs->local_addrlen, NULL);
    ngtcp2_addr_init(&path.remote, (struct sockaddr *)&remote_addr,
                     remote_addrlen, NULL);

    rv = ngtcp2_conn_read_pkt(qs->qconn, &path, &pi, buf, recvd, ts);
    if(rv != 0) {
      /* TODO Send CONNECTION_CLOSE if possible */
      return CURLE_RECV_ERROR;
    }
  }

  return CURLE_OK;
}

static CURLcode ng_flush_egress(struct Curl_easy *data,
                                int sockfd,
                                struct quicsocket *qs)
{
  int rv;
  ssize_t sent;
  ssize_t outlen;
  uint8_t out[NGTCP2_MAX_PKTLEN_IPV4];
  size_t pktlen;
  ngtcp2_path_storage ps;
  ngtcp2_tstamp ts = timestamp();
  struct sockaddr_storage remote_addr;
  ngtcp2_tstamp expiry;
  ngtcp2_duration timeout;
  int64_t stream_id;
  ssize_t veccnt;
  int fin;
  nghttp3_vec vec[16];
  ssize_t ndatalen;
  uint32_t flags;

  switch(qs->local_addr.ss_family) {
  case AF_INET:
    pktlen = NGTCP2_MAX_PKTLEN_IPV4;
    break;
#ifdef ENABLE_IPV6
  case AF_INET6:
    pktlen = NGTCP2_MAX_PKTLEN_IPV6;
    break;
#endif
  default:
    assert(0);
  }

  rv = ngtcp2_conn_handle_expiry(qs->qconn, ts);
  if(rv != 0) {
    failf(data, "ngtcp2_conn_handle_expiry returned error: %s",
          ngtcp2_strerror(rv));
    return CURLE_SEND_ERROR;
  }

  ngtcp2_path_storage_zero(&ps);

  for(;;) {
    outlen = -1;
    veccnt = 0;
    stream_id = -1;
    fin = 0;

    if(qs->h3conn && ngtcp2_conn_get_max_data_left(qs->qconn)) {
      veccnt = nghttp3_conn_writev_stream(qs->h3conn, &stream_id, &fin, vec,
                                          sizeof(vec) / sizeof(vec[0]));
      if(veccnt < 0) {
        failf(data, "nghttp3_conn_writev_stream returned error: %s",
              nghttp3_strerror((int)veccnt));
        return CURLE_SEND_ERROR;
      }
    }

    flags = NGTCP2_WRITE_STREAM_FLAG_MORE |
            (fin ? NGTCP2_WRITE_STREAM_FLAG_FIN : 0);

    outlen = ngtcp2_conn_writev_stream(qs->qconn, &ps.path, NULL, out, pktlen,

                                       &ndatalen, flags, stream_id,
                                       (const ngtcp2_vec *)vec, veccnt, ts);
    if(outlen == 0) {
      break;
    }
    if(outlen < 0) {
      if(outlen == NGTCP2_ERR_STREAM_DATA_BLOCKED ||
         outlen == NGTCP2_ERR_STREAM_SHUT_WR) {
        assert(ndatalen == -1);
        rv = nghttp3_conn_block_stream(qs->h3conn, stream_id);
        if(rv != 0) {

          failf(data, "nghttp3_conn_block_stream returned error: %s\n",
                nghttp3_strerror(rv));
          return CURLE_SEND_ERROR;
        }
        continue;
      }
      else if(outlen == NGTCP2_ERR_WRITE_MORE) {
        assert(ndatalen >= 0);
        rv = nghttp3_conn_add_write_offset(qs->h3conn, stream_id, ndatalen);

        if(rv != 0) {

          failf(data, "nghttp3_conn_add_write_offset returned error: %s\n",
                nghttp3_strerror(rv));
          return CURLE_SEND_ERROR;
        }
        continue;
      }
      else {
        assert(ndatalen == -1);
        failf(data, "ngtcp2_conn_writev_stream returned error: %s",
              ngtcp2_strerror((int)outlen));
        return CURLE_SEND_ERROR;
      }
    }

    else if(ndatalen >= 0) {




      rv = nghttp3_conn_add_write_offset(qs->h3conn, stream_id, ndatalen);

      if(rv != 0) {
        failf(data, "nghttp3_conn_add_write_offset returned error: %s\n",
              nghttp3_strerror(rv));
        return CURLE_SEND_ERROR;
      }


    }

    memcpy(&remote_addr, ps.path.remote.addr, ps.path.remote.addrlen);
    while((sent = send(sockfd, (const char *)out, outlen, 0)) == -1 &&
          SOCKERRNO == EINTR)
      ;

    if(sent == -1) {
      if(SOCKERRNO == EAGAIN || SOCKERRNO == EWOULDBLOCK) {
        /* TODO Cache packet */
        break;
      }
      else {
        failf(data, "send() returned %zd (errno %d)", sent,
              SOCKERRNO);
        return CURLE_SEND_ERROR;
      }
    }
  }

  expiry = ngtcp2_conn_get_expiry(qs->qconn);
  if(expiry != UINT64_MAX) {
    if(expiry <= ts) {
      timeout = NGTCP2_MILLISECONDS;
    }
    else {
      timeout = expiry - ts;
    }
    Curl_expire(data, timeout / NGTCP2_MILLISECONDS, EXPIRE_QUIC);
  }

  return CURLE_OK;
}

/*
 * Called from transfer.c:done_sending when we stop HTTP/3 uploading.
 */
CURLcode Curl_quic_done_sending(struct Curl_easy *data)
{
  struct connectdata *conn = data->conn;
  DEBUGASSERT(conn);
  if(conn->handler == &Curl_handler_http3) {
    /* only for HTTP/3 transfers */
    struct HTTP *stream = data->req.p.http;
    struct quicsocket *qs = conn->quic;
    stream->upload_done = TRUE;
    (void)nghttp3_conn_resume_stream(qs->h3conn, stream->stream3_id);
  }

  return CURLE_OK;
}
Changes to jni/curl/lib/vquic/ngtcp2.h.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#ifndef HEADER_CURL_VQUIC_NGTCP2_H
#define HEADER_CURL_VQUIC_NGTCP2_H
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2020, 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 https://curl.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









|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#ifndef HEADER_CURL_VQUIC_NGTCP2_H
#define HEADER_CURL_VQUIC_NGTCP2_H
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2021, 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 https://curl.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
44
45
46
47
48
49
50

51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
struct quicsocket {
  struct connectdata *conn; /* point back to the connection */
  ngtcp2_conn *qconn;
  ngtcp2_cid dcid;
  ngtcp2_cid scid;
  uint32_t version;
  ngtcp2_settings settings;

#ifdef USE_OPENSSL
  SSL_CTX *sslctx;
  SSL *ssl;
#elif defined(USE_GNUTLS)
  gnutls_certificate_credentials_t cred;
  gnutls_session_t ssl;
#endif
  struct quic_handshake crypto_data[3];
  /* the last TLS alert description generated by the local endpoint */
  uint8_t tls_alert;
  struct sockaddr_storage local_addr;
  socklen_t local_addrlen;

  nghttp3_conn *h3conn;
  nghttp3_conn_settings h3settings;
  int qlogfd;
};

#include "urldata.h"

#endif

#endif /* HEADER_CURL_VQUIC_NGTCP2_H */







>














|








44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
struct quicsocket {
  struct connectdata *conn; /* point back to the connection */
  ngtcp2_conn *qconn;
  ngtcp2_cid dcid;
  ngtcp2_cid scid;
  uint32_t version;
  ngtcp2_settings settings;
  ngtcp2_transport_params transport_params;
#ifdef USE_OPENSSL
  SSL_CTX *sslctx;
  SSL *ssl;
#elif defined(USE_GNUTLS)
  gnutls_certificate_credentials_t cred;
  gnutls_session_t ssl;
#endif
  struct quic_handshake crypto_data[3];
  /* the last TLS alert description generated by the local endpoint */
  uint8_t tls_alert;
  struct sockaddr_storage local_addr;
  socklen_t local_addrlen;

  nghttp3_conn *h3conn;
  nghttp3_settings h3settings;
  int qlogfd;
};

#include "urldata.h"

#endif

#endif /* HEADER_CURL_VQUIC_NGTCP2_H */
Changes to jni/curl/lib/vquic/quiche.c.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2020, 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 https://curl.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







|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2021, 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 https://curl.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
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68

69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94

95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114

115
116
117
118
119
120
121
122

123
124
125
126
127
128
129

130
131

132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174

175
176
177
178
179
180
181


182
183
184
185
186
187
188
#define H3BUGF(x) do { } while(0)
#endif

#define QUIC_MAX_STREAMS (256*1024)
#define QUIC_MAX_DATA (1*1024*1024)
#define QUIC_IDLE_TIMEOUT (60 * 1000) /* milliseconds */

static CURLcode process_ingress(struct connectdata *conn,
                                curl_socket_t sockfd,
                                struct quicsocket *qs);

static CURLcode flush_egress(struct connectdata *conn, curl_socket_t sockfd,
                             struct quicsocket *qs);

static CURLcode http_request(struct connectdata *conn, const void *mem,
                             size_t len);
static Curl_recv h3_stream_recv;
static Curl_send h3_stream_send;

static int quiche_getsock(struct connectdata *conn, curl_socket_t *socks)

{
  struct SingleRequest *k = &conn->data->req;
  int bitmap = GETSOCK_BLANK;

  socks[0] = conn->sock[FIRSTSOCKET];

  /* in a HTTP/2 connection we can basically always get a frame so we should
     always be ready for one */
  bitmap |= GETSOCK_READSOCK(FIRSTSOCKET);

  /* we're still uploading or the HTTP/2 layer wants to send data */
  if((k->keepon & (KEEP_SEND|KEEP_SEND_PAUSE)) == KEEP_SEND)
    bitmap |= GETSOCK_WRITESOCK(FIRSTSOCKET);

  return bitmap;
}

static int quiche_perform_getsock(const struct connectdata *conn,
                                  curl_socket_t *socks)
{
  return quiche_getsock((struct connectdata *)conn, socks);
}

static CURLcode qs_disconnect(struct connectdata *conn,
                              struct quicsocket *qs)
{

  if(qs->conn) {
    (void)quiche_conn_close(qs->conn, TRUE, 0, NULL, 0);
    /* flushing the egress is not a failsafe way to deliver all the
       outstanding packets, but we also don't want to get stuck here... */
    (void)flush_egress(conn, qs->sockfd, qs);
    quiche_conn_free(qs->conn);
    qs->conn = NULL;
  }
  if(qs->h3config)
    quiche_h3_config_free(qs->h3config);
  if(qs->h3c)
    quiche_h3_conn_free(qs->h3c);
  if(qs->cfg) {
    quiche_config_free(qs->cfg);
    qs->cfg = NULL;
  }
  return CURLE_OK;
}

static CURLcode quiche_disconnect(struct connectdata *conn,

                                  bool dead_connection)
{
  struct quicsocket *qs = conn->quic;
  (void)dead_connection;
  return qs_disconnect(conn, qs);
}

void Curl_quic_disconnect(struct connectdata *conn,

                          int tempindex)
{
  if(conn->transport == TRNSPRT_QUIC)
    qs_disconnect(conn, &conn->hequic[tempindex]);
}

static unsigned int quiche_conncheck(struct connectdata *conn,

                                     unsigned int checks_to_perform)
{

  (void)conn;
  (void)checks_to_perform;
  return CONNRESULT_NONE;
}

static CURLcode quiche_do(struct connectdata *conn, bool *done)
{
  struct HTTP *stream = conn->data->req.p.http;
  stream->h3req = FALSE; /* not sent */
  return Curl_http(conn, done);
}

static const struct Curl_handler Curl_handler_http3 = {
  "HTTPS",                              /* scheme */
  ZERO_NULL,                            /* setup_connection */
  quiche_do,                            /* do_it */
  Curl_http_done,                       /* done */
  ZERO_NULL,                            /* do_more */
  ZERO_NULL,                            /* connect_it */
  ZERO_NULL,                            /* connecting */
  ZERO_NULL,                            /* doing */
  quiche_getsock,                       /* proto_getsock */
  quiche_getsock,                       /* doing_getsock */
  ZERO_NULL,                            /* domore_getsock */
  quiche_perform_getsock,               /* perform_getsock */
  quiche_disconnect,                    /* disconnect */
  ZERO_NULL,                            /* readwrite */
  quiche_conncheck,                     /* connection_check */
  PORT_HTTP,                            /* defport */
  CURLPROTO_HTTPS,                      /* protocol */
  CURLPROTO_HTTP,                       /* family */
  PROTOPT_SSL | PROTOPT_STREAM          /* flags */
};

#ifdef DEBUG_QUICHE
static void quiche_debug_log(const char *line, void *argp)
{
  (void)argp;
  fprintf(stderr, "%s\n", line);
}
#endif

CURLcode Curl_quic_connect(struct connectdata *conn, curl_socket_t sockfd,

                           int sockindex,
                           const struct sockaddr *addr, socklen_t addrlen)
{
  CURLcode result;
  struct quicsocket *qs = &conn->hequic[sockindex];
  struct Curl_easy *data = conn->data;
  char *keylog_file = NULL;



#ifdef DEBUG_QUICHE
  /* initialize debug log callback only once */
  static int debug_log_init = 0;
  if(!debug_log_init) {
    quiche_enable_debug_logging(quiche_debug_log, NULL);
    debug_log_init = 1;







|



|


|




|
>

|















<
<
<
<
<
<
|


>




|














|
>




|


|
>



|


|
>


>





|

|

|














|

















|
>





<

>
>







49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86






87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180

181
182
183
184
185
186
187
188
189
190
#define H3BUGF(x) do { } while(0)
#endif

#define QUIC_MAX_STREAMS (256*1024)
#define QUIC_MAX_DATA (1*1024*1024)
#define QUIC_IDLE_TIMEOUT (60 * 1000) /* milliseconds */

static CURLcode process_ingress(struct Curl_easy *data,
                                curl_socket_t sockfd,
                                struct quicsocket *qs);

static CURLcode flush_egress(struct Curl_easy *data, curl_socket_t sockfd,
                             struct quicsocket *qs);

static CURLcode http_request(struct Curl_easy *data, const void *mem,
                             size_t len);
static Curl_recv h3_stream_recv;
static Curl_send h3_stream_send;

static int quiche_getsock(struct Curl_easy *data,
                          struct connectdata *conn, curl_socket_t *socks)
{
  struct SingleRequest *k = &data->req;
  int bitmap = GETSOCK_BLANK;

  socks[0] = conn->sock[FIRSTSOCKET];

  /* in a HTTP/2 connection we can basically always get a frame so we should
     always be ready for one */
  bitmap |= GETSOCK_READSOCK(FIRSTSOCKET);

  /* we're still uploading or the HTTP/2 layer wants to send data */
  if((k->keepon & (KEEP_SEND|KEEP_SEND_PAUSE)) == KEEP_SEND)
    bitmap |= GETSOCK_WRITESOCK(FIRSTSOCKET);

  return bitmap;
}







static CURLcode qs_disconnect(struct Curl_easy *data,
                              struct quicsocket *qs)
{
  DEBUGASSERT(qs);
  if(qs->conn) {
    (void)quiche_conn_close(qs->conn, TRUE, 0, NULL, 0);
    /* flushing the egress is not a failsafe way to deliver all the
       outstanding packets, but we also don't want to get stuck here... */
    (void)flush_egress(data, qs->sockfd, qs);
    quiche_conn_free(qs->conn);
    qs->conn = NULL;
  }
  if(qs->h3config)
    quiche_h3_config_free(qs->h3config);
  if(qs->h3c)
    quiche_h3_conn_free(qs->h3c);
  if(qs->cfg) {
    quiche_config_free(qs->cfg);
    qs->cfg = NULL;
  }
  return CURLE_OK;
}

static CURLcode quiche_disconnect(struct Curl_easy *data,
                                  struct connectdata *conn,
                                  bool dead_connection)
{
  struct quicsocket *qs = conn->quic;
  (void)dead_connection;
  return qs_disconnect(data, qs);
}

void Curl_quic_disconnect(struct Curl_easy *data,
                          struct connectdata *conn,
                          int tempindex)
{
  if(conn->transport == TRNSPRT_QUIC)
    qs_disconnect(data, &conn->hequic[tempindex]);
}

static unsigned int quiche_conncheck(struct Curl_easy *data,
                                     struct connectdata *conn,
                                     unsigned int checks_to_perform)
{
  (void)data;
  (void)conn;
  (void)checks_to_perform;
  return CONNRESULT_NONE;
}

static CURLcode quiche_do(struct Curl_easy *data, bool *done)
{
  struct HTTP *stream = data->req.p.http;
  stream->h3req = FALSE; /* not sent */
  return Curl_http(data, done);
}

static const struct Curl_handler Curl_handler_http3 = {
  "HTTPS",                              /* scheme */
  ZERO_NULL,                            /* setup_connection */
  quiche_do,                            /* do_it */
  Curl_http_done,                       /* done */
  ZERO_NULL,                            /* do_more */
  ZERO_NULL,                            /* connect_it */
  ZERO_NULL,                            /* connecting */
  ZERO_NULL,                            /* doing */
  quiche_getsock,                       /* proto_getsock */
  quiche_getsock,                       /* doing_getsock */
  ZERO_NULL,                            /* domore_getsock */
  quiche_getsock,                       /* perform_getsock */
  quiche_disconnect,                    /* disconnect */
  ZERO_NULL,                            /* readwrite */
  quiche_conncheck,                     /* connection_check */
  PORT_HTTP,                            /* defport */
  CURLPROTO_HTTPS,                      /* protocol */
  CURLPROTO_HTTP,                       /* family */
  PROTOPT_SSL | PROTOPT_STREAM          /* flags */
};

#ifdef DEBUG_QUICHE
static void quiche_debug_log(const char *line, void *argp)
{
  (void)argp;
  fprintf(stderr, "%s\n", line);
}
#endif

CURLcode Curl_quic_connect(struct Curl_easy *data,
                           struct connectdata *conn, curl_socket_t sockfd,
                           int sockindex,
                           const struct sockaddr *addr, socklen_t addrlen)
{
  CURLcode result;
  struct quicsocket *qs = &conn->hequic[sockindex];

  char *keylog_file = NULL;
  char ipbuf[40];
  long port;

#ifdef DEBUG_QUICHE
  /* initialize debug log callback only once */
  static int debug_log_init = 0;
  if(!debug_log_init) {
    quiche_enable_debug_logging(quiche_debug_log, NULL);
    debug_log_init = 1;
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258



259
260
261
262
263
264
265
266
    (void)Curl_qlogdir(data, qs->scid, sizeof(qs->scid), &qfd);
    if(qfd != -1)
      quiche_conn_set_qlog_fd(qs->conn, qfd,
                              "qlog title", "curl qlog");
  }
#endif

  result = flush_egress(conn, sockfd, qs);
  if(result)
    return result;

  /* store the used address as a string */
  if(!Curl_addr2string((struct sockaddr*)addr, addrlen,
                       conn->primary_ip, &conn->primary_port)) {
    char buffer[STRERROR_LEN];
    failf(data, "ssrem inet_ntop() failed with errno %d: %s",
          SOCKERRNO, Curl_strerror(SOCKERRNO, buffer, sizeof(buffer)));
    return CURLE_BAD_FUNCTION_ARGUMENT;
  }
  memcpy(conn->ip_addr_str, conn->primary_ip, MAX_IPADR_LEN);



  Curl_persistconninfo(conn);

  /* for connection reuse purposes: */
  conn->ssl[FIRSTSOCKET].state = ssl_connection_complete;

  {
    unsigned char alpn_protocols[] = QUICHE_H3_APPLICATION_PROTOCOL;
    unsigned alpn_len, offset = 0;







|



|
|
<





|
>
>
>
|







241
242
243
244
245
246
247
248
249
250
251
252
253

254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
    (void)Curl_qlogdir(data, qs->scid, sizeof(qs->scid), &qfd);
    if(qfd != -1)
      quiche_conn_set_qlog_fd(qs->conn, qfd,
                              "qlog title", "curl qlog");
  }
#endif

  result = flush_egress(data, sockfd, qs);
  if(result)
    return result;

  /* extract the used address as a string */
  if(!Curl_addr2string((struct sockaddr*)addr, addrlen, ipbuf, &port)) {

    char buffer[STRERROR_LEN];
    failf(data, "ssrem inet_ntop() failed with errno %d: %s",
          SOCKERRNO, Curl_strerror(SOCKERRNO, buffer, sizeof(buffer)));
    return CURLE_BAD_FUNCTION_ARGUMENT;
  }

  infof(data, "Connect socket %d over QUIC to %s:%ld\n",
        sockfd, ipbuf, port);

  Curl_persistconninfo(data, conn, NULL, -1);

  /* for connection reuse purposes: */
  conn->ssl[FIRSTSOCKET].state = ssl_connection_complete;

  {
    unsigned char alpn_protocols[] = QUICHE_H3_APPLICATION_PROTOCOL;
    unsigned alpn_len, offset = 0;
316
317
318
319
320
321
322
323


324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
  quiche_h3_conn_free(qs->h3c);
  return result;
}

/*
 * This function gets polled to check if this QUIC connection has connected.
 */
CURLcode Curl_quic_is_connected(struct connectdata *conn, int sockindex,


                                bool *done)
{
  CURLcode result;
  struct quicsocket *qs = &conn->hequic[sockindex];
  curl_socket_t sockfd = conn->tempsock[sockindex];

  result = process_ingress(conn, sockfd, qs);
  if(result)
    goto error;

  result = flush_egress(conn, sockfd, qs);
  if(result)
    goto error;

  if(quiche_conn_is_established(qs->conn)) {
    *done = TRUE;
    result = quiche_has_connected(conn, 0, sockindex);
    DEBUGF(infof(conn->data, "quiche established connection!\n"));
  }

  return result;
  error:
  qs_disconnect(conn, qs);
  return result;
}

static CURLcode process_ingress(struct connectdata *conn, int sockfd,
                                struct quicsocket *qs)
{
  ssize_t recvd;
  struct Curl_easy *data = conn->data;
  uint8_t *buf = (uint8_t *)data->state.buffer;
  size_t bufsize = data->set.buffer_size;

  /* in case the timeout expired */
  quiche_conn_on_timeout(qs->conn);

  do {
    recvd = recv(sockfd, buf, bufsize, 0);
    if((recvd < 0) && ((SOCKERRNO == EAGAIN) || (SOCKERRNO == EWOULDBLOCK)))
      break;

    if(recvd < 0) {
      failf(conn->data, "quiche: recv() unexpectedly returned %zd "
            "(errno: %d, socket %d)", recvd, SOCKERRNO, sockfd);
      return CURLE_RECV_ERROR;
    }

    recvd = quiche_conn_recv(qs->conn, buf, recvd);
    if(recvd == QUICHE_ERR_DONE)
      break;

    if(recvd < 0) {
      failf(conn->data, "quiche_conn_recv() == %zd", recvd);
      return CURLE_RECV_ERROR;
    }
  } while(1);

  return CURLE_OK;
}

/*
 * flush_egress drains the buffers and sends off data.
 * Calls failf() on errors.
 */
static CURLcode flush_egress(struct connectdata *conn, int sockfd,
                             struct quicsocket *qs)
{
  ssize_t sent;
  uint8_t out[1200];
  int64_t timeout_ns;

  do {
    sent = quiche_conn_send(qs->conn, out, sizeof(out));
    if(sent == QUICHE_ERR_DONE)
      break;

    if(sent < 0) {
      failf(conn->data, "quiche_conn_send returned %zd\n",
            sent);
      return CURLE_SEND_ERROR;
    }

    sent = send(sockfd, out, sent, 0);
    if(sent < 0) {
      failf(conn->data, "send() returned %zd\n", sent);
      return CURLE_SEND_ERROR;
    }
  } while(1);

  /* time until the next timeout event, as nanoseconds. */
  timeout_ns = quiche_conn_timeout_as_nanos(qs->conn);
  if(timeout_ns)
    /* expire uses milliseconds */
    Curl_expire(conn->data, (timeout_ns + 999999) / 1000000, EXPIRE_QUIC);

  return CURLE_OK;
}

struct h3h1header {
  char *dest;
  size_t destlen; /* left to use */







|
>
>






|



|






|




|



|



<












|









|











|












|
<





|








|







320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359

360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407

408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
  quiche_h3_conn_free(qs->h3c);
  return result;
}

/*
 * This function gets polled to check if this QUIC connection has connected.
 */
CURLcode Curl_quic_is_connected(struct Curl_easy *data,
                                struct connectdata *conn,
                                int sockindex,
                                bool *done)
{
  CURLcode result;
  struct quicsocket *qs = &conn->hequic[sockindex];
  curl_socket_t sockfd = conn->tempsock[sockindex];

  result = process_ingress(data, sockfd, qs);
  if(result)
    goto error;

  result = flush_egress(data, sockfd, qs);
  if(result)
    goto error;

  if(quiche_conn_is_established(qs->conn)) {
    *done = TRUE;
    result = quiche_has_connected(conn, 0, sockindex);
    DEBUGF(infof(data, "quiche established connection!\n"));
  }

  return result;
  error:
  qs_disconnect(data, qs);
  return result;
}

static CURLcode process_ingress(struct Curl_easy *data, int sockfd,
                                struct quicsocket *qs)
{
  ssize_t recvd;

  uint8_t *buf = (uint8_t *)data->state.buffer;
  size_t bufsize = data->set.buffer_size;

  /* in case the timeout expired */
  quiche_conn_on_timeout(qs->conn);

  do {
    recvd = recv(sockfd, buf, bufsize, 0);
    if((recvd < 0) && ((SOCKERRNO == EAGAIN) || (SOCKERRNO == EWOULDBLOCK)))
      break;

    if(recvd < 0) {
      failf(data, "quiche: recv() unexpectedly returned %zd "
            "(errno: %d, socket %d)", recvd, SOCKERRNO, sockfd);
      return CURLE_RECV_ERROR;
    }

    recvd = quiche_conn_recv(qs->conn, buf, recvd);
    if(recvd == QUICHE_ERR_DONE)
      break;

    if(recvd < 0) {
      failf(data, "quiche_conn_recv() == %zd", recvd);
      return CURLE_RECV_ERROR;
    }
  } while(1);

  return CURLE_OK;
}

/*
 * flush_egress drains the buffers and sends off data.
 * Calls failf() on errors.
 */
static CURLcode flush_egress(struct Curl_easy *data, int sockfd,
                             struct quicsocket *qs)
{
  ssize_t sent;
  uint8_t out[1200];
  int64_t timeout_ns;

  do {
    sent = quiche_conn_send(qs->conn, out, sizeof(out));
    if(sent == QUICHE_ERR_DONE)
      break;

    if(sent < 0) {
      failf(data, "quiche_conn_send returned %zd", sent);

      return CURLE_SEND_ERROR;
    }

    sent = send(sockfd, out, sent, 0);
    if(sent < 0) {
      failf(data, "send() returned %zd", sent);
      return CURLE_SEND_ERROR;
    }
  } while(1);

  /* time until the next timeout event, as nanoseconds. */
  timeout_ns = quiche_conn_timeout_as_nanos(qs->conn);
  if(timeout_ns)
    /* expire uses milliseconds */
    Curl_expire(data, (timeout_ns + 999999) / 1000000, EXPIRE_QUIC);

  return CURLE_OK;
}

struct h3h1header {
  char *dest;
  size_t destlen; /* left to use */
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463

464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
  olen = strlen(headers->dest);
  headers->destlen -= olen;
  headers->nlen += olen;
  headers->dest += olen;
  return 0;
}

static ssize_t h3_stream_recv(struct connectdata *conn,
                              int sockindex,
                              char *buf,
                              size_t buffersize,
                              CURLcode *curlcode)
{
  ssize_t recvd = -1;
  ssize_t rcode;

  struct quicsocket *qs = conn->quic;
  curl_socket_t sockfd = conn->sock[sockindex];
  quiche_h3_event *ev;
  int rc;
  struct h3h1header headers;
  struct Curl_easy *data = conn->data;
  struct HTTP *stream = data->req.p.http;
  headers.dest = buf;
  headers.destlen = buffersize;
  headers.nlen = 0;

  if(process_ingress(conn, sockfd, qs)) {
    infof(data, "h3_stream_recv returns on ingress\n");
    *curlcode = CURLE_RECV_ERROR;
    return -1;
  }

  while(recvd < 0) {
    int64_t s = quiche_h3_conn_poll(qs->h3c, qs->conn, &ev);







|







>





<





|







453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473

474
475
476
477
478
479
480
481
482
483
484
485
486
  olen = strlen(headers->dest);
  headers->destlen -= olen;
  headers->nlen += olen;
  headers->dest += olen;
  return 0;
}

static ssize_t h3_stream_recv(struct Curl_easy *data,
                              int sockindex,
                              char *buf,
                              size_t buffersize,
                              CURLcode *curlcode)
{
  ssize_t recvd = -1;
  ssize_t rcode;
  struct connectdata *conn = data->conn;
  struct quicsocket *qs = conn->quic;
  curl_socket_t sockfd = conn->sock[sockindex];
  quiche_h3_event *ev;
  int rc;
  struct h3h1header headers;

  struct HTTP *stream = data->req.p.http;
  headers.dest = buf;
  headers.destlen = buffersize;
  headers.nlen = 0;

  if(process_ingress(data, sockfd, qs)) {
    infof(data, "h3_stream_recv returns on ingress\n");
    *curlcode = CURLE_RECV_ERROR;
    return -1;
  }

  while(recvd < 0) {
    int64_t s = quiche_h3_conn_poll(qs->h3c, qs->conn, &ev);
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555

556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
      break;
    default:
      break;
    }

    quiche_h3_event_free(ev);
  }
  if(flush_egress(conn, sockfd, qs)) {
    *curlcode = CURLE_SEND_ERROR;
    return -1;
  }

  *curlcode = (-1 == recvd)? CURLE_AGAIN : CURLE_OK;
  if(recvd >= 0)
    /* Get this called again to drain the event queue */
    Curl_expire(data, 0, EXPIRE_QUIC);

  data->state.drain = (recvd >= 0) ? 1 : 0;
  return recvd;
}

static ssize_t h3_stream_send(struct connectdata *conn,
                              int sockindex,
                              const void *mem,
                              size_t len,
                              CURLcode *curlcode)
{
  ssize_t sent;

  struct quicsocket *qs = conn->quic;
  curl_socket_t sockfd = conn->sock[sockindex];
  struct HTTP *stream = conn->data->req.p.http;

  if(!stream->h3req) {
    CURLcode result = http_request(conn, mem, len);
    if(result) {
      *curlcode = CURLE_SEND_ERROR;
      return -1;
    }
    sent = len;
  }
  else {
    H3BUGF(infof(conn->data, "Pass on %zd body bytes to quiche\n",
                 len));
    sent = quiche_h3_send_body(qs->h3c, qs->conn, stream->stream3_id,
                               (uint8_t *)mem, len, FALSE);
    if(sent < 0) {
      *curlcode = CURLE_SEND_ERROR;
      return -1;
    }
  }

  if(flush_egress(conn, sockfd, qs)) {
    *curlcode = CURLE_SEND_ERROR;
    return -1;
  }

  *curlcode = CURLE_OK;
  return sent;
}







|













|






>


|


|







|
<








|







532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574

575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
      break;
    default:
      break;
    }

    quiche_h3_event_free(ev);
  }
  if(flush_egress(data, sockfd, qs)) {
    *curlcode = CURLE_SEND_ERROR;
    return -1;
  }

  *curlcode = (-1 == recvd)? CURLE_AGAIN : CURLE_OK;
  if(recvd >= 0)
    /* Get this called again to drain the event queue */
    Curl_expire(data, 0, EXPIRE_QUIC);

  data->state.drain = (recvd >= 0) ? 1 : 0;
  return recvd;
}

static ssize_t h3_stream_send(struct Curl_easy *data,
                              int sockindex,
                              const void *mem,
                              size_t len,
                              CURLcode *curlcode)
{
  ssize_t sent;
  struct connectdata *conn = data->conn;
  struct quicsocket *qs = conn->quic;
  curl_socket_t sockfd = conn->sock[sockindex];
  struct HTTP *stream = data->req.p.http;

  if(!stream->h3req) {
    CURLcode result = http_request(data, mem, len);
    if(result) {
      *curlcode = CURLE_SEND_ERROR;
      return -1;
    }
    sent = len;
  }
  else {
    H3BUGF(infof(data, "Pass on %zd body bytes to quiche\n", len));

    sent = quiche_h3_send_body(qs->h3c, qs->conn, stream->stream3_id,
                               (uint8_t *)mem, len, FALSE);
    if(sent < 0) {
      *curlcode = CURLE_SEND_ERROR;
      return -1;
    }
  }

  if(flush_egress(data, sockfd, qs)) {
    *curlcode = CURLE_SEND_ERROR;
    return -1;
  }

  *curlcode = CURLE_OK;
  return sent;
}
594
595
596
597
598
599
600
601
602
603
604
605

606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
  return msnprintf(p, len, "quiche/%s", quiche_version());
}

/* Index where :authority header field will appear in request header
   field list. */
#define AUTHORITY_DST_IDX 3

static CURLcode http_request(struct connectdata *conn, const void *mem,
                             size_t len)
{
  /*
   */

  struct HTTP *stream = conn->data->req.p.http;
  size_t nheader;
  size_t i;
  size_t authority_idx;
  char *hdbuf = (char *)mem;
  char *end, *line_end;
  int64_t stream3_id;
  quiche_h3_header *nva = NULL;
  struct quicsocket *qs = conn->quic;
  CURLcode result = CURLE_OK;
  struct Curl_easy *data = conn->data;

  stream->h3req = TRUE; /* senf off! */

  /* Calculate number of headers contained in [mem, mem + len). Assumes a
     correctly generated HTTP header field block. */
  nheader = 0;
  for(i = 1; i < len; ++i) {







|




>
|









<







598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620

621
622
623
624
625
626
627
  return msnprintf(p, len, "quiche/%s", quiche_version());
}

/* Index where :authority header field will appear in request header
   field list. */
#define AUTHORITY_DST_IDX 3

static CURLcode http_request(struct Curl_easy *data, const void *mem,
                             size_t len)
{
  /*
   */
  struct connectdata *conn = data->conn;
  struct HTTP *stream = data->req.p.http;
  size_t nheader;
  size_t i;
  size_t authority_idx;
  char *hdbuf = (char *)mem;
  char *end, *line_end;
  int64_t stream3_id;
  quiche_h3_header *nva = NULL;
  struct quicsocket *qs = conn->quic;
  CURLcode result = CURLE_OK;


  stream->h3req = TRUE; /* senf off! */

  /* Calculate number of headers contained in [mem, mem + len). Assumes a
     correctly generated HTTP header field block. */
  nheader = 0;
  for(i = 1; i < len; ++i) {
822
823
824
825
826
827
828
829
830


831
832
833
834
835
836
837
838
839
840
841
842
843
  free(nva);
  return result;
}

/*
 * Called from transfer.c:done_sending when we stop HTTP/3 uploading.
 */
CURLcode Curl_quic_done_sending(struct connectdata *conn)
{


  if(conn->handler == &Curl_handler_http3) {
    /* only for HTTP/3 transfers */
    ssize_t sent;
    struct HTTP *stream = conn->data->req.p.http;
    struct quicsocket *qs = conn->quic;
    fprintf(stderr, "!!! Curl_quic_done_sending\n");
    stream->upload_done = TRUE;
    sent = quiche_h3_send_body(qs->h3c, qs->conn, stream->stream3_id,
                               NULL, 0, TRUE);
    if(sent < 0)
      return CURLE_SEND_ERROR;
  }








|

>
>



|

<







826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841

842
843
844
845
846
847
848
  free(nva);
  return result;
}

/*
 * Called from transfer.c:done_sending when we stop HTTP/3 uploading.
 */
CURLcode Curl_quic_done_sending(struct Curl_easy *data)
{
  struct connectdata *conn = data->conn;
  DEBUGASSERT(conn);
  if(conn->handler == &Curl_handler_http3) {
    /* only for HTTP/3 transfers */
    ssize_t sent;
    struct HTTP *stream = data->req.p.http;
    struct quicsocket *qs = conn->quic;

    stream->upload_done = TRUE;
    sent = quiche_h3_send_body(qs->h3c, qs->conn, stream->stream3_id,
                               NULL, 0, TRUE);
    if(sent < 0)
      return CURLE_SEND_ERROR;
  }

Changes to jni/curl/lib/vssh/libssh.c.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 2017 - 2020 Red Hat, Inc.
 *
 * Authors: Nikos Mavrogiannopoulos, Tomas Mraz, Stanislav Zidek,
 *          Robert Kolcun, Andreas Schneider
 *
 * 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 https://curl.se/docs/copyright.html.







|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 2017 - 2021 Red Hat, Inc.
 *
 * Authors: Nikos Mavrogiannopoulos, Tomas Mraz, Stanislav Zidek,
 *          Robert Kolcun, Andreas Schneider
 *
 * 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 https://curl.se/docs/copyright.html.
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118

119
120
121
122
123
124
125


126
127
128
129
130
131
132
133
134
135
136
137

138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
      ssh_string_free_char(x);                  \
      x = NULL;                                 \
    }                                           \
  } while(0)
#endif

/* Local functions: */
static CURLcode myssh_connect(struct connectdata *conn, bool *done);
static CURLcode myssh_multi_statemach(struct connectdata *conn,
                                      bool *done);
static CURLcode myssh_do_it(struct connectdata *conn, bool *done);

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 void sftp_quote(struct connectdata *conn);
static void sftp_quote_stat(struct connectdata *conn);
static int myssh_getsock(struct connectdata *conn, curl_socket_t *sock);
static int myssh_perform_getsock(const struct connectdata *conn,
                                 curl_socket_t *sock);

static CURLcode myssh_setup_connection(struct connectdata *conn);


/*
 * SCP protocol handler.
 */

const struct Curl_handler Curl_handler_scp = {
  "SCP",                        /* scheme */
  myssh_setup_connection,       /* setup_connection */
  myssh_do_it,                  /* do_it */
  scp_done,                     /* done */
  ZERO_NULL,                    /* do_more */
  myssh_connect,                /* connect_it */
  myssh_multi_statemach,        /* connecting */
  scp_doing,                    /* doing */
  myssh_getsock,                /* proto_getsock */
  myssh_getsock,                /* doing_getsock */
  ZERO_NULL,                    /* domore_getsock */
  myssh_perform_getsock,        /* perform_getsock */
  scp_disconnect,               /* disconnect */
  ZERO_NULL,                    /* readwrite */
  ZERO_NULL,                    /* connection_check */
  PORT_SSH,                     /* defport */
  CURLPROTO_SCP,                /* protocol */
  CURLPROTO_SCP,                /* family */
  PROTOPT_DIRLOCK | PROTOPT_CLOSEACTION | PROTOPT_NOURLQUERY    /* flags */







|
|

|

|

|
|
>


|

|

|
>
>

|



|
|
|
<
|

|
>

















|







103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136

137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
      ssh_string_free_char(x);                  \
      x = NULL;                                 \
    }                                           \
  } while(0)
#endif

/* Local functions: */
static CURLcode myssh_connect(struct Curl_easy *data, bool *done);
static CURLcode myssh_multi_statemach(struct Curl_easy *data,
                                      bool *done);
static CURLcode myssh_do_it(struct Curl_easy *data, bool *done);

static CURLcode scp_done(struct Curl_easy *data,
                         CURLcode, bool premature);
static CURLcode scp_doing(struct Curl_easy *data, bool *dophase_done);
static CURLcode scp_disconnect(struct Curl_easy *data,
                               struct connectdata *conn,
                               bool dead_connection);

static CURLcode sftp_done(struct Curl_easy *data,
                          CURLcode, bool premature);
static CURLcode sftp_doing(struct Curl_easy *data,
                           bool *dophase_done);
static CURLcode sftp_disconnect(struct Curl_easy *data,
                                struct connectdata *conn,
                                bool dead);
static
CURLcode sftp_perform(struct Curl_easy *data,
                      bool *connected,
                      bool *dophase_done);

static void sftp_quote(struct Curl_easy *data);
static void sftp_quote_stat(struct Curl_easy *data);
static int myssh_getsock(struct Curl_easy *data,

                         struct connectdata *conn, curl_socket_t *sock);

static CURLcode myssh_setup_connection(struct Curl_easy *data,
                                       struct connectdata *conn);

/*
 * SCP protocol handler.
 */

const struct Curl_handler Curl_handler_scp = {
  "SCP",                        /* scheme */
  myssh_setup_connection,       /* setup_connection */
  myssh_do_it,                  /* do_it */
  scp_done,                     /* done */
  ZERO_NULL,                    /* do_more */
  myssh_connect,                /* connect_it */
  myssh_multi_statemach,        /* connecting */
  scp_doing,                    /* doing */
  myssh_getsock,                /* proto_getsock */
  myssh_getsock,                /* doing_getsock */
  ZERO_NULL,                    /* domore_getsock */
  myssh_getsock,                /* perform_getsock */
  scp_disconnect,               /* disconnect */
  ZERO_NULL,                    /* readwrite */
  ZERO_NULL,                    /* connection_check */
  PORT_SSH,                     /* defport */
  CURLPROTO_SCP,                /* protocol */
  CURLPROTO_SCP,                /* family */
  PROTOPT_DIRLOCK | PROTOPT_CLOSEACTION | PROTOPT_NOURLQUERY    /* flags */
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
  ZERO_NULL,                            /* do_more */
  myssh_connect,                        /* connect_it */
  myssh_multi_statemach,                /* connecting */
  sftp_doing,                           /* doing */
  myssh_getsock,                        /* proto_getsock */
  myssh_getsock,                        /* doing_getsock */
  ZERO_NULL,                            /* domore_getsock */
  myssh_perform_getsock,                /* perform_getsock */
  sftp_disconnect,                      /* disconnect */
  ZERO_NULL,                            /* readwrite */
  ZERO_NULL,                            /* connection_check */
  PORT_SSH,                             /* defport */
  CURLPROTO_SFTP,                       /* protocol */
  CURLPROTO_SFTP,                       /* family */
  PROTOPT_DIRLOCK | PROTOPT_CLOSEACTION







|







177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
  ZERO_NULL,                            /* do_more */
  myssh_connect,                        /* connect_it */
  myssh_multi_statemach,                /* connecting */
  sftp_doing,                           /* doing */
  myssh_getsock,                        /* proto_getsock */
  myssh_getsock,                        /* doing_getsock */
  ZERO_NULL,                            /* domore_getsock */
  myssh_getsock,                        /* perform_getsock */
  sftp_disconnect,                      /* disconnect */
  ZERO_NULL,                            /* readwrite */
  ZERO_NULL,                            /* connection_check */
  PORT_SSH,                             /* defport */
  CURLPROTO_SFTP,                       /* protocol */
  CURLPROTO_SFTP,                       /* family */
  PROTOPT_DIRLOCK | PROTOPT_CLOSEACTION
219
220
221
222
223
224
225
226
227
228
229
230
231

232
233
234
235
236
237
238
#define state(x,y) mystate(x,y, __LINE__)
#endif

/*
 * SSH State machine related code
 */
/* This is the ONLY way to change SSH state! */
static void mystate(struct connectdata *conn, sshstate nowstate
#ifdef DEBUGBUILD
                    , int lineno
#endif
  )
{

  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",







|





>







222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
#define state(x,y) mystate(x,y, __LINE__)
#endif

/*
 * SSH State machine related code
 */
/* This is the ONLY way to change SSH state! */
static void mystate(struct Curl_easy *data, sshstate nowstate
#ifdef DEBUGBUILD
                    , int lineno
#endif
  )
{
  struct connectdata *conn = data->conn;
  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",
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
    "SSH_SESSION_DISCONNECT",
    "SSH_SESSION_FREE",
    "QUIT"
  };


  if(sshc->state != nowstate) {
    infof(conn->data, "SSH %p state change from %s to %s (line %d)\n",
          (void *) sshc, names[sshc->state], names[nowstate],
          lineno);
  }
#endif

  sshc->state = nowstate;
}

/* Multiple options:
 * 1. data->set.str[STRING_SSH_HOST_PUBLIC_KEY_MD5] is set with an MD5
 *    hash (90s style auth, not sure we should have it here)
 * 2. data->set.ssh_keyfunc callback is set. Then we do trust on first
 *    use. We even save on knownhosts if CURLKHSTAT_FINE_ADD_TO_FILE
 *    is returned by it.
 * 3. none of the above. We only accept if it is present on known hosts.
 *
 * Returns SSH_OK or SSH_ERROR.
 */
static int myssh_is_known(struct connectdata *conn)
{
  int rc;
  struct Curl_easy *data = conn->data;
  struct ssh_conn *sshc = &conn->proto.sshc;
  ssh_key pubkey;
  size_t hlen;
  unsigned char *hash = NULL;
  char *found_base64 = NULL;
  char *known_base64 = NULL;
  int vstate;







|


















|


|







297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
    "SSH_SESSION_DISCONNECT",
    "SSH_SESSION_FREE",
    "QUIT"
  };


  if(sshc->state != nowstate) {
    infof(data, "SSH %p state change from %s to %s (line %d)\n",
          (void *) sshc, names[sshc->state], names[nowstate],
          lineno);
  }
#endif

  sshc->state = nowstate;
}

/* Multiple options:
 * 1. data->set.str[STRING_SSH_HOST_PUBLIC_KEY_MD5] is set with an MD5
 *    hash (90s style auth, not sure we should have it here)
 * 2. data->set.ssh_keyfunc callback is set. Then we do trust on first
 *    use. We even save on knownhosts if CURLKHSTAT_FINE_ADD_TO_FILE
 *    is returned by it.
 * 3. none of the above. We only accept if it is present on known hosts.
 *
 * Returns SSH_OK or SSH_ERROR.
 */
static int myssh_is_known(struct Curl_easy *data)
{
  int rc;
  struct connectdata *conn = data->conn;
  struct ssh_conn *sshc = &conn->proto.sshc;
  ssh_key pubkey;
  size_t hlen;
  unsigned char *hash = NULL;
  char *found_base64 = NULL;
  char *known_base64 = NULL;
  int vstate;
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
      goto cleanup;
    }
  }
  rc = SSH_OK;

cleanup:
  if(found_base64) {
    free(found_base64);
  }
  if(known_base64) {
    free(known_base64);
  }
  if(hash)
    ssh_clean_pubkey_hash(&hash);
  ssh_key_free(pubkey);
#if LIBSSH_VERSION_INT >= SSH_VERSION_INT(0,9,0)
  if(knownhostsentry) {
    ssh_knownhosts_entry_free(knownhostsentry);
  }
#endif
  return rc;
}

#define MOVE_TO_ERROR_STATE(_r) { \
  state(conn, SSH_SESSION_DISCONNECT); \
  sshc->actualcode = _r; \
  rc = SSH_ERROR; \
  break; \
}

#define MOVE_TO_SFTP_CLOSE_STATE() { \
  state(conn, SSH_SFTP_CLOSE); \
  sshc->actualcode = sftp_error_to_CURLE(sftp_get_error(sshc->sftp_session)); \
  rc = SSH_ERROR; \
  break; \
}

#define MOVE_TO_LAST_AUTH \
  if(sshc->auth_methods & SSH_AUTH_METHOD_PASSWORD) { \
    rc = SSH_OK; \
    state(conn, SSH_AUTH_PASS_INIT); \
    break; \
  } \
  else { \
    MOVE_TO_ERROR_STATE(CURLE_LOGIN_DENIED); \
  }

#define MOVE_TO_TERTIARY_AUTH \
  if(sshc->auth_methods & SSH_AUTH_METHOD_INTERACTIVE) { \
    rc = SSH_OK; \
    state(conn, SSH_AUTH_KEY_INIT); \
    break; \
  } \
  else { \
    MOVE_TO_LAST_AUTH; \
  }

#define MOVE_TO_SECONDARY_AUTH \
  if(sshc->auth_methods & SSH_AUTH_METHOD_GSSAPI_MIC) { \
    rc = SSH_OK; \
    state(conn, SSH_AUTH_GSSAPI); \
    break; \
  } \
  else { \
    MOVE_TO_TERTIARY_AUTH; \
  }

static







|


|













|






|








|









|









|







529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
      goto cleanup;
    }
  }
  rc = SSH_OK;

cleanup:
  if(found_base64) {
    (free)(found_base64);
  }
  if(known_base64) {
    (free)(known_base64);
  }
  if(hash)
    ssh_clean_pubkey_hash(&hash);
  ssh_key_free(pubkey);
#if LIBSSH_VERSION_INT >= SSH_VERSION_INT(0,9,0)
  if(knownhostsentry) {
    ssh_knownhosts_entry_free(knownhostsentry);
  }
#endif
  return rc;
}

#define MOVE_TO_ERROR_STATE(_r) { \
  state(data, SSH_SESSION_DISCONNECT); \
  sshc->actualcode = _r; \
  rc = SSH_ERROR; \
  break; \
}

#define MOVE_TO_SFTP_CLOSE_STATE() { \
  state(data, SSH_SFTP_CLOSE); \
  sshc->actualcode = sftp_error_to_CURLE(sftp_get_error(sshc->sftp_session)); \
  rc = SSH_ERROR; \
  break; \
}

#define MOVE_TO_LAST_AUTH \
  if(sshc->auth_methods & SSH_AUTH_METHOD_PASSWORD) { \
    rc = SSH_OK; \
    state(data, SSH_AUTH_PASS_INIT); \
    break; \
  } \
  else { \
    MOVE_TO_ERROR_STATE(CURLE_LOGIN_DENIED); \
  }

#define MOVE_TO_TERTIARY_AUTH \
  if(sshc->auth_methods & SSH_AUTH_METHOD_INTERACTIVE) { \
    rc = SSH_OK; \
    state(data, SSH_AUTH_KEY_INIT); \
    break; \
  } \
  else { \
    MOVE_TO_LAST_AUTH; \
  }

#define MOVE_TO_SECONDARY_AUTH \
  if(sshc->auth_methods & SSH_AUTH_METHOD_GSSAPI_MIC) { \
    rc = SSH_OK; \
    state(data, SSH_AUTH_GSSAPI); \
    break; \
  } \
  else { \
    MOVE_TO_TERTIARY_AUTH; \
  }

static
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673

/*
 * 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 libssh function returns SSH_AGAIN
 * meaning it wants to be called again when the socket is ready
 */
static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
{
  CURLcode result = CURLE_OK;
  struct Curl_easy *data = conn->data;
  struct SSHPROTO *protop = data->req.p.ssh;
  struct ssh_conn *sshc = &conn->proto.sshc;
  curl_socket_t sock = conn->sock[FIRSTSOCKET];
  int rc = SSH_NO_ERROR, err;
  char *new_readdir_line;
  int seekerr = CURL_SEEKFUNC_OK;
  const char *err_msg;







|


|







660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677

/*
 * 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 libssh function returns SSH_AGAIN
 * meaning it wants to be called again when the socket is ready
 */
static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block)
{
  CURLcode result = CURLE_OK;
  struct connectdata *conn = data->conn;
  struct SSHPROTO *protop = data->req.p.ssh;
  struct ssh_conn *sshc = &conn->proto.sshc;
  curl_socket_t sock = conn->sock[FIRSTSOCKET];
  int rc = SSH_NO_ERROR, err;
  char *new_readdir_line;
  int seekerr = CURL_SEEKFUNC_OK;
  const char *err_msg;
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
      ssh_set_log_level(SSH_LOG_PROTOCOL);
#endif

      /* Set libssh to non-blocking, since everything internally is
         non-blocking */
      ssh_set_blocking(sshc->ssh_session, 0);

      state(conn, SSH_S_STARTUP);
      /* FALLTHROUGH */

    case SSH_S_STARTUP:
      rc = ssh_connect(sshc->ssh_session);
      if(rc == SSH_AGAIN)
        break;

      if(rc != SSH_OK) {
        failf(data, "Failure establishing ssh session");
        MOVE_TO_ERROR_STATE(CURLE_FAILED_INIT);
      }

      state(conn, SSH_HOSTKEY);

      /* FALLTHROUGH */
    case SSH_HOSTKEY:

      rc = myssh_is_known(conn);
      if(rc != SSH_OK) {
        MOVE_TO_ERROR_STATE(CURLE_PEER_FAILED_VERIFICATION);
      }

      state(conn, SSH_AUTHLIST);
      /* FALLTHROUGH */
    case SSH_AUTHLIST:{
        sshc->authed = FALSE;

        rc = ssh_userauth_none(sshc->ssh_session, NULL);
        if(rc == SSH_AUTH_AGAIN) {
          rc = SSH_AGAIN;
          break;
        }

        if(rc == SSH_AUTH_SUCCESS) {
          sshc->authed = TRUE;
          infof(data, "Authenticated with none\n");
          state(conn, SSH_AUTH_DONE);
          break;
        }
        else if(rc == SSH_AUTH_ERROR) {
          MOVE_TO_ERROR_STATE(CURLE_LOGIN_DENIED);
        }

        sshc->auth_methods = ssh_userauth_list(sshc->ssh_session, NULL);
        if(sshc->auth_methods & SSH_AUTH_METHOD_PUBLICKEY) {
          state(conn, SSH_AUTH_PKEY_INIT);
          infof(data, "Authentication using SSH public key file\n");
        }
        else if(sshc->auth_methods & SSH_AUTH_METHOD_GSSAPI_MIC) {
          state(conn, SSH_AUTH_GSSAPI);
        }
        else if(sshc->auth_methods & SSH_AUTH_METHOD_INTERACTIVE) {
          state(conn, SSH_AUTH_KEY_INIT);
        }
        else if(sshc->auth_methods & SSH_AUTH_METHOD_PASSWORD) {
          state(conn, SSH_AUTH_PASS_INIT);
        }
        else {                  /* unsupported authentication method */
          MOVE_TO_ERROR_STATE(CURLE_LOGIN_DENIED);
        }

        break;
      }







|












|




|




|













|








|



|


|


|







689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
      ssh_set_log_level(SSH_LOG_PROTOCOL);
#endif

      /* Set libssh to non-blocking, since everything internally is
         non-blocking */
      ssh_set_blocking(sshc->ssh_session, 0);

      state(data, SSH_S_STARTUP);
      /* FALLTHROUGH */

    case SSH_S_STARTUP:
      rc = ssh_connect(sshc->ssh_session);
      if(rc == SSH_AGAIN)
        break;

      if(rc != SSH_OK) {
        failf(data, "Failure establishing ssh session");
        MOVE_TO_ERROR_STATE(CURLE_FAILED_INIT);
      }

      state(data, SSH_HOSTKEY);

      /* FALLTHROUGH */
    case SSH_HOSTKEY:

      rc = myssh_is_known(data);
      if(rc != SSH_OK) {
        MOVE_TO_ERROR_STATE(CURLE_PEER_FAILED_VERIFICATION);
      }

      state(data, SSH_AUTHLIST);
      /* FALLTHROUGH */
    case SSH_AUTHLIST:{
        sshc->authed = FALSE;

        rc = ssh_userauth_none(sshc->ssh_session, NULL);
        if(rc == SSH_AUTH_AGAIN) {
          rc = SSH_AGAIN;
          break;
        }

        if(rc == SSH_AUTH_SUCCESS) {
          sshc->authed = TRUE;
          infof(data, "Authenticated with none\n");
          state(data, SSH_AUTH_DONE);
          break;
        }
        else if(rc == SSH_AUTH_ERROR) {
          MOVE_TO_ERROR_STATE(CURLE_LOGIN_DENIED);
        }

        sshc->auth_methods = ssh_userauth_list(sshc->ssh_session, NULL);
        if(sshc->auth_methods & SSH_AUTH_METHOD_PUBLICKEY) {
          state(data, SSH_AUTH_PKEY_INIT);
          infof(data, "Authentication using SSH public key file\n");
        }
        else if(sshc->auth_methods & SSH_AUTH_METHOD_GSSAPI_MIC) {
          state(data, SSH_AUTH_GSSAPI);
        }
        else if(sshc->auth_methods & SSH_AUTH_METHOD_INTERACTIVE) {
          state(data, SSH_AUTH_KEY_INIT);
        }
        else if(sshc->auth_methods & SSH_AUTH_METHOD_PASSWORD) {
          state(data, SSH_AUTH_PASS_INIT);
        }
        else {                  /* unsupported authentication method */
          MOVE_TO_ERROR_STATE(CURLE_LOGIN_DENIED);
        }

        break;
      }
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
        if(rc != SSH_OK) {
          failf(data, "Could not load private key file %s",
                data->set.str[STRING_SSH_PRIVATE_KEY]);
          MOVE_TO_ERROR_STATE(CURLE_LOGIN_DENIED);
          break;
        }

        state(conn, SSH_AUTH_PKEY);
        break;

      }
      else {
        rc = ssh_userauth_publickey_auto(sshc->ssh_session, NULL,
                                         data->set.ssl.key_passwd);
        if(rc == SSH_AUTH_AGAIN) {
          rc = SSH_AGAIN;
          break;
        }
        if(rc == SSH_AUTH_SUCCESS) {
          rc = SSH_OK;
          sshc->authed = TRUE;
          infof(data, "Completed public key authentication\n");
          state(conn, SSH_AUTH_DONE);
          break;
        }

        MOVE_TO_SECONDARY_AUTH;
      }
      break;
    case SSH_AUTH_PKEY:
      rc = ssh_userauth_publickey(sshc->ssh_session, NULL, sshc->privkey);
      if(rc == SSH_AUTH_AGAIN) {
        rc = SSH_AGAIN;
        break;
      }

      if(rc == SSH_AUTH_SUCCESS) {
        sshc->authed = TRUE;
        infof(data, "Completed public key authentication\n");
        state(conn, SSH_AUTH_DONE);
        break;
      }
      else {
        infof(data, "Failed public key authentication (rc: %d)\n", rc);
        MOVE_TO_SECONDARY_AUTH;
      }
      break;







|














|
















|







785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
        if(rc != SSH_OK) {
          failf(data, "Could not load private key file %s",
                data->set.str[STRING_SSH_PRIVATE_KEY]);
          MOVE_TO_ERROR_STATE(CURLE_LOGIN_DENIED);
          break;
        }

        state(data, SSH_AUTH_PKEY);
        break;

      }
      else {
        rc = ssh_userauth_publickey_auto(sshc->ssh_session, NULL,
                                         data->set.ssl.key_passwd);
        if(rc == SSH_AUTH_AGAIN) {
          rc = SSH_AGAIN;
          break;
        }
        if(rc == SSH_AUTH_SUCCESS) {
          rc = SSH_OK;
          sshc->authed = TRUE;
          infof(data, "Completed public key authentication\n");
          state(data, SSH_AUTH_DONE);
          break;
        }

        MOVE_TO_SECONDARY_AUTH;
      }
      break;
    case SSH_AUTH_PKEY:
      rc = ssh_userauth_publickey(sshc->ssh_session, NULL, sshc->privkey);
      if(rc == SSH_AUTH_AGAIN) {
        rc = SSH_AGAIN;
        break;
      }

      if(rc == SSH_AUTH_SUCCESS) {
        sshc->authed = TRUE;
        infof(data, "Completed public key authentication\n");
        state(data, SSH_AUTH_DONE);
        break;
      }
      else {
        infof(data, "Failed public key authentication (rc: %d)\n", rc);
        MOVE_TO_SECONDARY_AUTH;
      }
      break;
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
        break;
      }

      if(rc == SSH_AUTH_SUCCESS) {
        rc = SSH_OK;
        sshc->authed = TRUE;
        infof(data, "Completed gssapi authentication\n");
        state(conn, SSH_AUTH_DONE);
        break;
      }

      MOVE_TO_TERTIARY_AUTH;
      break;

    case SSH_AUTH_KEY_INIT:
      if(data->set.ssh_auth_types & CURLSSH_AUTH_KEYBOARD) {
        state(conn, SSH_AUTH_KEY);
      }
      else {
        MOVE_TO_LAST_AUTH;
      }
      break;

    case SSH_AUTH_KEY:

      /* Authentication failed. Continue with keyboard-interactive now. */
      rc = myssh_auth_interactive(conn);
      if(rc == SSH_AGAIN) {
        break;
      }
      if(rc == SSH_OK) {
        sshc->authed = TRUE;
        infof(data, "completed keyboard interactive authentication\n");
      }
      state(conn, SSH_AUTH_DONE);
      break;

    case SSH_AUTH_PASS_INIT:
      if(!(data->set.ssh_auth_types & CURLSSH_AUTH_PASSWORD)) {
        /* Host key authentication is intentionally not implemented */
        MOVE_TO_ERROR_STATE(CURLE_LOGIN_DENIED);
      }
      state(conn, SSH_AUTH_PASS);
      /* FALLTHROUGH */

    case SSH_AUTH_PASS:
      rc = ssh_userauth_password(sshc->ssh_session, NULL, conn->passwd);
      if(rc == SSH_AUTH_AGAIN) {
        rc = SSH_AGAIN;
        break;
      }

      if(rc == SSH_AUTH_SUCCESS) {
        sshc->authed = TRUE;
        infof(data, "Completed password authentication\n");
        state(conn, SSH_AUTH_DONE);
      }
      else {
        MOVE_TO_ERROR_STATE(CURLE_LOGIN_DENIED);
      }
      break;

    case SSH_AUTH_DONE:
      if(!sshc->authed) {
        failf(data, "Authentication failure");
        MOVE_TO_ERROR_STATE(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:
      ssh_set_blocking(sshc->ssh_session, 1);

      sshc->sftp_session = sftp_new(sshc->ssh_session);
      if(!sshc->sftp_session) {







|








|

















|







|












|


















|





|



|







841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
        break;
      }

      if(rc == SSH_AUTH_SUCCESS) {
        rc = SSH_OK;
        sshc->authed = TRUE;
        infof(data, "Completed gssapi authentication\n");
        state(data, SSH_AUTH_DONE);
        break;
      }

      MOVE_TO_TERTIARY_AUTH;
      break;

    case SSH_AUTH_KEY_INIT:
      if(data->set.ssh_auth_types & CURLSSH_AUTH_KEYBOARD) {
        state(data, SSH_AUTH_KEY);
      }
      else {
        MOVE_TO_LAST_AUTH;
      }
      break;

    case SSH_AUTH_KEY:

      /* Authentication failed. Continue with keyboard-interactive now. */
      rc = myssh_auth_interactive(conn);
      if(rc == SSH_AGAIN) {
        break;
      }
      if(rc == SSH_OK) {
        sshc->authed = TRUE;
        infof(data, "completed keyboard interactive authentication\n");
      }
      state(data, SSH_AUTH_DONE);
      break;

    case SSH_AUTH_PASS_INIT:
      if(!(data->set.ssh_auth_types & CURLSSH_AUTH_PASSWORD)) {
        /* Host key authentication is intentionally not implemented */
        MOVE_TO_ERROR_STATE(CURLE_LOGIN_DENIED);
      }
      state(data, SSH_AUTH_PASS);
      /* FALLTHROUGH */

    case SSH_AUTH_PASS:
      rc = ssh_userauth_password(sshc->ssh_session, NULL, conn->passwd);
      if(rc == SSH_AUTH_AGAIN) {
        rc = SSH_AGAIN;
        break;
      }

      if(rc == SSH_AUTH_SUCCESS) {
        sshc->authed = TRUE;
        infof(data, "Completed password authentication\n");
        state(data, SSH_AUTH_DONE);
      }
      else {
        MOVE_TO_ERROR_STATE(CURLE_LOGIN_DENIED);
      }
      break;

    case SSH_AUTH_DONE:
      if(!sshc->authed) {
        failf(data, "Authentication failure");
        MOVE_TO_ERROR_STATE(CURLE_LOGIN_DENIED);
        break;
      }

      /*
       * At this point we have an authenticated ssh session.
       */
      infof(data, "Authentication complete\n");

      Curl_pgrsTime(data, TIMER_APPCONNECT);      /* SSH is connected */

      conn->sockfd = sock;
      conn->writesockfd = CURL_SOCKET_BAD;

      if(conn->handler->protocol == CURLPROTO_SFTP) {
        state(data, SSH_SFTP_INIT);
        break;
      }
      infof(data, "SSH CONNECT phase done\n");
      state(data, SSH_STOP);
      break;

    case SSH_SFTP_INIT:
      ssh_set_blocking(sshc->ssh_session, 1);

      sshc->sftp_session = sftp_new(sshc->ssh_session);
      if(!sshc->sftp_session) {
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
      if(rc != SSH_OK) {
        rc = sftp_get_error(sshc->sftp_session);
        failf(data, "Failure initializing sftp session: %s",
              ssh_get_error(sshc->ssh_session));
        MOVE_TO_ERROR_STATE(sftp_error_to_CURLE(rc));
        break;
      }
      state(conn, SSH_SFTP_REALPATH);
      /* FALLTHROUGH */
    case SSH_SFTP_REALPATH:
      /*
       * Get the "home" directory
       */
      sshc->homedir = sftp_canonicalize_path(sshc->sftp_session, ".");
      if(sshc->homedir == NULL) {
        MOVE_TO_ERROR_STATE(CURLE_COULDNT_CONNECT);
      }
      conn->data->state.most_recent_ftp_entrypath = sshc->homedir;

      /* 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 = Curl_getworkingpath(conn, sshc->homedir, &protop->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_GETINFO);
      }
      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 */
      sftp_quote(conn);
      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_GETINFO);
        }
      }
      break;

    case SSH_SFTP_QUOTE_STAT:
      sftp_quote_stat(conn);
      break;

    case SSH_SFTP_QUOTE_SETSTAT:
      rc = sftp_setstat(sshc->sftp_session, sshc->quote_path2,
                        sshc->quote_attrs);
      if(rc != 0 && !sshc->acceptfail) {
        Curl_safefree(sshc->quote_path1);
        Curl_safefree(sshc->quote_path2);
        failf(data, "Attempt to set SFTP stats failed: %s",
              ssh_get_error(sshc->ssh_session));
        state(conn, SSH_SFTP_CLOSE);
        sshc->nextstate = SSH_NO_STATE;
        sshc->actualcode = CURLE_QUOTE_ERROR;
        /* sshc->actualcode = sftp_error_to_CURLE(err);
         * we do not send the actual error; we return
         * the error the libssh2 backend is returning */
        break;
      }
      state(conn, SSH_SFTP_NEXT_QUOTE);
      break;

    case SSH_SFTP_QUOTE_SYMLINK:
      rc = sftp_symlink(sshc->sftp_session, sshc->quote_path2,
                        sshc->quote_path1);
      if(rc != 0 && !sshc->acceptfail) {
        Curl_safefree(sshc->quote_path1);
        Curl_safefree(sshc->quote_path2);
        failf(data, "symlink command failed: %s",
              ssh_get_error(sshc->ssh_session));
        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 = sftp_mkdir(sshc->sftp_session, sshc->quote_path1,
                      (mode_t)data->set.new_directory_perms);
      if(rc != 0 && !sshc->acceptfail) {
        Curl_safefree(sshc->quote_path1);
        failf(data, "mkdir command failed: %s",
              ssh_get_error(sshc->ssh_session));
        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 = sftp_rename(sshc->sftp_session, sshc->quote_path1,
                       sshc->quote_path2);
      if(rc != 0 && !sshc->acceptfail) {
        Curl_safefree(sshc->quote_path1);
        Curl_safefree(sshc->quote_path2);
        failf(data, "rename command failed: %s",
              ssh_get_error(sshc->ssh_session));
        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 = sftp_rmdir(sshc->sftp_session, sshc->quote_path1);
      if(rc != 0 && !sshc->acceptfail) {
        Curl_safefree(sshc->quote_path1);
        failf(data, "rmdir command failed: %s",
              ssh_get_error(sshc->ssh_session));
        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 = sftp_unlink(sshc->sftp_session, sshc->quote_path1);
      if(rc != 0 && !sshc->acceptfail) {
        Curl_safefree(sshc->quote_path1);
        failf(data, "rm command failed: %s",
              ssh_get_error(sshc->ssh_session));
        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_STATVFS:
    {
      sftp_statvfs_t statvfs;

      statvfs = sftp_statvfs(sshc->sftp_session, sshc->quote_path1);
      if(!statvfs && !sshc->acceptfail) {
        Curl_safefree(sshc->quote_path1);
        failf(data, "statvfs command failed: %s",
              ssh_get_error(sshc->ssh_session));
        state(conn, SSH_SFTP_CLOSE);
        sshc->nextstate = SSH_NO_STATE;
        sshc->actualcode = CURLE_QUOTE_ERROR;
        break;
      }
      else if(statvfs) {
        char *tmp = aprintf("statvfs:\n"
                            "f_bsize: %llu\n" "f_frsize: %llu\n"







|









|






|



<
|


|






|


|







|


|





|









|



|



|





|










|







|










|




|









|




|










|




|








|




|








|




|











|







940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967

968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
      if(rc != SSH_OK) {
        rc = sftp_get_error(sshc->sftp_session);
        failf(data, "Failure initializing sftp session: %s",
              ssh_get_error(sshc->ssh_session));
        MOVE_TO_ERROR_STATE(sftp_error_to_CURLE(rc));
        break;
      }
      state(data, SSH_SFTP_REALPATH);
      /* FALLTHROUGH */
    case SSH_SFTP_REALPATH:
      /*
       * Get the "home" directory
       */
      sshc->homedir = sftp_canonicalize_path(sshc->sftp_session, ".");
      if(sshc->homedir == NULL) {
        MOVE_TO_ERROR_STATE(CURLE_COULDNT_CONNECT);
      }
      data->state.most_recent_ftp_entrypath = sshc->homedir;

      /* 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(data, SSH_STOP);
      break;

    case SSH_SFTP_QUOTE_INIT:

      result = Curl_getworkingpath(data, sshc->homedir, &protop->path);
      if(result) {
        sshc->actualcode = result;
        state(data, SSH_STOP);
        break;
      }

      if(data->set.quote) {
        infof(data, "Sending quote commands\n");
        sshc->quote_item = data->set.quote;
        state(data, SSH_SFTP_QUOTE);
      }
      else {
        state(data, SSH_SFTP_GETINFO);
      }
      break;

    case SSH_SFTP_POSTQUOTE_INIT:
      if(data->set.postquote) {
        infof(data, "Sending quote commands\n");
        sshc->quote_item = data->set.postquote;
        state(data, SSH_SFTP_QUOTE);
      }
      else {
        state(data, SSH_STOP);
      }
      break;

    case SSH_SFTP_QUOTE:
      /* Send any quote commands */
      sftp_quote(data);
      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(data, SSH_SFTP_QUOTE);
      }
      else {
        if(sshc->nextstate != SSH_NO_STATE) {
          state(data, sshc->nextstate);
          sshc->nextstate = SSH_NO_STATE;
        }
        else {
          state(data, SSH_SFTP_GETINFO);
        }
      }
      break;

    case SSH_SFTP_QUOTE_STAT:
      sftp_quote_stat(data);
      break;

    case SSH_SFTP_QUOTE_SETSTAT:
      rc = sftp_setstat(sshc->sftp_session, sshc->quote_path2,
                        sshc->quote_attrs);
      if(rc != 0 && !sshc->acceptfail) {
        Curl_safefree(sshc->quote_path1);
        Curl_safefree(sshc->quote_path2);
        failf(data, "Attempt to set SFTP stats failed: %s",
              ssh_get_error(sshc->ssh_session));
        state(data, SSH_SFTP_CLOSE);
        sshc->nextstate = SSH_NO_STATE;
        sshc->actualcode = CURLE_QUOTE_ERROR;
        /* sshc->actualcode = sftp_error_to_CURLE(err);
         * we do not send the actual error; we return
         * the error the libssh2 backend is returning */
        break;
      }
      state(data, SSH_SFTP_NEXT_QUOTE);
      break;

    case SSH_SFTP_QUOTE_SYMLINK:
      rc = sftp_symlink(sshc->sftp_session, sshc->quote_path2,
                        sshc->quote_path1);
      if(rc != 0 && !sshc->acceptfail) {
        Curl_safefree(sshc->quote_path1);
        Curl_safefree(sshc->quote_path2);
        failf(data, "symlink command failed: %s",
              ssh_get_error(sshc->ssh_session));
        state(data, SSH_SFTP_CLOSE);
        sshc->nextstate = SSH_NO_STATE;
        sshc->actualcode = CURLE_QUOTE_ERROR;
        break;
      }
      state(data, SSH_SFTP_NEXT_QUOTE);
      break;

    case SSH_SFTP_QUOTE_MKDIR:
      rc = sftp_mkdir(sshc->sftp_session, sshc->quote_path1,
                      (mode_t)data->set.new_directory_perms);
      if(rc != 0 && !sshc->acceptfail) {
        Curl_safefree(sshc->quote_path1);
        failf(data, "mkdir command failed: %s",
              ssh_get_error(sshc->ssh_session));
        state(data, SSH_SFTP_CLOSE);
        sshc->nextstate = SSH_NO_STATE;
        sshc->actualcode = CURLE_QUOTE_ERROR;
        break;
      }
      state(data, SSH_SFTP_NEXT_QUOTE);
      break;

    case SSH_SFTP_QUOTE_RENAME:
      rc = sftp_rename(sshc->sftp_session, sshc->quote_path1,
                       sshc->quote_path2);
      if(rc != 0 && !sshc->acceptfail) {
        Curl_safefree(sshc->quote_path1);
        Curl_safefree(sshc->quote_path2);
        failf(data, "rename command failed: %s",
              ssh_get_error(sshc->ssh_session));
        state(data, SSH_SFTP_CLOSE);
        sshc->nextstate = SSH_NO_STATE;
        sshc->actualcode = CURLE_QUOTE_ERROR;
        break;
      }
      state(data, SSH_SFTP_NEXT_QUOTE);
      break;

    case SSH_SFTP_QUOTE_RMDIR:
      rc = sftp_rmdir(sshc->sftp_session, sshc->quote_path1);
      if(rc != 0 && !sshc->acceptfail) {
        Curl_safefree(sshc->quote_path1);
        failf(data, "rmdir command failed: %s",
              ssh_get_error(sshc->ssh_session));
        state(data, SSH_SFTP_CLOSE);
        sshc->nextstate = SSH_NO_STATE;
        sshc->actualcode = CURLE_QUOTE_ERROR;
        break;
      }
      state(data, SSH_SFTP_NEXT_QUOTE);
      break;

    case SSH_SFTP_QUOTE_UNLINK:
      rc = sftp_unlink(sshc->sftp_session, sshc->quote_path1);
      if(rc != 0 && !sshc->acceptfail) {
        Curl_safefree(sshc->quote_path1);
        failf(data, "rm command failed: %s",
              ssh_get_error(sshc->ssh_session));
        state(data, SSH_SFTP_CLOSE);
        sshc->nextstate = SSH_NO_STATE;
        sshc->actualcode = CURLE_QUOTE_ERROR;
        break;
      }
      state(data, SSH_SFTP_NEXT_QUOTE);
      break;

    case SSH_SFTP_QUOTE_STATVFS:
    {
      sftp_statvfs_t statvfs;

      statvfs = sftp_statvfs(sshc->sftp_session, sshc->quote_path1);
      if(!statvfs && !sshc->acceptfail) {
        Curl_safefree(sshc->quote_path1);
        failf(data, "statvfs command failed: %s",
              ssh_get_error(sshc->ssh_session));
        state(data, SSH_SFTP_CLOSE);
        sshc->nextstate = SSH_NO_STATE;
        sshc->actualcode = CURLE_QUOTE_ERROR;
        break;
      }
      else if(statvfs) {
        char *tmp = aprintf("statvfs:\n"
                            "f_bsize: %llu\n" "f_frsize: %llu\n"
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
                            statvfs->f_ffree, statvfs->f_favail,
                            statvfs->f_fsid, statvfs->f_flag,
                            statvfs->f_namemax);
        sftp_statvfs_free(statvfs);

        if(!tmp) {
          result = CURLE_OUT_OF_MEMORY;
          state(conn, SSH_SFTP_CLOSE);
          sshc->nextstate = SSH_NO_STATE;
          break;
        }

        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;
        }
      }
      state(conn, SSH_SFTP_NEXT_QUOTE);
      break;
    }

    case SSH_SFTP_GETINFO:
      if(data->set.get_filetime) {
        state(conn, SSH_SFTP_FILETIME);
      }
      else {
        state(conn, SSH_SFTP_TRANS_INIT);
      }
      break;

    case SSH_SFTP_FILETIME:
    {
      sftp_attributes attrs;

      attrs = sftp_stat(sshc->sftp_session, protop->path);
      if(attrs != 0) {
        data->info.filetime = attrs->mtime;
        sftp_attributes_free(attrs);
      }

      state(conn, SSH_SFTP_TRANS_INIT);
      break;
    }

    case SSH_SFTP_TRANS_INIT:
      if(data->set.upload)
        state(conn, SSH_SFTP_UPLOAD_INIT);
      else {
        if(protop->path[strlen(protop->path)-1] == '/')
          state(conn, SSH_SFTP_READDIR_INIT);
        else
          state(conn, SSH_SFTP_DOWNLOAD_INIT);
      }
      break;

    case SSH_SFTP_UPLOAD_INIT:
    {
      int flags;








|




|


|




|





|


|













|





|


|

|







1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
                            statvfs->f_ffree, statvfs->f_favail,
                            statvfs->f_fsid, statvfs->f_flag,
                            statvfs->f_namemax);
        sftp_statvfs_free(statvfs);

        if(!tmp) {
          result = CURLE_OUT_OF_MEMORY;
          state(data, SSH_SFTP_CLOSE);
          sshc->nextstate = SSH_NO_STATE;
          break;
        }

        result = Curl_client_write(data, CLIENTWRITE_HEADER, tmp, strlen(tmp));
        free(tmp);
        if(result) {
          state(data, SSH_SFTP_CLOSE);
          sshc->nextstate = SSH_NO_STATE;
          sshc->actualcode = result;
        }
      }
      state(data, SSH_SFTP_NEXT_QUOTE);
      break;
    }

    case SSH_SFTP_GETINFO:
      if(data->set.get_filetime) {
        state(data, SSH_SFTP_FILETIME);
      }
      else {
        state(data, SSH_SFTP_TRANS_INIT);
      }
      break;

    case SSH_SFTP_FILETIME:
    {
      sftp_attributes attrs;

      attrs = sftp_stat(sshc->sftp_session, protop->path);
      if(attrs != 0) {
        data->info.filetime = attrs->mtime;
        sftp_attributes_free(attrs);
      }

      state(data, SSH_SFTP_TRANS_INIT);
      break;
    }

    case SSH_SFTP_TRANS_INIT:
      if(data->set.upload)
        state(data, SSH_SFTP_UPLOAD_INIT);
      else {
        if(protop->path[strlen(protop->path)-1] == '/')
          state(data, SSH_SFTP_READDIR_INIT);
        else
          state(data, SSH_SFTP_DOWNLOAD_INIT);
      }
      break;

    case SSH_SFTP_UPLOAD_INIT:
    {
      int flags;

1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
      if(data->set.ftp_append)
        /* Try to open for append, but create if nonexisting */
        flags = O_WRONLY|O_CREAT|O_APPEND;
      else if(data->state.resume_from > 0)
        /* If we have restart position then open for append */
        flags = O_WRONLY|O_APPEND;
      else
        /* Clear file before writing (normal behaviour) */
        flags = O_WRONLY|O_CREAT|O_TRUNC;

      if(sshc->sftp_file)
        sftp_close(sshc->sftp_file);
      sshc->sftp_file =
        sftp_open(sshc->sftp_session, protop->path,
                  flags, (mode_t)data->set.new_file_perms);
      if(!sshc->sftp_file) {
        err = sftp_get_error(sshc->sftp_session);

        if(((err == SSH_FX_NO_SUCH_FILE || err == SSH_FX_FAILURE ||
             err == SSH_FX_NO_SUCH_PATH)) &&
             (data->set.ftp_create_missing_dirs &&
             (strlen(protop->path) > 1))) {
               /* try to create the path remotely */
               rc = 0;
               sshc->secondCreateDirs = 1;
               state(conn, SSH_SFTP_CREATE_DIRS_INIT);
               break;
        }
        else {
          MOVE_TO_SFTP_CLOSE_STATE();
        }
      }








|

















|







1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
      if(data->set.ftp_append)
        /* Try to open for append, but create if nonexisting */
        flags = O_WRONLY|O_CREAT|O_APPEND;
      else if(data->state.resume_from > 0)
        /* If we have restart position then open for append */
        flags = O_WRONLY|O_APPEND;
      else
        /* Clear file before writing (normal behavior) */
        flags = O_WRONLY|O_CREAT|O_TRUNC;

      if(sshc->sftp_file)
        sftp_close(sshc->sftp_file);
      sshc->sftp_file =
        sftp_open(sshc->sftp_session, protop->path,
                  flags, (mode_t)data->set.new_file_perms);
      if(!sshc->sftp_file) {
        err = sftp_get_error(sshc->sftp_session);

        if(((err == SSH_FX_NO_SUCH_FILE || err == SSH_FX_FAILURE ||
             err == SSH_FX_NO_SUCH_PATH)) &&
             (data->set.ftp_create_missing_dirs &&
             (strlen(protop->path) > 1))) {
               /* try to create the path remotely */
               rc = 0;
               sshc->secondCreateDirs = 1;
               state(data, SSH_SFTP_CREATE_DIRS_INIT);
               break;
        }
        else {
          MOVE_TO_SFTP_CLOSE_STATE();
        }
      }

1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
      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, 0, EXPIRE_RUN_NOW);

      state(conn, SSH_STOP);
      break;
    }

    case SSH_SFTP_CREATE_DIRS_INIT:
      if(strlen(protop->path) > 1) {
        sshc->slash_pos = protop->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", protop->path);
        state(conn, SSH_SFTP_CREATE_DIRS_MKDIR);
        break;
      }
      state(conn, SSH_SFTP_UPLOAD_INIT);
      break;

    case SSH_SFTP_CREATE_DIRS_MKDIR:
      /* 'mode' - parameter is preliminary - default to 0644 */
      rc = sftp_mkdir(sshc->sftp_session, protop->path,
                      (mode_t)data->set.new_directory_perms);
      *sshc->slash_pos = '/';







|






|


|









|


|







1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
      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, 0, EXPIRE_RUN_NOW);

      state(data, SSH_STOP);
      break;
    }

    case SSH_SFTP_CREATE_DIRS_INIT:
      if(strlen(protop->path) > 1) {
        sshc->slash_pos = protop->path + 1; /* ignore the leading '/' */
        state(data, SSH_SFTP_CREATE_DIRS);
      }
      else {
        state(data, 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", protop->path);
        state(data, SSH_SFTP_CREATE_DIRS_MKDIR);
        break;
      }
      state(data, SSH_SFTP_UPLOAD_INIT);
      break;

    case SSH_SFTP_CREATE_DIRS_MKDIR:
      /* 'mode' - parameter is preliminary - default to 0644 */
      rc = sftp_mkdir(sshc->sftp_session, protop->path,
                      (mode_t)data->set.new_directory_perms);
      *sshc->slash_pos = '/';
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
        if((err != SSH_FX_FILE_ALREADY_EXISTS) &&
           (err != SSH_FX_FAILURE) &&
           (err != SSH_FX_PERMISSION_DENIED)) {
          MOVE_TO_SFTP_CLOSE_STATE();
        }
        rc = 0; /* clear rc and continue */
      }
      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_dir = sftp_opendir(sshc->sftp_session,
                                    protop->path);
      if(!sshc->sftp_dir) {
        failf(data, "Could not open directory for reading: %s",
              ssh_get_error(sshc->ssh_session));
        MOVE_TO_SFTP_CLOSE_STATE();
      }
      state(conn, SSH_SFTP_READDIR);
      break;

    case SSH_SFTP_READDIR:

      if(sshc->readdir_attrs)
        sftp_attributes_free(sshc->readdir_attrs);

      sshc->readdir_attrs = sftp_readdir(sshc->sftp_session, sshc->sftp_dir);
      if(sshc->readdir_attrs) {
        sshc->readdir_filename = sshc->readdir_attrs->name;
        sshc->readdir_longentry = sshc->readdir_attrs->longname;
        sshc->readdir_len = strlen(sshc->readdir_filename);

        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 */
          Curl_debug(data, CURLINFO_DATA_OUT, (char *)sshc->readdir_filename,
                     sshc->readdir_len);
        }
        else {
          sshc->readdir_currLen = strlen(sshc->readdir_longentry);
          sshc->readdir_totalLen = 80 + sshc->readdir_currLen;
          sshc->readdir_line = calloc(sshc->readdir_totalLen, 1);
          if(!sshc->readdir_line) {
            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 & SSH_FILEXFER_ATTR_PERMISSIONS) &&
             ((sshc->readdir_attrs->permissions & S_IFMT) ==
              S_IFLNK)) {
            sshc->readdir_linkPath = malloc(PATH_MAX + 1);
            if(sshc->readdir_linkPath == NULL) {
              state(conn, SSH_SFTP_CLOSE);
              sshc->actualcode = CURLE_OUT_OF_MEMORY;
              break;
            }

            msnprintf(sshc->readdir_linkPath, PATH_MAX, "%s%s", protop->path,
                      sshc->readdir_filename);

            state(conn, SSH_SFTP_READDIR_LINK);
            break;
          }
          state(conn, SSH_SFTP_READDIR_BOTTOM);
          break;
        }
      }
      else if(sftp_dir_eof(sshc->sftp_dir)) {
        state(conn, SSH_SFTP_READDIR_DONE);
        break;
      }
      else {
        failf(data, "Could not open remote file for reading: %s",
              ssh_get_error(sshc->ssh_session));
        MOVE_TO_SFTP_CLOSE_STATE();
        break;







|





|














|


















|



|




|















|











|







|


|




|







1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
        if((err != SSH_FX_FILE_ALREADY_EXISTS) &&
           (err != SSH_FX_FAILURE) &&
           (err != SSH_FX_PERMISSION_DENIED)) {
          MOVE_TO_SFTP_CLOSE_STATE();
        }
        rc = 0; /* clear rc and continue */
      }
      state(data, SSH_SFTP_CREATE_DIRS);
      break;

    case SSH_SFTP_READDIR_INIT:
      Curl_pgrsSetDownloadSize(data, -1);
      if(data->set.opt_no_body) {
        state(data, SSH_STOP);
        break;
      }

      /*
       * This is a directory that we are trying to get, so produce a directory
       * listing
       */
      sshc->sftp_dir = sftp_opendir(sshc->sftp_session,
                                    protop->path);
      if(!sshc->sftp_dir) {
        failf(data, "Could not open directory for reading: %s",
              ssh_get_error(sshc->ssh_session));
        MOVE_TO_SFTP_CLOSE_STATE();
      }
      state(data, SSH_SFTP_READDIR);
      break;

    case SSH_SFTP_READDIR:

      if(sshc->readdir_attrs)
        sftp_attributes_free(sshc->readdir_attrs);

      sshc->readdir_attrs = sftp_readdir(sshc->sftp_session, sshc->sftp_dir);
      if(sshc->readdir_attrs) {
        sshc->readdir_filename = sshc->readdir_attrs->name;
        sshc->readdir_longentry = sshc->readdir_attrs->longname;
        sshc->readdir_len = strlen(sshc->readdir_filename);

        if(data->set.ftp_list_only) {
          char *tmpLine;

          tmpLine = aprintf("%s\n", sshc->readdir_filename);
          if(tmpLine == NULL) {
            state(data, SSH_SFTP_CLOSE);
            sshc->actualcode = CURLE_OUT_OF_MEMORY;
            break;
          }
          result = Curl_client_write(data, CLIENTWRITE_BODY,
                                     tmpLine, sshc->readdir_len + 1);
          free(tmpLine);

          if(result) {
            state(data, 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 */
          Curl_debug(data, CURLINFO_DATA_OUT, (char *)sshc->readdir_filename,
                     sshc->readdir_len);
        }
        else {
          sshc->readdir_currLen = strlen(sshc->readdir_longentry);
          sshc->readdir_totalLen = 80 + sshc->readdir_currLen;
          sshc->readdir_line = calloc(sshc->readdir_totalLen, 1);
          if(!sshc->readdir_line) {
            state(data, 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 & SSH_FILEXFER_ATTR_PERMISSIONS) &&
             ((sshc->readdir_attrs->permissions & S_IFMT) ==
              S_IFLNK)) {
            sshc->readdir_linkPath = malloc(PATH_MAX + 1);
            if(sshc->readdir_linkPath == NULL) {
              state(data, SSH_SFTP_CLOSE);
              sshc->actualcode = CURLE_OUT_OF_MEMORY;
              break;
            }

            msnprintf(sshc->readdir_linkPath, PATH_MAX, "%s%s", protop->path,
                      sshc->readdir_filename);

            state(data, SSH_SFTP_READDIR_LINK);
            break;
          }
          state(data, SSH_SFTP_READDIR_BOTTOM);
          break;
        }
      }
      else if(sftp_dir_eof(sshc->sftp_dir)) {
        state(data, SSH_SFTP_READDIR_DONE);
        break;
      }
      else {
        failf(data, "Could not open remote file for reading: %s",
              ssh_get_error(sshc->ssh_session));
        MOVE_TO_SFTP_CLOSE_STATE();
        break;
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596

      /* get room for the filename and extra output */
      sshc->readdir_totalLen += 4 + sshc->readdir_len;
      new_readdir_line = Curl_saferealloc(sshc->readdir_line,
                                          sshc->readdir_totalLen);
      if(!new_readdir_line) {
        sshc->readdir_line = NULL;
        state(conn, SSH_SFTP_CLOSE);
        sshc->actualcode = CURLE_OUT_OF_MEMORY;
        break;
      }
      sshc->readdir_line = new_readdir_line;

      sshc->readdir_currLen += msnprintf(sshc->readdir_line +
                                         sshc->readdir_currLen,
                                         sshc->readdir_totalLen -
                                         sshc->readdir_currLen,
                                         " -> %s",
                                         sshc->readdir_filename);

      sftp_attributes_free(sshc->readdir_link_attrs);
      sshc->readdir_link_attrs = NULL;
      sshc->readdir_filename = NULL;
      sshc->readdir_longentry = NULL;

      state(conn, SSH_SFTP_READDIR_BOTTOM);
      /* FALLTHROUGH */
    case SSH_SFTP_READDIR_BOTTOM:
      sshc->readdir_currLen += msnprintf(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 */
        Curl_debug(data, CURLINFO_DATA_OUT, sshc->readdir_line,
                   sshc->readdir_currLen);
        data->req.bytecount += sshc->readdir_currLen;
      }
      Curl_safefree(sshc->readdir_line);
      ssh_string_free_char(sshc->readdir_tmp);
      sshc->readdir_tmp = NULL;

      if(result) {
        state(conn, SSH_STOP);
      }
      else
        state(conn, SSH_SFTP_READDIR);
      break;

    case SSH_SFTP_READDIR_DONE:
      sftp_closedir(sshc->sftp_dir);
      sshc->sftp_dir = NULL;

      /* no data to transfer */
      Curl_setup_transfer(data, -1, -1, FALSE, -1);
      state(conn, SSH_STOP);
      break;

    case SSH_SFTP_DOWNLOAD_INIT:
      /*
       * Work on getting the specified file
       */
      if(sshc->sftp_file)
        sftp_close(sshc->sftp_file);

      sshc->sftp_file = sftp_open(sshc->sftp_session, protop->path,
                                  O_RDONLY, (mode_t)data->set.new_file_perms);
      if(!sshc->sftp_file) {
        failf(data, "Could not open remote file for reading: %s",
              ssh_get_error(sshc->ssh_session));

        MOVE_TO_SFTP_CLOSE_STATE();
      }

      state(conn, SSH_SFTP_DOWNLOAD_STAT);
      break;

    case SSH_SFTP_DOWNLOAD_STAT:
    {
      sftp_attributes attrs;
      curl_off_t size;








|

















|






|














|


|








|


















|







1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599

      /* get room for the filename and extra output */
      sshc->readdir_totalLen += 4 + sshc->readdir_len;
      new_readdir_line = Curl_saferealloc(sshc->readdir_line,
                                          sshc->readdir_totalLen);
      if(!new_readdir_line) {
        sshc->readdir_line = NULL;
        state(data, SSH_SFTP_CLOSE);
        sshc->actualcode = CURLE_OUT_OF_MEMORY;
        break;
      }
      sshc->readdir_line = new_readdir_line;

      sshc->readdir_currLen += msnprintf(sshc->readdir_line +
                                         sshc->readdir_currLen,
                                         sshc->readdir_totalLen -
                                         sshc->readdir_currLen,
                                         " -> %s",
                                         sshc->readdir_filename);

      sftp_attributes_free(sshc->readdir_link_attrs);
      sshc->readdir_link_attrs = NULL;
      sshc->readdir_filename = NULL;
      sshc->readdir_longentry = NULL;

      state(data, SSH_SFTP_READDIR_BOTTOM);
      /* FALLTHROUGH */
    case SSH_SFTP_READDIR_BOTTOM:
      sshc->readdir_currLen += msnprintf(sshc->readdir_line +
                                         sshc->readdir_currLen,
                                         sshc->readdir_totalLen -
                                         sshc->readdir_currLen, "\n");
      result = Curl_client_write(data, CLIENTWRITE_BODY,
                                 sshc->readdir_line,
                                 sshc->readdir_currLen);

      if(!result) {
        /* output debug output if that is requested */
        Curl_debug(data, CURLINFO_DATA_OUT, sshc->readdir_line,
                   sshc->readdir_currLen);
        data->req.bytecount += sshc->readdir_currLen;
      }
      Curl_safefree(sshc->readdir_line);
      ssh_string_free_char(sshc->readdir_tmp);
      sshc->readdir_tmp = NULL;

      if(result) {
        state(data, SSH_STOP);
      }
      else
        state(data, SSH_SFTP_READDIR);
      break;

    case SSH_SFTP_READDIR_DONE:
      sftp_closedir(sshc->sftp_dir);
      sshc->sftp_dir = NULL;

      /* no data to transfer */
      Curl_setup_transfer(data, -1, -1, FALSE, -1);
      state(data, SSH_STOP);
      break;

    case SSH_SFTP_DOWNLOAD_INIT:
      /*
       * Work on getting the specified file
       */
      if(sshc->sftp_file)
        sftp_close(sshc->sftp_file);

      sshc->sftp_file = sftp_open(sshc->sftp_session, protop->path,
                                  O_RDONLY, (mode_t)data->set.new_file_perms);
      if(!sshc->sftp_file) {
        failf(data, "Could not open remote file for reading: %s",
              ssh_get_error(sshc->ssh_session));

        MOVE_TO_SFTP_CLOSE_STATE();
      }

      state(data, SSH_SFTP_DOWNLOAD_STAT);
      break;

    case SSH_SFTP_DOWNLOAD_STAT:
    {
      sftp_attributes attrs;
      curl_off_t size;

1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635

        sftp_attributes_free(attrs);

        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;
          CURLofft to_t;
          CURLofft from_t;

          from_t = curlx_strtoofft(conn->data->state.range, &ptr, 0, &from);
          if(from_t == CURL_OFFT_FLOW) {
            return CURLE_RANGE_ERROR;
          }
          while(*ptr && (ISSPACE(*ptr) || (*ptr == '-')))
            ptr++;
          to_t = curlx_strtoofft(ptr, &ptr2, 0, &to);
          if(to_t == CURL_OFFT_FLOW) {







|






|







1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638

        sftp_attributes_free(attrs);

        if(size < 0) {
          failf(data, "Bad file size (%" CURL_FORMAT_CURL_OFF_T ")", size);
          return CURLE_BAD_DOWNLOAD_RESUME;
        }
        if(data->state.use_range) {
          curl_off_t from, to;
          char *ptr;
          char *ptr2;
          CURLofft to_t;
          CURLofft from_t;

          from_t = curlx_strtoofft(data->state.range, &ptr, 0, &from);
          if(from_t == CURL_OFFT_FLOW) {
            return CURLE_RANGE_ERROR;
          }
          while(*ptr && (ISSPACE(*ptr) || (*ptr == '-')))
            ptr++;
          to_t = curlx_strtoofft(ptr, &ptr2, 0, &to);
          if(to_t == CURL_OFFT_FLOW) {
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
    }

    /* Setup the actual download */
    if(data->req.size == 0) {
      /* no data to transfer */
      Curl_setup_transfer(data, -1, -1, FALSE, -1);
      infof(data, "File already completely downloaded\n");
      state(conn, SSH_STOP);
      break;
    }
    Curl_setup_transfer(data, FIRSTSOCKET, data->req.size, FALSE, -1);

    /* 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 libssh 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 {
      sshc->sftp_recv_state = 0;
      state(conn, SSH_STOP);
    }
    break;

    case SSH_SFTP_CLOSE:
      if(sshc->sftp_file) {
        sftp_close(sshc->sftp_file);
        sshc->sftp_file = NULL;
      }
      Curl_safefree(protop->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_file) {
        sftp_close(sshc->sftp_file);
        sshc->sftp_file = NULL;
      }

      if(sshc->sftp_session) {
        sftp_free(sshc->sftp_session);
        sshc->sftp_session = NULL;
      }

      SSH_STRING_FREE_CHAR(sshc->homedir);
      conn->data->state.most_recent_ftp_entrypath = NULL;

      state(conn, SSH_SESSION_DISCONNECT);
      break;


    case SSH_SCP_TRANS_INIT:
      result = Curl_getworkingpath(conn, sshc->homedir, &protop->path);
      if(result) {
        sshc->actualcode = result;
        state(conn, SSH_STOP);
        break;
      }

      /* Functions from the SCP subsystem cannot handle/return SSH_AGAIN */
      ssh_set_blocking(sshc->ssh_session, 1);

      if(data->set.upload) {
        if(data->state.infilesize < 0) {
          failf(data, "SCP requires a known file size for upload");
          sshc->actualcode = CURLE_UPLOAD_FAILED;
          MOVE_TO_ERROR_STATE(CURLE_UPLOAD_FAILED);
        }

        sshc->scp_session =
          ssh_scp_new(sshc->ssh_session, SSH_SCP_WRITE, protop->path);
        state(conn, SSH_SCP_UPLOAD_INIT);
      }
      else {
        sshc->scp_session =
          ssh_scp_new(sshc->ssh_session, SSH_SCP_READ, protop->path);
        state(conn, SSH_SCP_DOWNLOAD_INIT);
      }

      if(!sshc->scp_session) {
        err_msg = ssh_get_error(sshc->ssh_session);
        failf(conn->data, "%s", err_msg);
        MOVE_TO_ERROR_STATE(CURLE_UPLOAD_FAILED);
      }

      break;

    case SSH_SCP_UPLOAD_INIT:

      rc = ssh_scp_init(sshc->scp_session);
      if(rc != SSH_OK) {
        err_msg = ssh_get_error(sshc->ssh_session);
        failf(conn->data, "%s", err_msg);
        MOVE_TO_ERROR_STATE(CURLE_UPLOAD_FAILED);
      }

      rc = ssh_scp_push_file(sshc->scp_session, protop->path,
                             data->state.infilesize,
                             (int)data->set.new_file_perms);
      if(rc != SSH_OK) {
        err_msg = ssh_get_error(sshc->ssh_session);
        failf(conn->data, "%s", err_msg);
        MOVE_TO_ERROR_STATE(CURLE_UPLOAD_FAILED);
      }

      /* upload data */
      Curl_setup_transfer(data, -1, data->req.size, FALSE, FIRSTSOCKET);

      /* not set by Curl_setup_transfer to preserve keepon bits */
      conn->sockfd = conn->writesockfd;

      /* 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 libssh scp send function will deal
         with both accordingly */
      conn->cselect_bits = CURL_CSELECT_OUT;

      state(conn, SSH_STOP);

      break;

    case SSH_SCP_DOWNLOAD_INIT:

      rc = ssh_scp_init(sshc->scp_session);
      if(rc != SSH_OK) {
        err_msg = ssh_get_error(sshc->ssh_session);
        failf(conn->data, "%s", err_msg);
        MOVE_TO_ERROR_STATE(CURLE_COULDNT_CONNECT);
      }
      state(conn, SSH_SCP_DOWNLOAD);
      /* FALLTHROUGH */

    case SSH_SCP_DOWNLOAD:{
        curl_off_t bytecount;

        rc = ssh_scp_pull_request(sshc->scp_session);
        if(rc != SSH_SCP_REQUEST_NEWFILE) {
          err_msg = ssh_get_error(sshc->ssh_session);
          failf(conn->data, "%s", err_msg);
          MOVE_TO_ERROR_STATE(CURLE_REMOTE_FILE_NOT_FOUND);
          break;
        }

        /* download data */
        bytecount = ssh_scp_request_get_size(sshc->scp_session);
        data->req.maxdownload = (curl_off_t) bytecount;
        Curl_setup_transfer(data, FIRSTSOCKET, bytecount, FALSE, -1);

        /* 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 libssh recv function will deal
           with both accordingly */
        conn->cselect_bits = CURL_CSELECT_IN;

        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->scp_session) {
        rc = ssh_scp_close(sshc->scp_session);
        if(rc == SSH_AGAIN) {
          /* Currently the ssh_scp_close handles waiting for EOF in
           * blocking way.
           */
          break;
        }
        if(rc != SSH_OK) {
          infof(data, "Failed to close libssh scp channel: %s\n",
                ssh_get_error(sshc->ssh_session));
        }
      }

      state(conn, SSH_SCP_CHANNEL_FREE);
      break;

    case SSH_SCP_CHANNEL_FREE:
      if(sshc->scp_session) {
        ssh_scp_free(sshc->scp_session);
        sshc->scp_session = NULL;
      }
      DEBUGF(infof(data, "SCP DONE phase complete\n"));

      ssh_set_blocking(sshc->ssh_session, 0);

      state(conn, SSH_SESSION_DISCONNECT);
      /* FALLTHROUGH */

    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->scp_session) {
        ssh_scp_free(sshc->scp_session);
        sshc->scp_session = NULL;
      }

      ssh_disconnect(sshc->ssh_session);

      SSH_STRING_FREE_CHAR(sshc->homedir);
      conn->data->state.most_recent_ftp_entrypath = NULL;

      state(conn, SSH_SESSION_FREE);
      /* FALLTHROUGH */
    case SSH_SESSION_FREE:
      if(sshc->ssh_session) {
        ssh_free(sshc->ssh_session);
        sshc->ssh_session = NULL;
      }








|















|




|

















|



|




















|

|


<

|


|















|




|




|










|








|


















|








|


|








|

















|




|

|

















|











|














|

|







1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782

1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
    }

    /* Setup the actual download */
    if(data->req.size == 0) {
      /* no data to transfer */
      Curl_setup_transfer(data, -1, -1, FALSE, -1);
      infof(data, "File already completely downloaded\n");
      state(data, SSH_STOP);
      break;
    }
    Curl_setup_transfer(data, FIRSTSOCKET, data->req.size, FALSE, -1);

    /* 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 libssh 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(data, SSH_SFTP_CLOSE);
      sshc->actualcode = result;
    }
    else {
      sshc->sftp_recv_state = 0;
      state(data, SSH_STOP);
    }
    break;

    case SSH_SFTP_CLOSE:
      if(sshc->sftp_file) {
        sftp_close(sshc->sftp_file);
        sshc->sftp_file = NULL;
      }
      Curl_safefree(protop->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(data, sshc->nextstate);
        sshc->nextstate = SSH_SFTP_CLOSE;
      }
      else {
        state(data, 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_file) {
        sftp_close(sshc->sftp_file);
        sshc->sftp_file = NULL;
      }

      if(sshc->sftp_session) {
        sftp_free(sshc->sftp_session);
        sshc->sftp_session = NULL;
      }

      SSH_STRING_FREE_CHAR(sshc->homedir);
      data->state.most_recent_ftp_entrypath = NULL;

      state(data, SSH_SESSION_DISCONNECT);
      break;


    case SSH_SCP_TRANS_INIT:
      result = Curl_getworkingpath(data, sshc->homedir, &protop->path);
      if(result) {
        sshc->actualcode = result;
        state(data, SSH_STOP);
        break;
      }

      /* Functions from the SCP subsystem cannot handle/return SSH_AGAIN */
      ssh_set_blocking(sshc->ssh_session, 1);

      if(data->set.upload) {
        if(data->state.infilesize < 0) {
          failf(data, "SCP requires a known file size for upload");
          sshc->actualcode = CURLE_UPLOAD_FAILED;
          MOVE_TO_ERROR_STATE(CURLE_UPLOAD_FAILED);
        }

        sshc->scp_session =
          ssh_scp_new(sshc->ssh_session, SSH_SCP_WRITE, protop->path);
        state(data, SSH_SCP_UPLOAD_INIT);
      }
      else {
        sshc->scp_session =
          ssh_scp_new(sshc->ssh_session, SSH_SCP_READ, protop->path);
        state(data, SSH_SCP_DOWNLOAD_INIT);
      }

      if(!sshc->scp_session) {
        err_msg = ssh_get_error(sshc->ssh_session);
        failf(data, "%s", err_msg);
        MOVE_TO_ERROR_STATE(CURLE_UPLOAD_FAILED);
      }

      break;

    case SSH_SCP_UPLOAD_INIT:

      rc = ssh_scp_init(sshc->scp_session);
      if(rc != SSH_OK) {
        err_msg = ssh_get_error(sshc->ssh_session);
        failf(data, "%s", err_msg);
        MOVE_TO_ERROR_STATE(CURLE_UPLOAD_FAILED);
      }

      rc = ssh_scp_push_file(sshc->scp_session, protop->path,
                             data->state.infilesize,
                             (int)data->set.new_file_perms);
      if(rc != SSH_OK) {
        err_msg = ssh_get_error(sshc->ssh_session);
        failf(data, "%s", err_msg);
        MOVE_TO_ERROR_STATE(CURLE_UPLOAD_FAILED);
      }

      /* upload data */
      Curl_setup_transfer(data, -1, data->req.size, FALSE, FIRSTSOCKET);

      /* not set by Curl_setup_transfer to preserve keepon bits */
      conn->sockfd = conn->writesockfd;

      /* 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 libssh scp send function will deal
         with both accordingly */
      conn->cselect_bits = CURL_CSELECT_OUT;

      state(data, SSH_STOP);

      break;

    case SSH_SCP_DOWNLOAD_INIT:

      rc = ssh_scp_init(sshc->scp_session);
      if(rc != SSH_OK) {
        err_msg = ssh_get_error(sshc->ssh_session);
        failf(data, "%s", err_msg);
        MOVE_TO_ERROR_STATE(CURLE_COULDNT_CONNECT);
      }
      state(data, SSH_SCP_DOWNLOAD);
      /* FALLTHROUGH */

    case SSH_SCP_DOWNLOAD:{
        curl_off_t bytecount;

        rc = ssh_scp_pull_request(sshc->scp_session);
        if(rc != SSH_SCP_REQUEST_NEWFILE) {
          err_msg = ssh_get_error(sshc->ssh_session);
          failf(data, "%s", err_msg);
          MOVE_TO_ERROR_STATE(CURLE_REMOTE_FILE_NOT_FOUND);
          break;
        }

        /* download data */
        bytecount = ssh_scp_request_get_size(sshc->scp_session);
        data->req.maxdownload = (curl_off_t) bytecount;
        Curl_setup_transfer(data, FIRSTSOCKET, bytecount, FALSE, -1);

        /* 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 libssh recv function will deal
           with both accordingly */
        conn->cselect_bits = CURL_CSELECT_IN;

        state(data, SSH_STOP);
        break;
      }
    case SSH_SCP_DONE:
      if(data->set.upload)
        state(data, SSH_SCP_SEND_EOF);
      else
        state(data, SSH_SCP_CHANNEL_FREE);
      break;

    case SSH_SCP_SEND_EOF:
      if(sshc->scp_session) {
        rc = ssh_scp_close(sshc->scp_session);
        if(rc == SSH_AGAIN) {
          /* Currently the ssh_scp_close handles waiting for EOF in
           * blocking way.
           */
          break;
        }
        if(rc != SSH_OK) {
          infof(data, "Failed to close libssh scp channel: %s\n",
                ssh_get_error(sshc->ssh_session));
        }
      }

      state(data, SSH_SCP_CHANNEL_FREE);
      break;

    case SSH_SCP_CHANNEL_FREE:
      if(sshc->scp_session) {
        ssh_scp_free(sshc->scp_session);
        sshc->scp_session = NULL;
      }
      DEBUGF(infof(data, "SCP DONE phase complete\n"));

      ssh_set_blocking(sshc->ssh_session, 0);

      state(data, SSH_SESSION_DISCONNECT);
      /* FALLTHROUGH */

    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->scp_session) {
        ssh_scp_free(sshc->scp_session);
        sshc->scp_session = NULL;
      }

      ssh_disconnect(sshc->ssh_session);

      SSH_STRING_FREE_CHAR(sshc->homedir);
      data->state.most_recent_ftp_entrypath = NULL;

      state(data, SSH_SESSION_FREE);
      /* FALLTHROUGH */
    case SSH_SESSION_FREE:
      if(sshc->ssh_session) {
        ssh_free(sshc->ssh_session);
        sshc->ssh_session = NULL;
      }

1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017

2018
2019
2020
2021

2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
      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 == SSH_AGAIN) {
    /* 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 myssh_perform_getsock(const struct connectdata *conn,
                                 curl_socket_t *sock)
{
  int bitmap = GETSOCK_BLANK;

  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;
}

/* 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 myssh_getsock(struct connectdata *conn,
                         curl_socket_t *sock)
{
  /* if we know the direction we can use the generic *_getsock() function even
     for the protocol_connect and doing states */
  return myssh_perform_getsock(conn, sock);
}

static void myssh_block2waitfor(struct connectdata *conn, bool block)
{
  struct ssh_conn *sshc = &conn->proto.sshc;

  /* If it didn't block, or nothing was returned by ssh_get_poll_flags
   * have the original set */
  conn->waitfor = sshc->orig_waitfor;







|







|


















>
|
|


>











<
<
<
<
<
<
<
<
<
<







1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036










2037
2038
2039
2040
2041
2042
2043
      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(data, SSH_STOP);
      break;

    case SSH_QUIT:
      /* fallthrough, just stop! */
    default:
      /* internal error */
      sshc->nextstate = SSH_NO_STATE;
      state(data, SSH_STOP);
      break;

    }
  } while(!rc && (sshc->state != SSH_STOP));


  if(rc == SSH_AGAIN) {
    /* 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 myssh_getsock(struct Curl_easy *data,
                         struct connectdata *conn,
                         curl_socket_t *sock)
{
  int bitmap = GETSOCK_BLANK;
  (void)data;
  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;
}











static void myssh_block2waitfor(struct connectdata *conn, bool block)
{
  struct ssh_conn *sshc = &conn->proto.sshc;

  /* If it didn't block, or nothing was returned by ssh_get_poll_flags
   * have the original set */
  conn->waitfor = sshc->orig_waitfor;
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066

2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080

2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
    else if(dir & SSH_WRITE_PENDING) {
      conn->waitfor = KEEP_SEND;
    }
  }
}

/* called repeatedly until done from multi.c */
static CURLcode myssh_multi_statemach(struct connectdata *conn,
                                      bool *done)
{

  struct ssh_conn *sshc = &conn->proto.sshc;
  bool block;    /* we store the status and use that to provide a ssh_getsock()
                    implementation */
  CURLcode result = myssh_statemach_act(conn, &block);

  *done = (sshc->state == SSH_STOP) ? TRUE : FALSE;
  myssh_block2waitfor(conn, block);

  return result;
}

static CURLcode myssh_block_statemach(struct connectdata *conn,
                                      bool disconnect)
{

  struct ssh_conn *sshc = &conn->proto.sshc;
  CURLcode result = CURLE_OK;
  struct Curl_easy *data = conn->data;

  while((sshc->state != SSH_STOP) && !result) {
    bool block;
    timediff_t left = 1000;
    struct curltime now = Curl_now();

    result = myssh_statemach_act(conn, &block);
    if(result)
      break;

    if(!disconnect) {
      if(Curl_pgrsUpdate(conn))
        return CURLE_ABORTED_BY_CALLBACK;

      result = Curl_speedcheck(data, now);
      if(result)
        break;

      left = Curl_timeleft(data, NULL, FALSE);







|


>



|







|


>


<






|




|







2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078

2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
    else if(dir & SSH_WRITE_PENDING) {
      conn->waitfor = KEEP_SEND;
    }
  }
}

/* called repeatedly until done from multi.c */
static CURLcode myssh_multi_statemach(struct Curl_easy *data,
                                      bool *done)
{
  struct connectdata *conn = data->conn;
  struct ssh_conn *sshc = &conn->proto.sshc;
  bool block;    /* we store the status and use that to provide a ssh_getsock()
                    implementation */
  CURLcode result = myssh_statemach_act(data, &block);

  *done = (sshc->state == SSH_STOP) ? TRUE : FALSE;
  myssh_block2waitfor(conn, block);

  return result;
}

static CURLcode myssh_block_statemach(struct Curl_easy *data,
                                      bool disconnect)
{
  struct connectdata *conn = data->conn;
  struct ssh_conn *sshc = &conn->proto.sshc;
  CURLcode result = CURLE_OK;


  while((sshc->state != SSH_STOP) && !result) {
    bool block;
    timediff_t left = 1000;
    struct curltime now = Curl_now();

    result = myssh_statemach_act(data, &block);
    if(result)
      break;

    if(!disconnect) {
      if(Curl_pgrsUpdate(data))
        return CURLE_ABORTED_BY_CALLBACK;

      result = Curl_speedcheck(data, now);
      if(result)
        break;

      left = Curl_timeleft(data, NULL, FALSE);
2117
2118
2119
2120
2121
2122
2123
2124

2125
2126

2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145

2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159

  return result;
}

/*
 * SSH setup connection
 */
static CURLcode myssh_setup_connection(struct connectdata *conn)

{
  struct SSHPROTO *ssh;


  conn->data->req.p.ssh = 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 myssh_connect(struct connectdata *conn, bool *done)
{
  struct ssh_conn *ssh;
  CURLcode result;

  curl_socket_t sock = conn->sock[FIRSTSOCKET];
  struct Curl_easy *data = conn->data;
  int rc;

  /* initialize per-handle data if not already */
  if(!data->req.p.ssh)
    myssh_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;







|
>


>

|













|



>

<




|







2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144

2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156

  return result;
}

/*
 * SSH setup connection
 */
static CURLcode myssh_setup_connection(struct Curl_easy *data,
                                       struct connectdata *conn)
{
  struct SSHPROTO *ssh;
  (void)conn;

  data->req.p.ssh = 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 myssh_connect(struct Curl_easy *data, bool *done)
{
  struct ssh_conn *ssh;
  CURLcode result;
  struct connectdata *conn = data->conn;
  curl_socket_t sock = conn->sock[FIRSTSOCKET];

  int rc;

  /* initialize per-handle data if not already */
  if(!data->req.p.ssh)
    myssh_setup_connection(data, 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;
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278

2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329

2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
2370
2371
2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
2384
2385
2386

2387
2388
2389
2390
2391
2392
2393
      return CURLE_FAILED_INIT;
    }
  }

  /* we do not verify here, we do it at the state machine,
   * after connection */

  state(conn, SSH_INIT);

  result = myssh_multi_statemach(conn, done);

  return result;
}

/* called from multi.c while DOing */
static CURLcode scp_doing(struct connectdata *conn, bool *dophase_done)
{
  CURLcode result;

  result = myssh_multi_statemach(conn, dophase_done);

  if(*dophase_done) {
    DEBUGF(infof(conn->data, "DO phase is complete\n"));
  }
  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);

  result = myssh_multi_statemach(conn, dophase_done);

  *connected = conn->bits.tcpconnect[FIRSTSOCKET];

  if(*dophase_done) {
    DEBUGF(infof(conn->data, "DO phase is complete\n"));
  }

  return result;
}

static CURLcode myssh_do_it(struct connectdata *conn, bool *done)
{
  CURLcode result;
  bool connected = 0;
  struct Curl_easy *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;

  if(ssh->ssh_session) {
    /* only if there's a session still around to use! */

    state(conn, SSH_SESSION_DISCONNECT);

    result = myssh_block_statemach(conn, TRUE);
  }

  return result;
}

/* generic done function for both SCP and SFTP called from their specific
   done functions */
static CURLcode myssh_done(struct connectdata *conn, CURLcode status)
{
  CURLcode result = CURLE_OK;
  struct SSHPROTO *protop = conn->data->req.p.ssh;

  if(!status) {
    /* run the state-machine */
    result = myssh_block_statemach(conn, FALSE);
  }
  else
    result = status;

  if(protop)
    Curl_safefree(protop->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 myssh_done(conn, status);

}

static ssize_t scp_send(struct connectdata *conn, int sockindex,
                        const void *mem, size_t len, CURLcode *err)
{
  int rc;

  (void) sockindex; /* we only support SCP on the fixed known primary socket */
  (void) err;

  rc = ssh_scp_write(conn->proto.sshc.scp_session, mem, len);

#if 0
  /* The following code is misleading, mostly added as wishful thinking







|

|





|



|


|














|



>

|




|

|




|





|



|
















|

|







|
>









|

|







|


|



|






|


|




|





|

|



|



>







2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
2370
2371
2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
2384
2385
2386
2387
2388
2389
2390
2391
2392
2393
      return CURLE_FAILED_INIT;
    }
  }

  /* we do not verify here, we do it at the state machine,
   * after connection */

  state(data, SSH_INIT);

  result = myssh_multi_statemach(data, done);

  return result;
}

/* called from multi.c while DOing */
static CURLcode scp_doing(struct Curl_easy *data, bool *dophase_done)
{
  CURLcode result;

  result = myssh_multi_statemach(data, dophase_done);

  if(*dophase_done) {
    DEBUGF(infof(data, "DO phase is complete\n"));
  }
  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 Curl_easy *data,
                     bool *connected, bool *dophase_done)
{
  CURLcode result = CURLE_OK;
  struct connectdata *conn = data->conn;

  DEBUGF(infof(data, "DO phase starts\n"));

  *dophase_done = FALSE;        /* not done yet */

  /* start the first command in the DO phase */
  state(data, SSH_SCP_TRANS_INIT);

  result = myssh_multi_statemach(data, dophase_done);

  *connected = conn->bits.tcpconnect[FIRSTSOCKET];

  if(*dophase_done) {
    DEBUGF(infof(data, "DO phase is complete\n"));
  }

  return result;
}

static CURLcode myssh_do_it(struct Curl_easy *data, bool *done)
{
  CURLcode result;
  bool connected = 0;
  struct connectdata *conn = data->conn;
  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(data, &connected, done);
  else
    result = sftp_perform(data, &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 Curl_easy *data,
                               struct connectdata *conn,
                               bool dead_connection)
{
  CURLcode result = CURLE_OK;
  struct ssh_conn *ssh = &conn->proto.sshc;
  (void) dead_connection;

  if(ssh->ssh_session) {
    /* only if there's a session still around to use! */

    state(data, SSH_SESSION_DISCONNECT);

    result = myssh_block_statemach(data, TRUE);
  }

  return result;
}

/* generic done function for both SCP and SFTP called from their specific
   done functions */
static CURLcode myssh_done(struct Curl_easy *data, CURLcode status)
{
  CURLcode result = CURLE_OK;
  struct SSHPROTO *protop = data->req.p.ssh;

  if(!status) {
    /* run the state-machine */
    result = myssh_block_statemach(data, FALSE);
  }
  else
    result = status;

  if(protop)
    Curl_safefree(protop->path);
  if(Curl_pgrsDone(data))
    return CURLE_ABORTED_BY_CALLBACK;

  data->req.keepon = 0;   /* clear all bits */
  return result;
}


static CURLcode scp_done(struct Curl_easy *data, CURLcode status,
                         bool premature)
{
  (void) premature;             /* not used */

  if(!status)
    state(data, SSH_SCP_DONE);

  return myssh_done(data, status);

}

static ssize_t scp_send(struct Curl_easy *data, int sockindex,
                        const void *mem, size_t len, CURLcode *err)
{
  int rc;
  struct connectdata *conn = data->conn;
  (void) sockindex; /* we only support SCP on the fixed known primary socket */
  (void) err;

  rc = ssh_scp_write(conn->proto.sshc.scp_session, mem, len);

#if 0
  /* The following code is misleading, mostly added as wishful thinking
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415

2416
2417
2418
2419
2420
2421
2422
    *err = CURLE_SSH;
    return -1;
  }

  return len;
}

static ssize_t scp_recv(struct connectdata *conn, int sockindex,
                        char *mem, size_t len, CURLcode *err)
{
  ssize_t nread;

  (void) err;
  (void) sockindex; /* we only support SCP on the fixed known primary socket */

  /* libssh returns int */
  nread = ssh_scp_read(conn->proto.sshc.scp_session, mem, len);

#if 0







|



>







2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
    *err = CURLE_SSH;
    return -1;
  }

  return len;
}

static ssize_t scp_recv(struct Curl_easy *data, int sockindex,
                        char *mem, size_t len, CURLcode *err)
{
  ssize_t nread;
  struct connectdata *conn = data->conn;
  (void) err;
  (void) sockindex; /* we only support SCP on the fixed known primary socket */

  /* libssh returns int */
  nread = ssh_scp_read(conn->proto.sshc.scp_session, mem, len);

#if 0
2444
2445
2446
2447
2448
2449
2450
2451
2452
2453
2454
2455

2456
2457
2458
2459
2460
2461
2462
2463
2464
2465
2466
2467
2468
2469
2470
2471
2472
2473
2474
2475
2476
2477
2478
2479
2480
2481
2482
2483
2484
2485
2486
2487
2488
2489
2490


2491
2492
2493
2494
2495
2496
2497
2498
2499
2500
2501
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511

2512
2513
2514
2515
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529

2530
2531
2532
2533
2534
2535
2536
 * 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 = myssh_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 = myssh_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"));

  if(conn->proto.sshc.ssh_session) {
    /* only if there's a session still around to use! */
    state(conn, SSH_SFTP_SHUTDOWN);
    result = myssh_block_statemach(conn, TRUE);
  }

  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(!premature && conn->data->set.postquote && !conn->bits.retry)
      sshc->nextstate = SSH_SFTP_POSTQUOTE_INIT;
    state(conn, SSH_SFTP_CLOSE);
  }
  return myssh_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;

  (void)sockindex;

  nwrite = sftp_write(conn->proto.sshc.sftp_file, mem, len);

  myssh_block2waitfor(conn, FALSE);

#if 0 /* not returned by libssh on write */







|




>

|




|


|




|






|


|

|







|
>
>




|



|
|


|





|
|

>






|

|

|



|



>







2445
2446
2447
2448
2449
2450
2451
2452
2453
2454
2455
2456
2457
2458
2459
2460
2461
2462
2463
2464
2465
2466
2467
2468
2469
2470
2471
2472
2473
2474
2475
2476
2477
2478
2479
2480
2481
2482
2483
2484
2485
2486
2487
2488
2489
2490
2491
2492
2493
2494
2495
2496
2497
2498
2499
2500
2501
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
2539
2540
2541
2542
 * 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 Curl_easy *data,
                      bool *connected,
                      bool *dophase_done)
{
  CURLcode result = CURLE_OK;
  struct connectdata *conn = data->conn;

  DEBUGF(infof(data, "DO phase starts\n"));

  *dophase_done = FALSE; /* not done yet */

  /* start the first command in the DO phase */
  state(data, SSH_SFTP_QUOTE_INIT);

  /* run the state-machine */
  result = myssh_multi_statemach(data, dophase_done);

  *connected = conn->bits.tcpconnect[FIRSTSOCKET];

  if(*dophase_done) {
    DEBUGF(infof(data, "DO phase is complete\n"));
  }

  return result;
}

/* called from multi.c while DOing */
static CURLcode sftp_doing(struct Curl_easy *data,
                           bool *dophase_done)
{
  CURLcode result = myssh_multi_statemach(data, dophase_done);
  if(*dophase_done) {
    DEBUGF(infof(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 Curl_easy *data,
                                struct connectdata *conn,
                                bool dead_connection)
{
  CURLcode result = CURLE_OK;
  (void) dead_connection;

  DEBUGF(infof(data, "SSH DISCONNECT starts now\n"));

  if(conn->proto.sshc.ssh_session) {
    /* only if there's a session still around to use! */
    state(data, SSH_SFTP_SHUTDOWN);
    result = myssh_block_statemach(data, TRUE);
  }

  DEBUGF(infof(data, "SSH DISCONNECT is done\n"));

  return result;

}

static CURLcode sftp_done(struct Curl_easy *data, CURLcode status,
                          bool premature)
{
  struct connectdata *conn = data->conn;
  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(!premature && data->set.postquote && !conn->bits.retry)
      sshc->nextstate = SSH_SFTP_POSTQUOTE_INIT;
    state(data, SSH_SFTP_CLOSE);
  }
  return myssh_done(data, status);
}

/* return number of sent bytes */
static ssize_t sftp_send(struct Curl_easy *data, int sockindex,
                         const void *mem, size_t len, CURLcode *err)
{
  ssize_t nwrite;
  struct connectdata *conn = data->conn;
  (void)sockindex;

  nwrite = sftp_write(conn->proto.sshc.sftp_file, mem, len);

  myssh_block2waitfor(conn, FALSE);

#if 0 /* not returned by libssh on write */
2548
2549
2550
2551
2552
2553
2554
2555
2556
2557
2558

2559
2560
2561
2562
2563
2564
2565
2566
2567
2568
2569
2570
2571
2572
2573
2574
  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;

  DEBUGASSERT(len < CURL_MAX_READ_SIZE);

  switch(conn->proto.sshc.sftp_recv_state) {
    case 0:
      conn->proto.sshc.sftp_file_index =
            sftp_async_read_begin(conn->proto.sshc.sftp_file,
                                  (uint32_t)len);
      if(conn->proto.sshc.sftp_file_index < 0) {
        *err = CURLE_RECV_ERROR;
        return -1;
      }

      /* FALLTHROUGH */
    case 1:







|



>







|
|







2554
2555
2556
2557
2558
2559
2560
2561
2562
2563
2564
2565
2566
2567
2568
2569
2570
2571
2572
2573
2574
2575
2576
2577
2578
2579
2580
2581
  return nwrite;
}

/*
 * Return number of received (decrypted) bytes
 * or <0 on error
 */
static ssize_t sftp_recv(struct Curl_easy *data, int sockindex,
                         char *mem, size_t len, CURLcode *err)
{
  ssize_t nread;
  struct connectdata *conn = data->conn;
  (void)sockindex;

  DEBUGASSERT(len < CURL_MAX_READ_SIZE);

  switch(conn->proto.sshc.sftp_recv_state) {
    case 0:
      conn->proto.sshc.sftp_file_index =
        sftp_async_read_begin(conn->proto.sshc.sftp_file,
                              (uint32_t)len);
      if(conn->proto.sshc.sftp_file_index < 0) {
        *err = CURLE_RECV_ERROR;
        return -1;
      }

      /* FALLTHROUGH */
    case 1:
2594
2595
2596
2597
2598
2599
2600
2601
2602
2603
2604
2605
2606
2607
2608
2609
2610
2611

    default:
      /* we never reach here */
      return -1;
  }
}

static void sftp_quote(struct connectdata *conn)
{
  const char *cp;
  struct Curl_easy *data = conn->data;
  struct SSHPROTO *protop = data->req.p.ssh;
  struct ssh_conn *sshc = &conn->proto.sshc;
  CURLcode result;

  /*
   * Support some of the "FTP" commands
   */







|


|







2601
2602
2603
2604
2605
2606
2607
2608
2609
2610
2611
2612
2613
2614
2615
2616
2617
2618

    default:
      /* we never reach here */
      return -1;
  }
}

static void sftp_quote(struct Curl_easy *data)
{
  const char *cp;
  struct connectdata *conn = data->conn;
  struct SSHPROTO *protop = data->req.p.ssh;
  struct ssh_conn *sshc = &conn->proto.sshc;
  CURLcode result;

  /*
   * Support some of the "FTP" commands
   */
2624
2625
2626
2627
2628
2629
2630
2631
2632
2633
2634
2635
2636
2637
2638
2639
2640
2641
2642
2643
2644
2645
2646
2647
2648
2649
2650
2651
2652
2653
2654
2655
2656
2657
2658
2659
2660
2661
2662
2663
2664
2665
2666
2667
2668
2669
2670
2671
2672
2673
2674
2675
2676
2677
2678
2679
2680
2681
2682
2683

  if(strcasecompare("pwd", cmd)) {
    /* output debug output if that is requested */
    char *tmp = aprintf("257 \"%s\" is current directory.\n",
                        protop->path);
    if(!tmp) {
      sshc->actualcode = CURLE_OUT_OF_MEMORY;
      state(conn, SSH_SFTP_CLOSE);
      sshc->nextstate = SSH_NO_STATE;
      return;
    }
    Curl_debug(data, CURLINFO_HEADER_OUT, (char *) "PWD\n", 4);
    Curl_debug(data, CURLINFO_HEADER_IN, tmp, strlen(tmp));

    /* 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);
    return;
  }

  /*
   * 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;
    return;
  }

  /*
   * also, every command takes at least one argument so we get that
   * first argument right now
   */
  result = Curl_get_pathname(&cp, &sshc->quote_path1, sshc->homedir);
  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;
    return;
  }

  /*
   * SFTP is a binary protocol, so we don't send text commands







|









|


|




|










|















|







2631
2632
2633
2634
2635
2636
2637
2638
2639
2640
2641
2642
2643
2644
2645
2646
2647
2648
2649
2650
2651
2652
2653
2654
2655
2656
2657
2658
2659
2660
2661
2662
2663
2664
2665
2666
2667
2668
2669
2670
2671
2672
2673
2674
2675
2676
2677
2678
2679
2680
2681
2682
2683
2684
2685
2686
2687
2688
2689
2690

  if(strcasecompare("pwd", cmd)) {
    /* output debug output if that is requested */
    char *tmp = aprintf("257 \"%s\" is current directory.\n",
                        protop->path);
    if(!tmp) {
      sshc->actualcode = CURLE_OUT_OF_MEMORY;
      state(data, SSH_SFTP_CLOSE);
      sshc->nextstate = SSH_NO_STATE;
      return;
    }
    Curl_debug(data, CURLINFO_HEADER_OUT, (char *) "PWD\n", 4);
    Curl_debug(data, CURLINFO_HEADER_IN, tmp, strlen(tmp));

    /* 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(data, CLIENTWRITE_HEADER, tmp, strlen(tmp));
    free(tmp);
    if(result) {
      state(data, SSH_SFTP_CLOSE);
      sshc->nextstate = SSH_NO_STATE;
      sshc->actualcode = result;
    }
    else
      state(data, SSH_SFTP_NEXT_QUOTE);
    return;
  }

  /*
   * 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(data, SSH_SFTP_CLOSE);
    sshc->nextstate = SSH_NO_STATE;
    sshc->actualcode = CURLE_QUOTE_ERROR;
    return;
  }

  /*
   * also, every command takes at least one argument so we get that
   * first argument right now
   */
  result = Curl_get_pathname(&cp, &sshc->quote_path1, sshc->homedir);
  if(result) {
    if(result == CURLE_OUT_OF_MEMORY)
      failf(data, "Out of memory");
    else
      failf(data, "Syntax error: Bad first parameter");
    state(data, SSH_SFTP_CLOSE);
    sshc->nextstate = SSH_NO_STATE;
    sshc->actualcode = result;
    return;
  }

  /*
   * SFTP is a binary protocol, so we don't send text commands
2698
2699
2700
2701
2702
2703
2704
2705
2706
2707
2708
2709
2710
2711
2712
2713
2714
2715
2716
2717
2718
2719
2720
2721
2722
2723
2724
2725
2726
2727
2728
2729
2730
2731
2732
2733
2734
2735
2736
2737
2738
2739
2740
2741
2742
2743
2744
2745
2746
2747
2748
2749
2750
2751
2752
2753
2754
2755
2756
2757
2758
2759
2760
2761
2762
2763
2764
2765
2766
2767
2768
2769
2770
2771
2772
2773
2774
2775
2776
2777
2778
2779
2780
2781
2782
2783
2784
2785
2786
2787
2788
2789
2790
2791
    if(result) {
      if(result == CURLE_OUT_OF_MEMORY)
        failf(data, "Out of memory");
      else
        failf(data, "Syntax error in chgrp/chmod/chown/atime/mtime: "
              "Bad second parameter");
      Curl_safefree(sshc->quote_path1);
      state(conn, SSH_SFTP_CLOSE);
      sshc->nextstate = SSH_NO_STATE;
      sshc->actualcode = result;
      return;
    }
    sshc->quote_attrs = NULL;
    state(conn, SSH_SFTP_QUOTE_STAT);
    return;
  }
  if(strncasecompare(cmd, "ln ", 3) ||
     strncasecompare(cmd, "symlink ", 8)) {
    /* symbolic linking */
    /* sshc->quote_path1 is the source */
    /* get the destination */
    result = Curl_get_pathname(&cp, &sshc->quote_path2, sshc->homedir);
    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;
      return;
    }
    state(conn, SSH_SFTP_QUOTE_SYMLINK);
    return;
  }
  else if(strncasecompare(cmd, "mkdir ", 6)) {
    /* create dir */
    state(conn, SSH_SFTP_QUOTE_MKDIR);
    return;
  }
  else if(strncasecompare(cmd, "rename ", 7)) {
    /* rename file */
    /* first param is the source path */
    /* second param is the dest. path */
    result = Curl_get_pathname(&cp, &sshc->quote_path2, sshc->homedir);
    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;
      return;
    }
    state(conn, SSH_SFTP_QUOTE_RENAME);
    return;
  }
  else if(strncasecompare(cmd, "rmdir ", 6)) {
    /* delete dir */
    state(conn, SSH_SFTP_QUOTE_RMDIR);
    return;
  }
  else if(strncasecompare(cmd, "rm ", 3)) {
    state(conn, SSH_SFTP_QUOTE_UNLINK);
    return;
  }
#ifdef HAS_STATVFS_SUPPORT
  else if(strncasecompare(cmd, "statvfs ", 8)) {
    state(conn, SSH_SFTP_QUOTE_STATVFS);
    return;
  }
#endif

  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;
}

static void sftp_quote_stat(struct connectdata *conn)
{
  struct Curl_easy *data = conn->data;
  struct ssh_conn *sshc = &conn->proto.sshc;
  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







|





|














|




|




|













|




|




|



|




|







|




|

|







2705
2706
2707
2708
2709
2710
2711
2712
2713
2714
2715
2716
2717
2718
2719
2720
2721
2722
2723
2724
2725
2726
2727
2728
2729
2730
2731
2732
2733
2734
2735
2736
2737
2738
2739
2740
2741
2742
2743
2744
2745
2746
2747
2748
2749
2750
2751
2752
2753
2754
2755
2756
2757
2758
2759
2760
2761
2762
2763
2764
2765
2766
2767
2768
2769
2770
2771
2772
2773
2774
2775
2776
2777
2778
2779
2780
2781
2782
2783
2784
2785
2786
2787
2788
2789
2790
2791
2792
2793
2794
2795
2796
2797
2798
    if(result) {
      if(result == CURLE_OUT_OF_MEMORY)
        failf(data, "Out of memory");
      else
        failf(data, "Syntax error in chgrp/chmod/chown/atime/mtime: "
              "Bad second parameter");
      Curl_safefree(sshc->quote_path1);
      state(data, SSH_SFTP_CLOSE);
      sshc->nextstate = SSH_NO_STATE;
      sshc->actualcode = result;
      return;
    }
    sshc->quote_attrs = NULL;
    state(data, SSH_SFTP_QUOTE_STAT);
    return;
  }
  if(strncasecompare(cmd, "ln ", 3) ||
     strncasecompare(cmd, "symlink ", 8)) {
    /* symbolic linking */
    /* sshc->quote_path1 is the source */
    /* get the destination */
    result = Curl_get_pathname(&cp, &sshc->quote_path2, sshc->homedir);
    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(data, SSH_SFTP_CLOSE);
      sshc->nextstate = SSH_NO_STATE;
      sshc->actualcode = result;
      return;
    }
    state(data, SSH_SFTP_QUOTE_SYMLINK);
    return;
  }
  else if(strncasecompare(cmd, "mkdir ", 6)) {
    /* create dir */
    state(data, SSH_SFTP_QUOTE_MKDIR);
    return;
  }
  else if(strncasecompare(cmd, "rename ", 7)) {
    /* rename file */
    /* first param is the source path */
    /* second param is the dest. path */
    result = Curl_get_pathname(&cp, &sshc->quote_path2, sshc->homedir);
    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(data, SSH_SFTP_CLOSE);
      sshc->nextstate = SSH_NO_STATE;
      sshc->actualcode = result;
      return;
    }
    state(data, SSH_SFTP_QUOTE_RENAME);
    return;
  }
  else if(strncasecompare(cmd, "rmdir ", 6)) {
    /* delete dir */
    state(data, SSH_SFTP_QUOTE_RMDIR);
    return;
  }
  else if(strncasecompare(cmd, "rm ", 3)) {
    state(data, SSH_SFTP_QUOTE_UNLINK);
    return;
  }
#ifdef HAS_STATVFS_SUPPORT
  else if(strncasecompare(cmd, "statvfs ", 8)) {
    state(data, SSH_SFTP_QUOTE_STATVFS);
    return;
  }
#endif

  failf(data, "Unknown SFTP command");
  Curl_safefree(sshc->quote_path1);
  Curl_safefree(sshc->quote_path2);
  state(data, SSH_SFTP_CLOSE);
  sshc->nextstate = SSH_NO_STATE;
  sshc->actualcode = CURLE_QUOTE_ERROR;
}

static void sftp_quote_stat(struct Curl_easy *data)
{
  struct connectdata *conn = data->conn;
  struct ssh_conn *sshc = &conn->proto.sshc;
  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
2805
2806
2807
2808
2809
2810
2811
2812
2813
2814
2815
2816
2817
2818
2819
2820
2821
2822
2823
2824
2825
2826
2827
2828
2829
2830
2831
2832
2833
2834
2835
2836
2837
2838
2839
2840
2841
2842
2843
2844
2845
2846
2847
2848
2849
2850
2851
2852
2853
2854
2855
2856
2857
2858
2859
2860
2861
2862
2863
2864
2865
2866
2867
2868
2869
2870
2871
2872
2873
2874
2875
2876
2877
2878
2879
2880
2881
2882
2883
2884
2885
2886
2887
2888
2889
2890
2891
2892
2893
2894
2895
2896
2897
2898
2899
2900
    sftp_attributes_free(sshc->quote_attrs);
  sshc->quote_attrs = sftp_stat(sshc->sftp_session, sshc->quote_path2);
  if(sshc->quote_attrs == NULL) {
    Curl_safefree(sshc->quote_path1);
    Curl_safefree(sshc->quote_path2);
    failf(data, "Attempt to get SFTP stats failed: %d",
          sftp_get_error(sshc->sftp_session));
    state(conn, SSH_SFTP_CLOSE);
    sshc->nextstate = SSH_NO_STATE;
    sshc->actualcode = CURLE_QUOTE_ERROR;
    return;
  }

  /* Now set the new attributes... */
  if(strncasecompare(cmd, "chgrp", 5)) {
    sshc->quote_attrs->gid = (uint32_t)strtoul(sshc->quote_path1, NULL, 10);
    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;
      return;
    }
    sshc->quote_attrs->flags |= SSH_FILEXFER_ATTR_UIDGID;
  }
  else if(strncasecompare(cmd, "chmod", 5)) {
    mode_t perms;
    perms = (mode_t)strtoul(sshc->quote_path1, NULL, 8);
    /* permissions are octal */
    if(perms == 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;
      return;
    }
    sshc->quote_attrs->permissions = perms;
    sshc->quote_attrs->flags |= SSH_FILEXFER_ATTR_PERMISSIONS;
  }
  else if(strncasecompare(cmd, "chown", 5)) {
    sshc->quote_attrs->uid = (uint32_t)strtoul(sshc->quote_path1, NULL, 10);
    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;
      return;
    }
    sshc->quote_attrs->flags |= SSH_FILEXFER_ATTR_UIDGID;
  }
  else if(strncasecompare(cmd, "atime", 5)) {
    time_t date = Curl_getdate_capped(sshc->quote_path1);
    if(date == -1) {
      Curl_safefree(sshc->quote_path1);
      Curl_safefree(sshc->quote_path2);
      failf(data, "Syntax error: incorrect access date format");
      state(conn, SSH_SFTP_CLOSE);
      sshc->nextstate = SSH_NO_STATE;
      sshc->actualcode = CURLE_QUOTE_ERROR;
      return;
    }
    sshc->quote_attrs->atime = (uint32_t)date;
    sshc->quote_attrs->flags |= SSH_FILEXFER_ATTR_ACMODTIME;
  }
  else if(strncasecompare(cmd, "mtime", 5)) {
    time_t date = Curl_getdate_capped(sshc->quote_path1);
    if(date == -1) {
      Curl_safefree(sshc->quote_path1);
      Curl_safefree(sshc->quote_path2);
      failf(data, "Syntax error: incorrect modification date format");
      state(conn, SSH_SFTP_CLOSE);
      sshc->nextstate = SSH_NO_STATE;
      sshc->actualcode = CURLE_QUOTE_ERROR;
      return;
    }
    sshc->quote_attrs->mtime = (uint32_t)date;
    sshc->quote_attrs->flags |= SSH_FILEXFER_ATTR_ACMODTIME;
  }

  /* Now send the completed structure... */
  state(conn, SSH_SFTP_QUOTE_SETSTAT);
  return;
}

CURLcode Curl_ssh_init(void)
{
  if(ssh_init()) {
    DEBUGF(fprintf(stderr, "Error: libssh_init failed\n"));







|













|














|














|












|













|









|







2812
2813
2814
2815
2816
2817
2818
2819
2820
2821
2822
2823
2824
2825
2826
2827
2828
2829
2830
2831
2832
2833
2834
2835
2836
2837
2838
2839
2840
2841
2842
2843
2844
2845
2846
2847
2848
2849
2850
2851
2852
2853
2854
2855
2856
2857
2858
2859
2860
2861
2862
2863
2864
2865
2866
2867
2868
2869
2870
2871
2872
2873
2874
2875
2876
2877
2878
2879
2880
2881
2882
2883
2884
2885
2886
2887
2888
2889
2890
2891
2892
2893
2894
2895
2896
2897
2898
2899
2900
2901
2902
2903
2904
2905
2906
2907
    sftp_attributes_free(sshc->quote_attrs);
  sshc->quote_attrs = sftp_stat(sshc->sftp_session, sshc->quote_path2);
  if(sshc->quote_attrs == NULL) {
    Curl_safefree(sshc->quote_path1);
    Curl_safefree(sshc->quote_path2);
    failf(data, "Attempt to get SFTP stats failed: %d",
          sftp_get_error(sshc->sftp_session));
    state(data, SSH_SFTP_CLOSE);
    sshc->nextstate = SSH_NO_STATE;
    sshc->actualcode = CURLE_QUOTE_ERROR;
    return;
  }

  /* Now set the new attributes... */
  if(strncasecompare(cmd, "chgrp", 5)) {
    sshc->quote_attrs->gid = (uint32_t)strtoul(sshc->quote_path1, NULL, 10);
    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(data, SSH_SFTP_CLOSE);
      sshc->nextstate = SSH_NO_STATE;
      sshc->actualcode = CURLE_QUOTE_ERROR;
      return;
    }
    sshc->quote_attrs->flags |= SSH_FILEXFER_ATTR_UIDGID;
  }
  else if(strncasecompare(cmd, "chmod", 5)) {
    mode_t perms;
    perms = (mode_t)strtoul(sshc->quote_path1, NULL, 8);
    /* permissions are octal */
    if(perms == 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(data, SSH_SFTP_CLOSE);
      sshc->nextstate = SSH_NO_STATE;
      sshc->actualcode = CURLE_QUOTE_ERROR;
      return;
    }
    sshc->quote_attrs->permissions = perms;
    sshc->quote_attrs->flags |= SSH_FILEXFER_ATTR_PERMISSIONS;
  }
  else if(strncasecompare(cmd, "chown", 5)) {
    sshc->quote_attrs->uid = (uint32_t)strtoul(sshc->quote_path1, NULL, 10);
    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(data, SSH_SFTP_CLOSE);
      sshc->nextstate = SSH_NO_STATE;
      sshc->actualcode = CURLE_QUOTE_ERROR;
      return;
    }
    sshc->quote_attrs->flags |= SSH_FILEXFER_ATTR_UIDGID;
  }
  else if(strncasecompare(cmd, "atime", 5)) {
    time_t date = Curl_getdate_capped(sshc->quote_path1);
    if(date == -1) {
      Curl_safefree(sshc->quote_path1);
      Curl_safefree(sshc->quote_path2);
      failf(data, "Syntax error: incorrect access date format");
      state(data, SSH_SFTP_CLOSE);
      sshc->nextstate = SSH_NO_STATE;
      sshc->actualcode = CURLE_QUOTE_ERROR;
      return;
    }
    sshc->quote_attrs->atime = (uint32_t)date;
    sshc->quote_attrs->flags |= SSH_FILEXFER_ATTR_ACMODTIME;
  }
  else if(strncasecompare(cmd, "mtime", 5)) {
    time_t date = Curl_getdate_capped(sshc->quote_path1);
    if(date == -1) {
      Curl_safefree(sshc->quote_path1);
      Curl_safefree(sshc->quote_path2);
      failf(data, "Syntax error: incorrect modification date format");
      state(data, SSH_SFTP_CLOSE);
      sshc->nextstate = SSH_NO_STATE;
      sshc->actualcode = CURLE_QUOTE_ERROR;
      return;
    }
    sshc->quote_attrs->mtime = (uint32_t)date;
    sshc->quote_attrs->flags |= SSH_FILEXFER_ATTR_ACMODTIME;
  }

  /* Now send the completed structure... */
  state(data, SSH_SFTP_QUOTE_SETSTAT);
  return;
}

CURLcode Curl_ssh_init(void)
{
  if(ssh_init()) {
    DEBUGF(fprintf(stderr, "Error: libssh_init failed\n"));
Changes to jni/curl/lib/vssh/libssh2.c.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2020, 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 https://curl.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







|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2021, 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 https://curl.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
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129

130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154

/* Local functions: */
static const char *sftp_libssh2_strerror(unsigned long err);
static LIBSSH2_ALLOC_FUNC(my_libssh2_malloc);
static LIBSSH2_REALLOC_FUNC(my_libssh2_realloc);
static LIBSSH2_FREE_FUNC(my_libssh2_free);

static CURLcode ssh_force_knownhost_key_type(struct connectdata *conn);
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 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);
static int ssh_perform_getsock(const struct connectdata *conn,
                               curl_socket_t *sock);
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 */
  ZERO_NULL,                            /* connection_check */
  PORT_SSH,                             /* defport */
  CURLPROTO_SCP,                        /* protocol */
  CURLPROTO_SCP,                        /* family */
  PROTOPT_DIRLOCK | PROTOPT_CLOSEACTION







|
|
|
|
<
|
<
|
<
|
|
|
<
|
<
|
<
|
|
|
|
<
|
|
>

















|







99
100
101
102
103
104
105
106
107
108
109

110

111

112
113
114

115

116

117
118
119
120

121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148

/* Local functions: */
static const char *sftp_libssh2_strerror(unsigned long err);
static LIBSSH2_ALLOC_FUNC(my_libssh2_malloc);
static LIBSSH2_REALLOC_FUNC(my_libssh2_realloc);
static LIBSSH2_FREE_FUNC(my_libssh2_free);

static CURLcode ssh_force_knownhost_key_type(struct Curl_easy *data);
static CURLcode ssh_connect(struct Curl_easy *data, bool *done);
static CURLcode ssh_multi_statemach(struct Curl_easy *data, bool *done);
static CURLcode ssh_do(struct Curl_easy *data, bool *done);

static CURLcode scp_done(struct Curl_easy *data, CURLcode c, bool premature);

static CURLcode scp_doing(struct Curl_easy *data, bool *dophase_done);

static CURLcode scp_disconnect(struct Curl_easy *data,
                               struct connectdata *conn, bool dead_connection);
static CURLcode sftp_done(struct Curl_easy *data, CURLcode, bool premature);

static CURLcode sftp_doing(struct Curl_easy *data, bool *dophase_done);

static CURLcode sftp_disconnect(struct Curl_easy *data,

                                struct connectdata *conn, bool dead);
static CURLcode sftp_perform(struct Curl_easy *data, bool *connected,
                             bool *dophase_done);
static int ssh_getsock(struct Curl_easy *data, struct connectdata *conn,

                       curl_socket_t *sock);
static CURLcode ssh_setup_connection(struct Curl_easy *data,
                                     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_getsock,                          /* perform_getsock */
  scp_disconnect,                       /* disconnect */
  ZERO_NULL,                            /* readwrite */
  ZERO_NULL,                            /* connection_check */
  PORT_SSH,                             /* defport */
  CURLPROTO_SCP,                        /* protocol */
  CURLPROTO_SCP,                        /* family */
  PROTOPT_DIRLOCK | PROTOPT_CLOSEACTION
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
  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 */
  ZERO_NULL,                            /* connection_check */
  PORT_SSH,                             /* defport */
  CURLPROTO_SFTP,                       /* protocol */
  CURLPROTO_SFTP,                       /* family */
  PROTOPT_DIRLOCK | PROTOPT_CLOSEACTION







|







162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
  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_getsock,                          /* perform_getsock */
  sftp_disconnect,                      /* disconnect */
  ZERO_NULL,                            /* readwrite */
  ZERO_NULL,                            /* connection_check */
  PORT_SSH,                             /* defport */
  CURLPROTO_SFTP,                       /* protocol */
  CURLPROTO_SFTP,                       /* family */
  PROTOPT_DIRLOCK | PROTOPT_CLOSEACTION
304
305
306
307
308
309
310
311
312

313
314
315
316
317
318
319
    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",







|

>







298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
    free(ptr);
}

/*
 * SSH State machine related code
 */
/* This is the ONLY way to change SSH state! */
static void state(struct Curl_easy *data, sshstate nowstate)
{
  struct connectdata *conn = data->conn;
  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",
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
    "QUIT"
  };

  /* a precaution to make sure the lists are in sync */
  DEBUGASSERT(sizeof(names)/sizeof(names[0]) == SSH_LAST);

  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;
}








|







371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
    "QUIT"
  };

  /* a precaution to make sure the lists are in sync */
  DEBUGASSERT(sizeof(names)/sizeof(names[0]) == SSH_LAST);

  if(sshc->state != nowstate) {
    infof(data, "SFTP %p state change from %s to %s\n",
          (void *)sshc, names[sshc->state], names[nowstate]);
  }
#endif

  sshc->state = nowstate;
}

430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445

446
447
448
449
450
451
452
/*
 * 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 Curl_easy *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;
    struct libssh2_knownhost *host = NULL;
    int rc;
    int keytype;
    size_t keylen;
    const char *remotekey = libssh2_session_hostkey(sshc->ssh_session,
                                                    &keylen, &keytype);







|




<
<


>







425
426
427
428
429
430
431
432
433
434
435
436


437
438
439
440
441
442
443
444
445
446
/*
 * 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 Curl_easy *data)
{
  CURLcode result = CURLE_OK;

#ifdef HAVE_LIBSSH2_KNOWNHOST_API


  if(data->set.str[STRING_SSH_KNOWNHOSTS]) {
    /* we're asked to verify the host against a file */
    struct connectdata *conn = data->conn;
    struct ssh_conn *sshc = &conn->proto.sshc;
    struct libssh2_knownhost *host = NULL;
    int rc;
    int keytype;
    size_t keylen;
    const char *remotekey = libssh2_session_hostkey(sshc->ssh_session,
                                                    &keylen, &keytype);
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
      /* 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_REPLACE:
      /* remove old host+key that doesn't match */







|







554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
      /* no remotekey means failure! */
      rc = CURLKHSTAT_REJECT;

    switch(rc) {
    default: /* unknown return codes will equal reject */
      /* FALLTHROUGH */
    case CURLKHSTAT_REJECT:
      state(data, 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_REPLACE:
      /* remove old host+key that doesn't match */
605
606
607
608
609
610
611
612
613
614
615
616
617
618

619
620
621
622
623
624
625
626
627
          }
        }
      }
      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 Curl_easy *data = conn->data;
  const char *pubkey_md5 = data->set.str[STRING_SSH_HOST_PUBLIC_KEY_MD5];
  char md5buffer[33];

  const char *fingerprint = libssh2_hostkey_hash(sshc->ssh_session,
      LIBSSH2_HOSTKEY_HASH_MD5);

  if(fingerprint) {







|




|

>

<







599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614

615
616
617
618
619
620
621
          }
        }
      }
      break;
    }
  }
#else /* HAVE_LIBSSH2_KNOWNHOST_API */
  (void)data;
#endif
  return result;
}

static CURLcode ssh_check_fingerprint(struct Curl_easy *data)
{
  struct connectdata *conn = data->conn;
  struct ssh_conn *sshc = &conn->proto.sshc;

  const char *pubkey_md5 = data->set.str[STRING_SSH_HOST_PUBLIC_KEY_MD5];
  char md5buffer[33];

  const char *fingerprint = libssh2_hostkey_hash(sshc->ssh_session,
      LIBSSH2_HOSTKEY_HASH_MD5);

  if(fingerprint) {
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
      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;
    }
    infof(data, "MD5 checksum match!\n");
    /* as we already matched, we skip the check for known hosts */
    return CURLE_OK;
  }
  return ssh_knownhost(conn);
}

/*
 * ssh_force_knownhost_key_type() will check the known hosts file and try to
 * force a specific public key type from the server if an entry is found.
 */
static CURLcode ssh_force_knownhost_key_type(struct connectdata *conn)
{
  CURLcode result = CURLE_OK;

#ifdef HAVE_LIBSSH2_KNOWNHOST_API

#ifdef LIBSSH2_KNOWNHOST_KEY_ED25519
  static const char * const hostkey_method_ssh_ed25519







|







|






|







634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
      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(data, SSH_SESSION_FREE);
      sshc->actualcode = CURLE_PEER_FAILED_VERIFICATION;
      return sshc->actualcode;
    }
    infof(data, "MD5 checksum match!\n");
    /* as we already matched, we skip the check for known hosts */
    return CURLE_OK;
  }
  return ssh_knownhost(data);
}

/*
 * ssh_force_knownhost_key_type() will check the known hosts file and try to
 * force a specific public key type from the server if an entry is found.
 */
static CURLcode ssh_force_knownhost_key_type(struct Curl_easy *data)
{
  CURLcode result = CURLE_OK;

#ifdef HAVE_LIBSSH2_KNOWNHOST_API

#ifdef LIBSSH2_KNOWNHOST_KEY_ED25519
  static const char * const hostkey_method_ssh_ed25519
683
684
685
686
687
688
689

690
691
692
693
694
695
696
697
698
#endif
  static const char * const hostkey_method_ssh_rsa
    = "ssh-rsa";
  static const char * const hostkey_method_ssh_dss
    = "ssh-dss";

  const char *hostkey_method = NULL;

  struct ssh_conn *sshc = &conn->proto.sshc;
  struct Curl_easy *data = conn->data;
  struct libssh2_knownhost* store = NULL;
  const char *kh_name_end = NULL;
  size_t kh_name_size = 0;
  int port = 0;
  bool found = false;

  if(sshc->kh && !data->set.str[STRING_SSH_HOST_PUBLIC_KEY_MD5]) {







>

<







677
678
679
680
681
682
683
684
685

686
687
688
689
690
691
692
#endif
  static const char * const hostkey_method_ssh_rsa
    = "ssh-rsa";
  static const char * const hostkey_method_ssh_dss
    = "ssh-dss";

  const char *hostkey_method = NULL;
  struct connectdata *conn = data->conn;
  struct ssh_conn *sshc = &conn->proto.sshc;

  struct libssh2_knownhost* store = NULL;
  const char *kh_name_end = NULL;
  size_t kh_name_size = 0;
  int port = 0;
  bool found = false;

  if(sshc->kh && !data->set.str[STRING_SSH_HOST_PUBLIC_KEY_MD5]) {
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
      case LIBSSH2_KNOWNHOST_KEY_SSHRSA:
        hostkey_method = hostkey_method_ssh_rsa;
        break;
      case LIBSSH2_KNOWNHOST_KEY_SSHDSS:
        hostkey_method = hostkey_method_ssh_dss;
        break;
      case LIBSSH2_KNOWNHOST_KEY_RSA1:
        failf(data, "Found host key type RSA1 which is not supported\n");
        return CURLE_SSH;
      default:
        failf(data, "Unknown host key type: %i\n",
              (store->typemask & LIBSSH2_KNOWNHOST_KEY_MASK));
        return CURLE_SSH;
      }

      infof(data, "Set \"%s\" as SSH hostkey type\n", hostkey_method);
      result = libssh2_session_error_to_CURLE(
          libssh2_session_method_pref(
              sshc->ssh_session, LIBSSH2_METHOD_HOSTKEY, hostkey_method));
    }
    else {
      infof(data, "Did not find host %s in %s\n",
            conn->host.name, data->set.str[STRING_SSH_KNOWNHOSTS]);
    }
  }

#endif /* HAVE_LIBSSH2_KNOWNHOST_API */

  return result;
}

/*
 * 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 Curl_easy *data = conn->data;
  struct SSHPROTO *sftp_scp = data->req.p.ssh;
  struct ssh_conn *sshc = &conn->proto.sshc;
  curl_socket_t sock = conn->sock[FIRSTSOCKET];
  int rc = LIBSSH2_ERROR_NONE;
  int ssherr;
  unsigned long sftperr;
  int seekerr = CURL_SEEKFUNC_OK;
  size_t readdir_len;
  *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);

      result = ssh_force_knownhost_key_type(conn);
      if(result) {
        state(conn, SSH_SESSION_FREE);
        sshc->actualcode = result;
        break;
      }

      state(conn, SSH_S_STARTUP);
      /* FALLTHROUGH */

    case SSH_S_STARTUP:
      rc = libssh2_session_startup(sshc->ssh_session, (int)sock);
      if(rc == LIBSSH2_ERROR_EAGAIN) {
        break;
      }
      if(rc) {
        char *err_msg = NULL;
        (void)libssh2_session_last_error(sshc->ssh_session, &err_msg, NULL, 0);
        failf(data, "Failure establishing ssh session: %d, %s", rc, err_msg);

        state(conn, SSH_SESSION_FREE);
        sshc->actualcode = CURLE_FAILED_INIT;
        break;
      }

      state(conn, SSH_HOSTKEY);

      /* FALLTHROUGH */
    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







|


|






|
|



















|


|
|










<










|

|




|












|




|








|

|







753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805

806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
      case LIBSSH2_KNOWNHOST_KEY_SSHRSA:
        hostkey_method = hostkey_method_ssh_rsa;
        break;
      case LIBSSH2_KNOWNHOST_KEY_SSHDSS:
        hostkey_method = hostkey_method_ssh_dss;
        break;
      case LIBSSH2_KNOWNHOST_KEY_RSA1:
        failf(data, "Found host key type RSA1 which is not supported");
        return CURLE_SSH;
      default:
        failf(data, "Unknown host key type: %i",
              (store->typemask & LIBSSH2_KNOWNHOST_KEY_MASK));
        return CURLE_SSH;
      }

      infof(data, "Set \"%s\" as SSH hostkey type\n", hostkey_method);
      result = libssh2_session_error_to_CURLE(
        libssh2_session_method_pref(
          sshc->ssh_session, LIBSSH2_METHOD_HOSTKEY, hostkey_method));
    }
    else {
      infof(data, "Did not find host %s in %s\n",
            conn->host.name, data->set.str[STRING_SSH_KNOWNHOSTS]);
    }
  }

#endif /* HAVE_LIBSSH2_KNOWNHOST_API */

  return result;
}

/*
 * 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 Curl_easy *data, bool *block)
{
  CURLcode result = CURLE_OK;
  struct connectdata *conn = data->conn;
  struct SSHPROTO *sshp = data->req.p.ssh;
  struct ssh_conn *sshc = &conn->proto.sshc;
  curl_socket_t sock = conn->sock[FIRSTSOCKET];
  int rc = LIBSSH2_ERROR_NONE;
  int ssherr;
  unsigned long sftperr;
  int seekerr = CURL_SEEKFUNC_OK;
  size_t readdir_len;
  *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);

      result = ssh_force_knownhost_key_type(data);
      if(result) {
        state(data, SSH_SESSION_FREE);
        sshc->actualcode = result;
        break;
      }

      state(data, SSH_S_STARTUP);
      /* FALLTHROUGH */

    case SSH_S_STARTUP:
      rc = libssh2_session_startup(sshc->ssh_session, (int)sock);
      if(rc == LIBSSH2_ERROR_EAGAIN) {
        break;
      }
      if(rc) {
        char *err_msg = NULL;
        (void)libssh2_session_last_error(sshc->ssh_session, &err_msg, NULL, 0);
        failf(data, "Failure establishing ssh session: %d, %s", rc, err_msg);

        state(data, SSH_SESSION_FREE);
        sshc->actualcode = CURLE_FAILED_INIT;
        break;
      }

      state(data, SSH_HOSTKEY);

      /* FALLTHROUGH */
    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(data);
      if(!result)
        state(data, 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
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
                                             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;
        }
        ssherr = libssh2_session_last_errno(sshc->ssh_session);
        if(ssherr == LIBSSH2_ERROR_EAGAIN)
          rc = LIBSSH2_ERROR_EAGAIN;
        else {
          state(conn, SSH_SESSION_FREE);
          sshc->actualcode = libssh2_session_error_to_CURLE(ssherr);
        }
        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
       */







|






|







|







868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
                                             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(data, SSH_AUTH_DONE);
          break;
        }
        ssherr = libssh2_session_last_errno(sshc->ssh_session);
        if(ssherr == LIBSSH2_ERROR_EAGAIN)
          rc = LIBSSH2_ERROR_EAGAIN;
        else {
          state(data, SSH_SESSION_FREE);
          sshc->actualcode = libssh2_session_error_to_CURLE(ssherr);
        }
        break;
      }
      infof(data, "SSH authentication methods available: %s\n",
            sshc->authlist);

      state(data, 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
       */
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
          if(!sshc->rsa_pub)
            out_of_memory = TRUE;
        }

        if(out_of_memory || sshc->rsa == NULL) {
          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.ssl.key_passwd;
        if(!sshc->passphrase)
          sshc->passphrase = "";

        if(sshc->rsa_pub)
          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,







|












|


|







955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
          if(!sshc->rsa_pub)
            out_of_memory = TRUE;
        }

        if(out_of_memory || sshc->rsa == NULL) {
          Curl_safefree(sshc->rsa);
          Curl_safefree(sshc->rsa_pub);
          state(data, SSH_SESSION_FREE);
          sshc->actualcode = CURLE_OUT_OF_MEMORY;
          break;
        }

        sshc->passphrase = data->set.ssl.key_passwd;
        if(!sshc->passphrase)
          sshc->passphrase = "";

        if(sshc->rsa_pub)
          infof(data, "Using SSH public key file '%s'\n", sshc->rsa_pub);
        infof(data, "Using SSH private key file '%s'\n", sshc->rsa);

        state(data, SSH_AUTH_PKEY);
      }
      else {
        state(data, 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,
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119

      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 = NULL;
        (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);
        rc = 0; /* clear rc and continue */
      }
      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);
        rc = 0; /* clear rc and continue */
      }
      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;
      }
      if(rc == 0) {
        sshc->authed = TRUE;
        infof(data, "Initialized password authentication\n");
        state(conn, SSH_AUTH_DONE);
      }
      else {
        state(conn, SSH_AUTH_HOST_INIT);
        rc = 0; /* clear rc and continue */
      }
      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);
          rc = 0; /* clear rc and continue */
        }
        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);
        rc = 0; /* clear rc and continue */
      }
      else {
        state(conn, SSH_AUTH_AGENT);
        sshc->sshagent_prev_identity = NULL;
      }
#endif
      break;

    case SSH_AUTH_AGENT:
#ifdef HAVE_LIBSSH2_AGENT_API







|






|







|


|
















|


|







|


|




|















|









|



|




|










|



|







994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112

      Curl_safefree(sshc->rsa_pub);
      Curl_safefree(sshc->rsa);

      if(rc == 0) {
        sshc->authed = TRUE;
        infof(data, "Initialized SSH public key authentication\n");
        state(data, SSH_AUTH_DONE);
      }
      else {
        char *err_msg = NULL;
        (void)libssh2_session_last_error(sshc->ssh_session,
                                         &err_msg, NULL, 0);
        infof(data, "SSH public key authentication failed: %s\n", err_msg);
        state(data, SSH_AUTH_PASS_INIT);
        rc = 0; /* clear rc and continue */
      }
      break;

    case SSH_AUTH_PASS_INIT:
      if((data->set.ssh_auth_types & CURLSSH_AUTH_PASSWORD) &&
         (strstr(sshc->authlist, "password") != NULL)) {
        state(data, SSH_AUTH_PASS);
      }
      else {
        state(data, SSH_AUTH_HOST_INIT);
        rc = 0; /* clear rc and continue */
      }
      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;
      }
      if(rc == 0) {
        sshc->authed = TRUE;
        infof(data, "Initialized password authentication\n");
        state(data, SSH_AUTH_DONE);
      }
      else {
        state(data, SSH_AUTH_HOST_INIT);
        rc = 0; /* clear rc and continue */
      }
      break;

    case SSH_AUTH_HOST_INIT:
      if((data->set.ssh_auth_types & CURLSSH_AUTH_HOST) &&
         (strstr(sshc->authlist, "hostbased") != NULL)) {
        state(data, SSH_AUTH_HOST);
      }
      else {
        state(data, SSH_AUTH_AGENT_INIT);
      }
      break;

    case SSH_AUTH_HOST:
      state(data, 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(data, 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(data, SSH_AUTH_KEY_INIT);
          rc = 0; /* clear rc and continue */
        }
        else {
          state(data, SSH_AUTH_AGENT_LIST);
        }
      }
      else
#endif /* HAVE_LIBSSH2_AGENT_API */
        state(data, 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(data, SSH_AUTH_KEY_INIT);
        rc = 0; /* clear rc and continue */
      }
      else {
        state(data, SSH_AUTH_AGENT);
        sshc->sshagent_prev_identity = NULL;
      }
#endif
      break;

    case SSH_AUTH_AGENT:
#ifdef HAVE_LIBSSH2_AGENT_API
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
        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);
        rc = 0; /* clear rc and continue */
      }
#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;
      }
      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) {
        char *err_msg = NULL;
        if(libssh2_session_last_errno(sshc->ssh_session) ==
           LIBSSH2_ERROR_EAGAIN) {
          rc = LIBSSH2_ERROR_EAGAIN;
          break;
        }

        (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;
      }
      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 */
        sftperr = libssh2_sftp_last_error(sshc->sftp_session);
        if(sftperr)
          result = sftp_libssh2_error_to_CURLE(sftperr);
        else
          /* in this case, the error wasn't in the SFTP level but for example
             a time-out or similar */
          result = CURLE_SSH;
        sshc->actualcode = result;
        DEBUGF(infof(data, "error = %lu makes libcurl = %d\n",
                     sftperr, (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 = Curl_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_GETINFO);
      }
      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;







|


|








|


|

















|





|









|





|



|


















|



|



















|



|













|








|




|


|






|


|







|


|







1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
        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(data, SSH_AUTH_DONE);
      }
      else {
        state(data, SSH_AUTH_KEY_INIT);
        rc = 0; /* clear rc and continue */
      }
#endif
      break;

    case SSH_AUTH_KEY_INIT:
      if((data->set.ssh_auth_types & CURLSSH_AUTH_KEYBOARD)
         && (strstr(sshc->authlist, "keyboard-interactive") != NULL)) {
        state(data, SSH_AUTH_KEY);
      }
      else {
        state(data, 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;
      }
      if(rc == 0) {
        sshc->authed = TRUE;
        infof(data, "Initialized keyboard interactive authentication\n");
      }
      state(data, SSH_AUTH_DONE);
      break;

    case SSH_AUTH_DONE:
      if(!sshc->authed) {
        failf(data, "Authentication failure");
        state(data, 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(data, TIMER_APPCONNECT); /* SSH is connected */

      conn->sockfd = sock;
      conn->writesockfd = CURL_SOCKET_BAD;

      if(conn->handler->protocol == CURLPROTO_SFTP) {
        state(data, SSH_SFTP_INIT);
        break;
      }
      infof(data, "SSH CONNECT phase done\n");
      state(data, 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) {
        char *err_msg = NULL;
        if(libssh2_session_last_errno(sshc->ssh_session) ==
           LIBSSH2_ERROR_EAGAIN) {
          rc = LIBSSH2_ERROR_EAGAIN;
          break;
        }

        (void)libssh2_session_last_error(sshc->ssh_session,
                                         &err_msg, NULL, 0);
        failf(data, "Failure initializing sftp session: %s", err_msg);
        state(data, SSH_SESSION_FREE);
        sshc->actualcode = CURLE_FAILED_INIT;
        break;
      }
      state(data, 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;
      }
      if(rc > 0) {
        /* It seems that this string is not always NULL terminated */
        tempHome[rc] = '\0';
        sshc->homedir = strdup(tempHome);
        if(!sshc->homedir) {
          state(data, SSH_SFTP_CLOSE);
          sshc->actualcode = CURLE_OUT_OF_MEMORY;
          break;
        }
        data->state.most_recent_ftp_entrypath = sshc->homedir;
      }
      else {
        /* Return the error type */
        sftperr = libssh2_sftp_last_error(sshc->sftp_session);
        if(sftperr)
          result = sftp_libssh2_error_to_CURLE(sftperr);
        else
          /* in this case, the error wasn't in the SFTP level but for example
             a time-out or similar */
          result = CURLE_SSH;
        sshc->actualcode = result;
        DEBUGF(infof(data, "error = %lu makes libcurl = %d\n",
                     sftperr, (int)result));
        state(data, 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(data, SSH_STOP);
    break;

    case SSH_SFTP_QUOTE_INIT:

      result = Curl_getworkingpath(data, sshc->homedir, &sshp->path);
      if(result) {
        sshc->actualcode = result;
        state(data, SSH_STOP);
        break;
      }

      if(data->set.quote) {
        infof(data, "Sending quote commands\n");
        sshc->quote_item = data->set.quote;
        state(data, SSH_SFTP_QUOTE);
      }
      else {
        state(data, SSH_SFTP_GETINFO);
      }
      break;

    case SSH_SFTP_POSTQUOTE_INIT:
      if(data->set.postquote) {
        infof(data, "Sending quote commands\n");
        sshc->quote_item = data->set.postquote;
        state(data, SSH_SFTP_QUOTE);
      }
      else {
        state(data, SSH_STOP);
      }
      break;

    case SSH_SFTP_QUOTE:
      /* Send any quote commands */
    {
      const char *cp;
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
        cmd++;
        sshc->acceptfail = TRUE;
      }

      if(strcasecompare("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;
        }
        Curl_debug(data, CURLINFO_HEADER_OUT, (char *)"PWD\n", 4);
        Curl_debug(data, CURLINFO_HEADER_IN, tmp, strlen(tmp));

        /* 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;
      }
      {
        /*
         * 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 command '%s'. Missing parameter!",
                cmd);
          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 = Curl_get_pathname(&cp, &sshc->quote_path1, sshc->homedir);
        if(result) {
          if(result == CURLE_OUT_OF_MEMORY)
            failf(data, "Out of memory");
          else
            failf(data, "Syntax error: Bad first parameter to '%s'", cmd);
          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







|


|









|


|




|











|















|







1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
        cmd++;
        sshc->acceptfail = TRUE;
      }

      if(strcasecompare("pwd", cmd)) {
        /* output debug output if that is requested */
        char *tmp = aprintf("257 \"%s\" is current directory.\n",
                            sshp->path);
        if(!tmp) {
          result = CURLE_OUT_OF_MEMORY;
          state(data, SSH_SFTP_CLOSE);
          sshc->nextstate = SSH_NO_STATE;
          break;
        }
        Curl_debug(data, CURLINFO_HEADER_OUT, (char *)"PWD\n", 4);
        Curl_debug(data, CURLINFO_HEADER_IN, tmp, strlen(tmp));

        /* 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(data, CLIENTWRITE_HEADER, tmp, strlen(tmp));
        free(tmp);
        if(result) {
          state(data, SSH_SFTP_CLOSE);
          sshc->nextstate = SSH_NO_STATE;
          sshc->actualcode = result;
        }
        else
          state(data, SSH_SFTP_NEXT_QUOTE);
        break;
      }
      {
        /*
         * 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 command '%s'. Missing parameter!",
                cmd);
          state(data, 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 = Curl_get_pathname(&cp, &sshc->quote_path1, sshc->homedir);
        if(result) {
          if(result == CURLE_OUT_OF_MEMORY)
            failf(data, "Out of memory");
          else
            failf(data, "Syntax error: Bad first parameter to '%s'", cmd);
          state(data, SSH_SFTP_CLOSE);
          sshc->nextstate = SSH_NO_STATE;
          sshc->actualcode = result;
          break;
        }

        /*
         * SFTP is a binary protocol, so we don't send text commands
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
          result = Curl_get_pathname(&cp, &sshc->quote_path2, sshc->homedir);
          if(result) {
            if(result == CURLE_OUT_OF_MEMORY)
              failf(data, "Out of memory");
            else
              failf(data, "Syntax error in %s: Bad second parameter", cmd);
            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;
        }
        if(strncasecompare(cmd, "ln ", 3) ||
           strncasecompare(cmd, "symlink ", 8)) {
          /* symbolic linking */
          /* sshc->quote_path1 is the source */
          /* get the destination */
          result = Curl_get_pathname(&cp, &sshc->quote_path2, sshc->homedir);
          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(strncasecompare(cmd, "mkdir ", 6)) {
          /* create dir */
          state(conn, SSH_SFTP_QUOTE_MKDIR);
          break;
        }
        else if(strncasecompare(cmd, "rename ", 7)) {
          /* rename file */
          /* first param is the source path */
          /* second param is the dest. path */
          result = Curl_get_pathname(&cp, &sshc->quote_path2, sshc->homedir);
          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(strncasecompare(cmd, "rmdir ", 6)) {
          /* delete dir */
          state(conn, SSH_SFTP_QUOTE_RMDIR);
          break;
        }
        else if(strncasecompare(cmd, "rm ", 3)) {
          state(conn, SSH_SFTP_QUOTE_UNLINK);
          break;
        }
#ifdef HAS_STATVFS_SUPPORT
        else if(strncasecompare(cmd, "statvfs ", 8)) {
          state(conn, SSH_SFTP_QUOTE_STATVFS);
          break;
        }
#endif

        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;
      }
    }
    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_GETINFO);
        }
      }
      break;

    case SSH_SFTP_QUOTE_STAT:
    {
      char *cmd = sshc->quote_item->data;







|




|
|















|




|




|













|




|




|



|




|







|














|



|



|







1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
          result = Curl_get_pathname(&cp, &sshc->quote_path2, sshc->homedir);
          if(result) {
            if(result == CURLE_OUT_OF_MEMORY)
              failf(data, "Out of memory");
            else
              failf(data, "Syntax error in %s: Bad second parameter", cmd);
            Curl_safefree(sshc->quote_path1);
            state(data, SSH_SFTP_CLOSE);
            sshc->nextstate = SSH_NO_STATE;
            sshc->actualcode = result;
            break;
          }
          memset(&sshp->quote_attrs, 0, sizeof(LIBSSH2_SFTP_ATTRIBUTES));
          state(data, SSH_SFTP_QUOTE_STAT);
          break;
        }
        if(strncasecompare(cmd, "ln ", 3) ||
           strncasecompare(cmd, "symlink ", 8)) {
          /* symbolic linking */
          /* sshc->quote_path1 is the source */
          /* get the destination */
          result = Curl_get_pathname(&cp, &sshc->quote_path2, sshc->homedir);
          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(data, SSH_SFTP_CLOSE);
            sshc->nextstate = SSH_NO_STATE;
            sshc->actualcode = result;
            break;
          }
          state(data, SSH_SFTP_QUOTE_SYMLINK);
          break;
        }
        else if(strncasecompare(cmd, "mkdir ", 6)) {
          /* create dir */
          state(data, SSH_SFTP_QUOTE_MKDIR);
          break;
        }
        else if(strncasecompare(cmd, "rename ", 7)) {
          /* rename file */
          /* first param is the source path */
          /* second param is the dest. path */
          result = Curl_get_pathname(&cp, &sshc->quote_path2, sshc->homedir);
          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(data, SSH_SFTP_CLOSE);
            sshc->nextstate = SSH_NO_STATE;
            sshc->actualcode = result;
            break;
          }
          state(data, SSH_SFTP_QUOTE_RENAME);
          break;
        }
        else if(strncasecompare(cmd, "rmdir ", 6)) {
          /* delete dir */
          state(data, SSH_SFTP_QUOTE_RMDIR);
          break;
        }
        else if(strncasecompare(cmd, "rm ", 3)) {
          state(data, SSH_SFTP_QUOTE_UNLINK);
          break;
        }
#ifdef HAS_STATVFS_SUPPORT
        else if(strncasecompare(cmd, "statvfs ", 8)) {
          state(data, SSH_SFTP_QUOTE_STATVFS);
          break;
        }
#endif

        failf(data, "Unknown SFTP command");
        Curl_safefree(sshc->quote_path1);
        Curl_safefree(sshc->quote_path2);
        state(data, SSH_SFTP_CLOSE);
        sshc->nextstate = SSH_NO_STATE;
        sshc->actualcode = CURLE_QUOTE_ERROR;
        break;
      }
    }
    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(data, SSH_SFTP_QUOTE);
      }
      else {
        if(sshc->nextstate != SSH_NO_STATE) {
          state(data, sshc->nextstate);
          sshc->nextstate = SSH_NO_STATE;
        }
        else {
          state(data, SSH_SFTP_GETINFO);
        }
      }
      break;

    case SSH_SFTP_QUOTE_STAT:
    {
      char *cmd = sshc->quote_item->data;
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
        /* 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;
        }
        if(rc != 0 && !sshc->acceptfail) { /* get those attributes */
          sftperr = libssh2_sftp_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(sftperr));
          state(conn, SSH_SFTP_CLOSE);
          sshc->nextstate = SSH_NO_STATE;
          sshc->actualcode = CURLE_QUOTE_ERROR;
          break;
        }
      }

      /* Now set the new attributes... */
      if(strncasecompare(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(strncasecompare(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(strncasecompare(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;
        }
      }
      else if(strncasecompare(cmd, "atime", 5)) {
        time_t date = Curl_getdate_capped(sshc->quote_path1);
        if(date == -1) {
          Curl_safefree(sshc->quote_path1);
          Curl_safefree(sshc->quote_path2);
          failf(data, "Syntax error: incorrect access date format");
          state(conn, SSH_SFTP_CLOSE);
          sshc->nextstate = SSH_NO_STATE;
          sshc->actualcode = CURLE_QUOTE_ERROR;
          break;
        }
        sshc->quote_attrs.atime = (unsigned long)date;
        sshc->quote_attrs.flags = LIBSSH2_SFTP_ATTR_ACMODTIME;
      }
      else if(strncasecompare(cmd, "mtime", 5)) {
        time_t date = Curl_getdate_capped(sshc->quote_path1);
        if(date == -1) {
          Curl_safefree(sshc->quote_path1);
          Curl_safefree(sshc->quote_path2);
          failf(data, "Syntax error: incorrect modification date format");
          state(conn, SSH_SFTP_CLOSE);
          sshc->nextstate = SSH_NO_STATE;
          sshc->actualcode = CURLE_QUOTE_ERROR;
          break;
        }
        sshc->quote_attrs.mtime = (unsigned long)date;
        sshc->quote_attrs.flags = LIBSSH2_SFTP_ATTR_ACMODTIME;
      }

      /* 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;
      }
      if(rc != 0 && !sshc->acceptfail) {
        sftperr = libssh2_sftp_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(sftperr));
        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;
      }
      if(rc != 0 && !sshc->acceptfail) {
        sftperr = libssh2_sftp_last_error(sshc->sftp_session);
        Curl_safefree(sshc->quote_path1);
        Curl_safefree(sshc->quote_path2);
        failf(data, "symlink command failed: %s",
              sftp_libssh2_strerror(sftperr));
        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;
      }
      if(rc != 0 && !sshc->acceptfail) {
        sftperr = libssh2_sftp_last_error(sshc->sftp_session);
        Curl_safefree(sshc->quote_path1);
        failf(data, "mkdir command failed: %s",
              sftp_libssh2_strerror(sftperr));
        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;
      }
      if(rc != 0 && !sshc->acceptfail) {
        sftperr = libssh2_sftp_last_error(sshc->sftp_session);
        Curl_safefree(sshc->quote_path1);
        Curl_safefree(sshc->quote_path2);
        failf(data, "rename command failed: %s",
              sftp_libssh2_strerror(sftperr));
        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;
      }
      if(rc != 0 && !sshc->acceptfail) {
        sftperr = libssh2_sftp_last_error(sshc->sftp_session);
        Curl_safefree(sshc->quote_path1);
        failf(data, "rmdir command failed: %s",
              sftp_libssh2_strerror(sftperr));
        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;
      }
      if(rc != 0 && !sshc->acceptfail) {
        sftperr = libssh2_sftp_last_error(sshc->sftp_session);
        Curl_safefree(sshc->quote_path1);
        failf(data, "rm command failed: %s", sftp_libssh2_strerror(sftperr));
        state(conn, SSH_SFTP_CLOSE);
        sshc->nextstate = SSH_NO_STATE;
        sshc->actualcode = CURLE_QUOTE_ERROR;
        break;
      }
      state(conn, SSH_SFTP_NEXT_QUOTE);
      break;

#ifdef HAS_STATVFS_SUPPORT
    case SSH_SFTP_QUOTE_STATVFS:
    {
      LIBSSH2_SFTP_STATVFS statvfs;
      rc = libssh2_sftp_statvfs(sshc->sftp_session, sshc->quote_path1,
                                curlx_uztoui(strlen(sshc->quote_path1)),
                                &statvfs);

      if(rc == LIBSSH2_ERROR_EAGAIN) {
        break;
      }
      if(rc != 0 && !sshc->acceptfail) {
        sftperr = libssh2_sftp_last_error(sshc->sftp_session);
        Curl_safefree(sshc->quote_path1);
        failf(data, "statvfs command failed: %s",
              sftp_libssh2_strerror(sftperr));
        state(conn, SSH_SFTP_CLOSE);
        sshc->nextstate = SSH_NO_STATE;
        sshc->actualcode = CURLE_QUOTE_ERROR;
        break;
      }
      else if(rc == 0) {
        char *tmp = aprintf("statvfs:\n"
                            "f_bsize: %llu\n" "f_frsize: %llu\n"
                            "f_blocks: %llu\n" "f_bfree: %llu\n"
                            "f_bavail: %llu\n" "f_files: %llu\n"
                            "f_ffree: %llu\n" "f_favail: %llu\n"
                            "f_fsid: %llu\n" "f_flag: %llu\n"
                            "f_namemax: %llu\n",
                            statvfs.f_bsize, statvfs.f_frsize,
                            statvfs.f_blocks, statvfs.f_bfree,
                            statvfs.f_bavail, statvfs.f_files,
                            statvfs.f_ffree, statvfs.f_favail,
                            statvfs.f_fsid, statvfs.f_flag,
                            statvfs.f_namemax);
        if(!tmp) {
          result = CURLE_OUT_OF_MEMORY;
          state(conn, SSH_SFTP_CLOSE);
          sshc->nextstate = SSH_NO_STATE;
          break;
        }

        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;
        }
      }
      state(conn, SSH_SFTP_NEXT_QUOTE);
      break;
    }
#endif
    case SSH_SFTP_GETINFO:
    {
      if(data->set.get_filetime) {
        state(conn, SSH_SFTP_FILETIME);
      }
      else {
        state(conn, SSH_SFTP_TRANS_INIT);
      }
      break;
    }

    case SSH_SFTP_FILETIME:
    {
      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;
      }
      if(rc == 0) {
        data->info.filetime = attrs.mtime;
      }

      state(conn, SSH_SFTP_TRANS_INIT);
      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;
          }
          if(rc) {
            data->state.resume_from = 0;
          }







|









|








|
|
|




|






|
|

|




|






|
|
|




|











|




|
|







|




|
|



|







|









|




|

















|




|














|




|




















|




|













|




|












|




|


















|




















|




|


|




|






|


|








|
|








|





|

|
|

|
















|
|







1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
        /* 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,
                                  &sshp->quote_attrs);
        if(rc == LIBSSH2_ERROR_EAGAIN) {
          break;
        }
        if(rc != 0 && !sshc->acceptfail) { /* get those attributes */
          sftperr = libssh2_sftp_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(sftperr));
          state(data, SSH_SFTP_CLOSE);
          sshc->nextstate = SSH_NO_STATE;
          sshc->actualcode = CURLE_QUOTE_ERROR;
          break;
        }
      }

      /* Now set the new attributes... */
      if(strncasecompare(cmd, "chgrp", 5)) {
        sshp->quote_attrs.gid = strtoul(sshc->quote_path1, NULL, 10);
        sshp->quote_attrs.flags = LIBSSH2_SFTP_ATTR_UIDGID;
        if(sshp->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(data, SSH_SFTP_CLOSE);
          sshc->nextstate = SSH_NO_STATE;
          sshc->actualcode = CURLE_QUOTE_ERROR;
          break;
        }
      }
      else if(strncasecompare(cmd, "chmod", 5)) {
        sshp->quote_attrs.permissions = strtoul(sshc->quote_path1, NULL, 8);
        sshp->quote_attrs.flags = LIBSSH2_SFTP_ATTR_PERMISSIONS;
        /* permissions are octal */
        if(sshp->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(data, SSH_SFTP_CLOSE);
          sshc->nextstate = SSH_NO_STATE;
          sshc->actualcode = CURLE_QUOTE_ERROR;
          break;
        }
      }
      else if(strncasecompare(cmd, "chown", 5)) {
        sshp->quote_attrs.uid = strtoul(sshc->quote_path1, NULL, 10);
        sshp->quote_attrs.flags = LIBSSH2_SFTP_ATTR_UIDGID;
        if(sshp->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(data, SSH_SFTP_CLOSE);
          sshc->nextstate = SSH_NO_STATE;
          sshc->actualcode = CURLE_QUOTE_ERROR;
          break;
        }
      }
      else if(strncasecompare(cmd, "atime", 5)) {
        time_t date = Curl_getdate_capped(sshc->quote_path1);
        if(date == -1) {
          Curl_safefree(sshc->quote_path1);
          Curl_safefree(sshc->quote_path2);
          failf(data, "Syntax error: incorrect access date format");
          state(data, SSH_SFTP_CLOSE);
          sshc->nextstate = SSH_NO_STATE;
          sshc->actualcode = CURLE_QUOTE_ERROR;
          break;
        }
        sshp->quote_attrs.atime = (unsigned long)date;
        sshp->quote_attrs.flags = LIBSSH2_SFTP_ATTR_ACMODTIME;
      }
      else if(strncasecompare(cmd, "mtime", 5)) {
        time_t date = Curl_getdate_capped(sshc->quote_path1);
        if(date == -1) {
          Curl_safefree(sshc->quote_path1);
          Curl_safefree(sshc->quote_path2);
          failf(data, "Syntax error: incorrect modification date format");
          state(data, SSH_SFTP_CLOSE);
          sshc->nextstate = SSH_NO_STATE;
          sshc->actualcode = CURLE_QUOTE_ERROR;
          break;
        }
        sshp->quote_attrs.mtime = (unsigned long)date;
        sshp->quote_attrs.flags = LIBSSH2_SFTP_ATTR_ACMODTIME;
      }

      /* Now send the completed structure... */
      state(data, 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,
                                &sshp->quote_attrs);
      if(rc == LIBSSH2_ERROR_EAGAIN) {
        break;
      }
      if(rc != 0 && !sshc->acceptfail) {
        sftperr = libssh2_sftp_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(sftperr));
        state(data, SSH_SFTP_CLOSE);
        sshc->nextstate = SSH_NO_STATE;
        sshc->actualcode = CURLE_QUOTE_ERROR;
        break;
      }
      state(data, 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;
      }
      if(rc != 0 && !sshc->acceptfail) {
        sftperr = libssh2_sftp_last_error(sshc->sftp_session);
        Curl_safefree(sshc->quote_path1);
        Curl_safefree(sshc->quote_path2);
        failf(data, "symlink command failed: %s",
              sftp_libssh2_strerror(sftperr));
        state(data, SSH_SFTP_CLOSE);
        sshc->nextstate = SSH_NO_STATE;
        sshc->actualcode = CURLE_QUOTE_ERROR;
        break;
      }
      state(data, 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;
      }
      if(rc != 0 && !sshc->acceptfail) {
        sftperr = libssh2_sftp_last_error(sshc->sftp_session);
        Curl_safefree(sshc->quote_path1);
        failf(data, "mkdir command failed: %s",
              sftp_libssh2_strerror(sftperr));
        state(data, SSH_SFTP_CLOSE);
        sshc->nextstate = SSH_NO_STATE;
        sshc->actualcode = CURLE_QUOTE_ERROR;
        break;
      }
      state(data, 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;
      }
      if(rc != 0 && !sshc->acceptfail) {
        sftperr = libssh2_sftp_last_error(sshc->sftp_session);
        Curl_safefree(sshc->quote_path1);
        Curl_safefree(sshc->quote_path2);
        failf(data, "rename command failed: %s",
              sftp_libssh2_strerror(sftperr));
        state(data, SSH_SFTP_CLOSE);
        sshc->nextstate = SSH_NO_STATE;
        sshc->actualcode = CURLE_QUOTE_ERROR;
        break;
      }
      state(data, 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;
      }
      if(rc != 0 && !sshc->acceptfail) {
        sftperr = libssh2_sftp_last_error(sshc->sftp_session);
        Curl_safefree(sshc->quote_path1);
        failf(data, "rmdir command failed: %s",
              sftp_libssh2_strerror(sftperr));
        state(data, SSH_SFTP_CLOSE);
        sshc->nextstate = SSH_NO_STATE;
        sshc->actualcode = CURLE_QUOTE_ERROR;
        break;
      }
      state(data, 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;
      }
      if(rc != 0 && !sshc->acceptfail) {
        sftperr = libssh2_sftp_last_error(sshc->sftp_session);
        Curl_safefree(sshc->quote_path1);
        failf(data, "rm command failed: %s", sftp_libssh2_strerror(sftperr));
        state(data, SSH_SFTP_CLOSE);
        sshc->nextstate = SSH_NO_STATE;
        sshc->actualcode = CURLE_QUOTE_ERROR;
        break;
      }
      state(data, SSH_SFTP_NEXT_QUOTE);
      break;

#ifdef HAS_STATVFS_SUPPORT
    case SSH_SFTP_QUOTE_STATVFS:
    {
      LIBSSH2_SFTP_STATVFS statvfs;
      rc = libssh2_sftp_statvfs(sshc->sftp_session, sshc->quote_path1,
                                curlx_uztoui(strlen(sshc->quote_path1)),
                                &statvfs);

      if(rc == LIBSSH2_ERROR_EAGAIN) {
        break;
      }
      if(rc != 0 && !sshc->acceptfail) {
        sftperr = libssh2_sftp_last_error(sshc->sftp_session);
        Curl_safefree(sshc->quote_path1);
        failf(data, "statvfs command failed: %s",
              sftp_libssh2_strerror(sftperr));
        state(data, SSH_SFTP_CLOSE);
        sshc->nextstate = SSH_NO_STATE;
        sshc->actualcode = CURLE_QUOTE_ERROR;
        break;
      }
      else if(rc == 0) {
        char *tmp = aprintf("statvfs:\n"
                            "f_bsize: %llu\n" "f_frsize: %llu\n"
                            "f_blocks: %llu\n" "f_bfree: %llu\n"
                            "f_bavail: %llu\n" "f_files: %llu\n"
                            "f_ffree: %llu\n" "f_favail: %llu\n"
                            "f_fsid: %llu\n" "f_flag: %llu\n"
                            "f_namemax: %llu\n",
                            statvfs.f_bsize, statvfs.f_frsize,
                            statvfs.f_blocks, statvfs.f_bfree,
                            statvfs.f_bavail, statvfs.f_files,
                            statvfs.f_ffree, statvfs.f_favail,
                            statvfs.f_fsid, statvfs.f_flag,
                            statvfs.f_namemax);
        if(!tmp) {
          result = CURLE_OUT_OF_MEMORY;
          state(data, SSH_SFTP_CLOSE);
          sshc->nextstate = SSH_NO_STATE;
          break;
        }

        result = Curl_client_write(data, CLIENTWRITE_HEADER, tmp, strlen(tmp));
        free(tmp);
        if(result) {
          state(data, SSH_SFTP_CLOSE);
          sshc->nextstate = SSH_NO_STATE;
          sshc->actualcode = result;
        }
      }
      state(data, SSH_SFTP_NEXT_QUOTE);
      break;
    }
#endif
    case SSH_SFTP_GETINFO:
    {
      if(data->set.get_filetime) {
        state(data, SSH_SFTP_FILETIME);
      }
      else {
        state(data, SSH_SFTP_TRANS_INIT);
      }
      break;
    }

    case SSH_SFTP_FILETIME:
    {
      LIBSSH2_SFTP_ATTRIBUTES attrs;

      rc = libssh2_sftp_stat_ex(sshc->sftp_session, sshp->path,
                                curlx_uztoui(strlen(sshp->path)),
                                LIBSSH2_SFTP_STAT, &attrs);
      if(rc == LIBSSH2_ERROR_EAGAIN) {
        break;
      }
      if(rc == 0) {
        data->info.filetime = attrs.mtime;
      }

      state(data, SSH_SFTP_TRANS_INIT);
      break;
    }

    case SSH_SFTP_TRANS_INIT:
      if(data->set.upload)
        state(data, SSH_SFTP_UPLOAD_INIT);
      else {
        if(sshp->path[strlen(sshp->path)-1] == '/')
          state(data, SSH_SFTP_READDIR_INIT);
        else
          state(data, 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, sshp->path,
                                    curlx_uztoui(strlen(sshp->path)),
                                    LIBSSH2_SFTP_STAT, &attrs);
          if(rc == LIBSSH2_ERROR_EAGAIN) {
            break;
          }
          if(rc) {
            data->state.resume_from = 0;
          }
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
      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;

        if(LIBSSH2_ERROR_SFTP_PROTOCOL == rc)
          /* only when there was an SFTP protocol error can we extract
             the sftp error! */
          sftperr = libssh2_sftp_last_error(sshc->sftp_session);
        else
          sftperr = LIBSSH2_FX_OK; /* not an sftp error at all */

        if(sshc->secondCreateDirs) {
          state(conn, SSH_SFTP_CLOSE);
          sshc->actualcode = sftperr != LIBSSH2_FX_OK ?
            sftp_libssh2_error_to_CURLE(sftperr):CURLE_SSH;
          failf(data, "Creating the dir/file failed: %s",
                sftp_libssh2_strerror(sftperr));
          break;
        }
        if(((sftperr == LIBSSH2_FX_NO_SUCH_FILE) ||
            (sftperr == LIBSSH2_FX_FAILURE) ||
            (sftperr == LIBSSH2_FX_NO_SUCH_PATH)) &&
           (data->set.ftp_create_missing_dirs &&
            (strlen(sftp_scp->path) > 1))) {
          /* try to create the path remotely */
          rc = 0; /* clear rc and continue */
          sshc->secondCreateDirs = 1;
          state(conn, SSH_SFTP_CREATE_DIRS_INIT);
          break;
        }
        state(conn, SSH_SFTP_CLOSE);
        sshc->actualcode = sftperr != LIBSSH2_FX_OK ?
          sftp_libssh2_error_to_CURLE(sftperr):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;







|



|
|

















|










|



|


|







1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
      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 behavior) */
        flags = LIBSSH2_FXF_WRITE|LIBSSH2_FXF_CREAT|LIBSSH2_FXF_TRUNC;

      sshc->sftp_handle =
        libssh2_sftp_open_ex(sshc->sftp_session, sshp->path,
                             curlx_uztoui(strlen(sshp->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;

        if(LIBSSH2_ERROR_SFTP_PROTOCOL == rc)
          /* only when there was an SFTP protocol error can we extract
             the sftp error! */
          sftperr = libssh2_sftp_last_error(sshc->sftp_session);
        else
          sftperr = LIBSSH2_FX_OK; /* not an sftp error at all */

        if(sshc->secondCreateDirs) {
          state(data, SSH_SFTP_CLOSE);
          sshc->actualcode = sftperr != LIBSSH2_FX_OK ?
            sftp_libssh2_error_to_CURLE(sftperr):CURLE_SSH;
          failf(data, "Creating the dir/file failed: %s",
                sftp_libssh2_strerror(sftperr));
          break;
        }
        if(((sftperr == LIBSSH2_FX_NO_SUCH_FILE) ||
            (sftperr == LIBSSH2_FX_FAILURE) ||
            (sftperr == LIBSSH2_FX_NO_SUCH_PATH)) &&
           (data->set.ftp_create_missing_dirs &&
            (strlen(sshp->path) > 1))) {
          /* try to create the path remotely */
          rc = 0; /* clear rc and continue */
          sshc->secondCreateDirs = 1;
          state(data, SSH_SFTP_CREATE_DIRS_INIT);
          break;
        }
        state(data, SSH_SFTP_CLOSE);
        sshc->actualcode = sftperr != LIBSSH2_FX_OK ?
          sftp_libssh2_error_to_CURLE(sftperr):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;
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
      /* upload data */
      Curl_setup_transfer(data, -1, -1, FALSE, FIRSTSOCKET);

      /* 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, 0, EXPIRE_RUN_NOW);

        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;
      }
      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 < 0) {
        /*
         * 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
         */
        sftperr = libssh2_sftp_last_error(sshc->sftp_session);
        if((sftperr != LIBSSH2_FX_FILE_ALREADY_EXISTS) &&
           (sftperr != LIBSSH2_FX_FAILURE) &&
           (sftperr != LIBSSH2_FX_PERMISSION_DENIED)) {
          result = sftp_libssh2_error_to_CURLE(sftperr);
          state(conn, SSH_SFTP_CLOSE);
          sshc->actualcode = result?result:CURLE_SSH;
          break;
        }
        rc = 0; /* clear rc and continue */
      }
      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;
        }
        sftperr = libssh2_sftp_last_error(sshc->sftp_session);
        failf(data, "Could not open directory for reading: %s",
              sftp_libssh2_strerror(sftperr));
        state(conn, SSH_SFTP_CLOSE);
        result = sftp_libssh2_error_to_CURLE(sftperr);
        sshc->actualcode = result?result:CURLE_SSH;
        break;
      }
      sshc->readdir_filename = malloc(PATH_MAX + 1);
      if(!sshc->readdir_filename) {
        state(conn, SSH_SFTP_CLOSE);
        sshc->actualcode = CURLE_OUT_OF_MEMORY;
        break;
      }
      sshc->readdir_longentry = malloc(PATH_MAX + 1);
      if(!sshc->readdir_longentry) {
        Curl_safefree(sshc->readdir_filename);
        state(conn, SSH_SFTP_CLOSE);
        sshc->actualcode = CURLE_OUT_OF_MEMORY;
        break;
      }
      Curl_dyn_init(&sshc->readdir, PATH_MAX * 2);
      state(conn, SSH_SFTP_READDIR);
      break;

    case SSH_SFTP_READDIR:
      rc = libssh2_sftp_readdir_ex(sshc->sftp_handle,
                                   sshc->readdir_filename,
                                   PATH_MAX,
                                   sshc->readdir_longentry,
                                   PATH_MAX,
                                   &sshc->readdir_attrs);
      if(rc == LIBSSH2_ERROR_EAGAIN) {
        break;
      }
      if(rc > 0) {
        readdir_len = (size_t) rc;
        sshc->readdir_filename[readdir_len] = '\0';

        if(data->set.ftp_list_only) {
          result = Curl_client_write(conn, CLIENTWRITE_BODY,
                                     sshc->readdir_filename,
                                     readdir_len);
          if(!result)
            result = Curl_client_write(conn, CLIENTWRITE_BODY,
                                       (char *)"\n", 1);
          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 += readdir_len + 1;

          /* output debug output if that is requested */
          Curl_debug(data, CURLINFO_DATA_IN, sshc->readdir_filename,
                     readdir_len);
          Curl_debug(data, CURLINFO_DATA_IN, (char *)"\n", 1);
        }
        else {
          result = Curl_dyn_add(&sshc->readdir, sshc->readdir_longentry);

          if(!result) {
            if((sshc->readdir_attrs.flags & LIBSSH2_SFTP_ATTR_PERMISSIONS) &&
               ((sshc->readdir_attrs.permissions & LIBSSH2_SFTP_S_IFMT) ==
                LIBSSH2_SFTP_S_IFLNK)) {
              Curl_dyn_init(&sshc->readdir_link, PATH_MAX);
              result = Curl_dyn_add(&sshc->readdir_link, sftp_scp->path);
              state(conn, SSH_SFTP_READDIR_LINK);
              if(!result)
                break;
            }
            else {
              state(conn, SSH_SFTP_READDIR_BOTTOM);
              break;
            }
          }
          sshc->actualcode = result;
          state(conn, SSH_SFTP_CLOSE);
          break;
        }
      }
      else if(rc == 0) {
        Curl_safefree(sshc->readdir_filename);
        Curl_safefree(sshc->readdir_longentry);
        state(conn, SSH_SFTP_READDIR_DONE);
        break;
      }
      else if(rc < 0) {
        sftperr = libssh2_sftp_last_error(sshc->sftp_session);
        result = sftp_libssh2_error_to_CURLE(sftperr);
        sshc->actualcode = result?result:CURLE_SSH;
        failf(data, "Could not open remote file for reading: %s :: %d",
              sftp_libssh2_strerror(sftperr),
              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:
      rc =
        libssh2_sftp_symlink_ex(sshc->sftp_session,
                                Curl_dyn_ptr(&sshc->readdir_link),
                                (int)Curl_dyn_len(&sshc->readdir_link),
                                sshc->readdir_filename,
                                PATH_MAX, LIBSSH2_SFTP_READLINK);
      if(rc == LIBSSH2_ERROR_EAGAIN) {
        break;
      }
      readdir_len = (size_t) rc;
      Curl_dyn_free(&sshc->readdir_link);

      /* append filename and extra output */
      result = Curl_dyn_addf(&sshc->readdir, " -> %s", sshc->readdir_filename);

      if(result) {
        sshc->readdir_line = NULL;
        Curl_safefree(sshc->readdir_filename);
        Curl_safefree(sshc->readdir_longentry);
        state(conn, SSH_SFTP_CLOSE);
        sshc->actualcode = result;
        break;
      }

      state(conn, SSH_SFTP_READDIR_BOTTOM);
      break;

    case SSH_SFTP_READDIR_BOTTOM:
      result = Curl_dyn_addn(&sshc->readdir, "\n", 1);
      if(!result)
        result = Curl_client_write(conn, CLIENTWRITE_BODY,
                                   Curl_dyn_ptr(&sshc->readdir),
                                   Curl_dyn_len(&sshc->readdir));

      if(!result) {
        /* output debug output if that is requested */
        Curl_debug(data, CURLINFO_DATA_IN,
                   Curl_dyn_ptr(&sshc->readdir),
                   Curl_dyn_len(&sshc->readdir));
        data->req.bytecount += Curl_dyn_len(&sshc->readdir);
      }
      if(result) {
        Curl_dyn_free(&sshc->readdir);
        state(conn, SSH_STOP);
      }
      else {
        Curl_dyn_reset(&sshc->readdir);
        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(data, -1, -1, FALSE, -1);
      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;
        }
        sftperr = libssh2_sftp_last_error(sshc->sftp_session);
        failf(data, "Could not open remote file for reading: %s",
              sftp_libssh2_strerror(sftperr));
        state(conn, SSH_SFTP_CLOSE);
        result = sftp_libssh2_error_to_CURLE(sftperr);
        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;
      }
      if(rc ||
         !(attrs.flags & LIBSSH2_SFTP_ATTR_SIZE) ||
         (attrs.filesize == 0)) {







|

















|





|
|
|


|








|
|


|




|
|

















|





|





|








|

|










|




|
|
|



|
|
|
|



|
|




|

|

|





|


|
|


|


|







|




|


|
|

|
|
|




|




|




|
|
|









|
|
|







|
|
|




<
|


|



|
|
|




|



|

|
|
|




|
|
|


|
|


|
|










|
|



|







|
|











|




|






|
|







2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218

2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
      /* upload data */
      Curl_setup_transfer(data, -1, -1, FALSE, FIRSTSOCKET);

      /* not set by Curl_setup_transfer to preserve keepon bits */
      conn->sockfd = conn->writesockfd;

      if(result) {
        state(data, 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, 0, EXPIRE_RUN_NOW);

        state(data, SSH_STOP);
      }
      break;
    }

    case SSH_SFTP_CREATE_DIRS_INIT:
      if(strlen(sshp->path) > 1) {
        sshc->slash_pos = sshp->path + 1; /* ignore the leading '/' */
        state(data, SSH_SFTP_CREATE_DIRS);
      }
      else {
        state(data, 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", sshp->path);
        state(data, SSH_SFTP_CREATE_DIRS_MKDIR);
        break;
      }
      state(data, 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, sshp->path,
                                 curlx_uztoui(strlen(sshp->path)),
                                 data->set.new_directory_perms);
      if(rc == LIBSSH2_ERROR_EAGAIN) {
        break;
      }
      *sshc->slash_pos = '/';
      ++sshc->slash_pos;
      if(rc < 0) {
        /*
         * 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
         */
        sftperr = libssh2_sftp_last_error(sshc->sftp_session);
        if((sftperr != LIBSSH2_FX_FILE_ALREADY_EXISTS) &&
           (sftperr != LIBSSH2_FX_FAILURE) &&
           (sftperr != LIBSSH2_FX_PERMISSION_DENIED)) {
          result = sftp_libssh2_error_to_CURLE(sftperr);
          state(data, SSH_SFTP_CLOSE);
          sshc->actualcode = result?result:CURLE_SSH;
          break;
        }
        rc = 0; /* clear rc and continue */
      }
      state(data, SSH_SFTP_CREATE_DIRS);
      break;

    case SSH_SFTP_READDIR_INIT:
      Curl_pgrsSetDownloadSize(data, -1);
      if(data->set.opt_no_body) {
        state(data, 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,
                                               sshp->path,
                                               curlx_uztoui(
                                                 strlen(sshp->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;
        }
        sftperr = libssh2_sftp_last_error(sshc->sftp_session);
        failf(data, "Could not open directory for reading: %s",
              sftp_libssh2_strerror(sftperr));
        state(data, SSH_SFTP_CLOSE);
        result = sftp_libssh2_error_to_CURLE(sftperr);
        sshc->actualcode = result?result:CURLE_SSH;
        break;
      }
      sshp->readdir_filename = malloc(PATH_MAX + 1);
      if(!sshp->readdir_filename) {
        state(data, SSH_SFTP_CLOSE);
        sshc->actualcode = CURLE_OUT_OF_MEMORY;
        break;
      }
      sshp->readdir_longentry = malloc(PATH_MAX + 1);
      if(!sshp->readdir_longentry) {
        Curl_safefree(sshp->readdir_filename);
        state(data, SSH_SFTP_CLOSE);
        sshc->actualcode = CURLE_OUT_OF_MEMORY;
        break;
      }
      Curl_dyn_init(&sshp->readdir, PATH_MAX * 2);
      state(data, SSH_SFTP_READDIR);
      break;

    case SSH_SFTP_READDIR:
      rc = libssh2_sftp_readdir_ex(sshc->sftp_handle,
                                   sshp->readdir_filename,
                                   PATH_MAX,
                                   sshp->readdir_longentry,
                                   PATH_MAX,
                                   &sshp->readdir_attrs);
      if(rc == LIBSSH2_ERROR_EAGAIN) {
        break;
      }
      if(rc > 0) {
        readdir_len = (size_t) rc;
        sshp->readdir_filename[readdir_len] = '\0';

        if(data->set.ftp_list_only) {
          result = Curl_client_write(data, CLIENTWRITE_BODY,
                                     sshp->readdir_filename,
                                     readdir_len);
          if(!result)
            result = Curl_client_write(data, CLIENTWRITE_BODY,
                                       (char *)"\n", 1);
          if(result) {
            state(data, SSH_STOP);
            break;
          }
          /* since this counts what we send to the client, we include the
             newline in this counter */
          data->req.bytecount += readdir_len + 1;

          /* output debug output if that is requested */
          Curl_debug(data, CURLINFO_DATA_IN, sshp->readdir_filename,
                     readdir_len);
          Curl_debug(data, CURLINFO_DATA_IN, (char *)"\n", 1);
        }
        else {
          result = Curl_dyn_add(&sshp->readdir, sshp->readdir_longentry);

          if(!result) {
            if((sshp->readdir_attrs.flags & LIBSSH2_SFTP_ATTR_PERMISSIONS) &&
               ((sshp->readdir_attrs.permissions & LIBSSH2_SFTP_S_IFMT) ==
                LIBSSH2_SFTP_S_IFLNK)) {
              Curl_dyn_init(&sshp->readdir_link, PATH_MAX);
              result = Curl_dyn_add(&sshp->readdir_link, sshp->path);
              state(data, SSH_SFTP_READDIR_LINK);
              if(!result)
                break;
            }
            else {
              state(data, SSH_SFTP_READDIR_BOTTOM);
              break;
            }
          }
          sshc->actualcode = result;
          state(data, SSH_SFTP_CLOSE);
          break;
        }
      }
      else if(rc == 0) {
        Curl_safefree(sshp->readdir_filename);
        Curl_safefree(sshp->readdir_longentry);
        state(data, SSH_SFTP_READDIR_DONE);
        break;
      }
      else if(rc < 0) {
        sftperr = libssh2_sftp_last_error(sshc->sftp_session);
        result = sftp_libssh2_error_to_CURLE(sftperr);
        sshc->actualcode = result?result:CURLE_SSH;
        failf(data, "Could not open remote file for reading: %s :: %d",
              sftp_libssh2_strerror(sftperr),
              libssh2_session_last_errno(sshc->ssh_session));
        Curl_safefree(sshp->readdir_filename);
        Curl_safefree(sshp->readdir_longentry);
        state(data, SSH_SFTP_CLOSE);
        break;
      }
      break;

    case SSH_SFTP_READDIR_LINK:
      rc =
        libssh2_sftp_symlink_ex(sshc->sftp_session,
                                Curl_dyn_ptr(&sshp->readdir_link),
                                (int)Curl_dyn_len(&sshp->readdir_link),
                                sshp->readdir_filename,
                                PATH_MAX, LIBSSH2_SFTP_READLINK);
      if(rc == LIBSSH2_ERROR_EAGAIN) {
        break;
      }

      Curl_dyn_free(&sshp->readdir_link);

      /* append filename and extra output */
      result = Curl_dyn_addf(&sshp->readdir, " -> %s", sshp->readdir_filename);

      if(result) {
        sshc->readdir_line = NULL;
        Curl_safefree(sshp->readdir_filename);
        Curl_safefree(sshp->readdir_longentry);
        state(data, SSH_SFTP_CLOSE);
        sshc->actualcode = result;
        break;
      }

      state(data, SSH_SFTP_READDIR_BOTTOM);
      break;

    case SSH_SFTP_READDIR_BOTTOM:
      result = Curl_dyn_addn(&sshp->readdir, "\n", 1);
      if(!result)
        result = Curl_client_write(data, CLIENTWRITE_BODY,
                                   Curl_dyn_ptr(&sshp->readdir),
                                   Curl_dyn_len(&sshp->readdir));

      if(!result) {
        /* output debug output if that is requested */
        Curl_debug(data, CURLINFO_DATA_IN,
                   Curl_dyn_ptr(&sshp->readdir),
                   Curl_dyn_len(&sshp->readdir));
        data->req.bytecount += Curl_dyn_len(&sshp->readdir);
      }
      if(result) {
        Curl_dyn_free(&sshp->readdir);
        state(data, SSH_STOP);
      }
      else {
        Curl_dyn_reset(&sshp->readdir);
        state(data, 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(sshp->readdir_filename);
      Curl_safefree(sshp->readdir_longentry);

      /* no data to transfer */
      Curl_setup_transfer(data, -1, -1, FALSE, -1);
      state(data, SSH_STOP);
      break;

    case SSH_SFTP_DOWNLOAD_INIT:
      /*
       * Work on getting the specified file
       */
      sshc->sftp_handle =
        libssh2_sftp_open_ex(sshc->sftp_session, sshp->path,
                             curlx_uztoui(strlen(sshp->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;
        }
        sftperr = libssh2_sftp_last_error(sshc->sftp_session);
        failf(data, "Could not open remote file for reading: %s",
              sftp_libssh2_strerror(sftperr));
        state(data, SSH_SFTP_CLOSE);
        result = sftp_libssh2_error_to_CURLE(sftperr);
        sshc->actualcode = result?result:CURLE_SSH;
        break;
      }
      state(data, SSH_SFTP_DOWNLOAD_STAT);
      break;

    case SSH_SFTP_DOWNLOAD_STAT:
    {
      LIBSSH2_SFTP_ATTRIBUTES attrs;

      rc = libssh2_sftp_stat_ex(sshc->sftp_session, sshp->path,
                                curlx_uztoui(strlen(sshp->path)),
                                LIBSSH2_SFTP_STAT, &attrs);
      if(rc == LIBSSH2_ERROR_EAGAIN) {
        break;
      }
      if(rc ||
         !(attrs.flags & LIBSSH2_SFTP_ATTR_SIZE) ||
         (attrs.filesize == 0)) {
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351
2352
2353
      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;
          CURLofft to_t;
          CURLofft from_t;

          from_t = curlx_strtoofft(conn->data->state.range, &ptr, 0, &from);
          if(from_t == CURL_OFFT_FLOW)
            return CURLE_RANGE_ERROR;
          while(*ptr && (ISSPACE(*ptr) || (*ptr == '-')))
            ptr++;
          to_t = curlx_strtoofft(ptr, &ptr2, 0, &to);
          if(to_t == CURL_OFFT_FLOW)
            return CURLE_RANGE_ERROR;







|






|







2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
      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(data->state.use_range) {
          curl_off_t from, to;
          char *ptr;
          char *ptr2;
          CURLofft to_t;
          CURLofft from_t;

          from_t = curlx_strtoofft(data->state.range, &ptr, 0, &from);
          if(from_t == CURL_OFFT_FLOW)
            return CURLE_RANGE_ERROR;
          while(*ptr && (ISSPACE(*ptr) || (*ptr == '-')))
            ptr++;
          to_t = curlx_strtoofft(ptr, &ptr2, 0, &to);
          if(to_t == CURL_OFFT_FLOW)
            return CURLE_RANGE_ERROR;
2370
2371
2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
2384
            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 */







|







2362
2363
2364
2365
2366
2367
2368
2369
2370
2371
2372
2373
2374
2375
2376
            from = to;
            size = 0;
          }
          else {
            size = to - from + 1;
          }

          SFTP_SEEK(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 */
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
2450
2451
2452
2453
2454
2455
2456
2457
2458
2459
2460
2461
2462
2463
2464
2465
2466
2467
2468
2469
2470
2471
2472
2473
2474
2475
2476
2477
2478
2479
    }

    /* Setup the actual download */
    if(data->req.size == 0) {
      /* no data to transfer */
      Curl_setup_transfer(data, -1, -1, FALSE, -1);
      infof(data, "File already completely downloaded\n");
      state(conn, SSH_STOP);
      break;
    }
    Curl_setup_transfer(data, FIRSTSOCKET, data->req.size, FALSE, -1);

    /* 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;
        }
        if(rc < 0) {
          char *err_msg = NULL;
          (void)libssh2_session_last_error(sshc->ssh_session,
                                           &err_msg, NULL, 0);
          infof(data, "Failed to close libssh2 file: %d %s\n", rc, err_msg);
        }
        sshc->sftp_handle = NULL;
      }

      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







|















|



|


















|








|



|







2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
2450
2451
2452
2453
2454
2455
2456
2457
2458
2459
2460
2461
2462
2463
2464
2465
2466
2467
2468
2469
2470
2471
    }

    /* Setup the actual download */
    if(data->req.size == 0) {
      /* no data to transfer */
      Curl_setup_transfer(data, -1, -1, FALSE, -1);
      infof(data, "File already completely downloaded\n");
      state(data, SSH_STOP);
      break;
    }
    Curl_setup_transfer(data, FIRSTSOCKET, data->req.size, FALSE, -1);

    /* 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(data, SSH_SFTP_CLOSE);
      sshc->actualcode = result;
    }
    else {
      state(data, SSH_STOP);
    }
    break;

    case SSH_SFTP_CLOSE:
      if(sshc->sftp_handle) {
        rc = libssh2_sftp_close(sshc->sftp_handle);
        if(rc == LIBSSH2_ERROR_EAGAIN) {
          break;
        }
        if(rc < 0) {
          char *err_msg = NULL;
          (void)libssh2_session_last_error(sshc->ssh_session,
                                           &err_msg, NULL, 0);
          infof(data, "Failed to close libssh2 file: %d %s\n", rc, err_msg);
        }
        sshc->sftp_handle = NULL;
      }

      Curl_safefree(sshp->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(data, sshc->nextstate);
        sshc->nextstate = SSH_SFTP_CLOSE;
      }
      else {
        state(data, 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
2500
2501
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
2539
2540
2541
2542
2543
2544
2545
2546
2547
2548
2549
2550
2551
2552
2553
2554
2555
2556
2557
2558
2559
2560
2561
2562
2563
2564
2565
2566
2567
2568
2569
2570
2571
2572
2573
2574
2575
2576
2577
2578
2579
2580
2581
2582
2583
2584
2585
2586
2587
2588
2589
2590
2591
2592
2593
2594
2595
        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 = Curl_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) {
        int ssh_err;
        char *err_msg = NULL;

        if(libssh2_session_last_errno(sshc->ssh_session) ==
           LIBSSH2_ERROR_EAGAIN) {
          rc = LIBSSH2_ERROR_EAGAIN;
          break;
        }

        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);
        /* Map generic errors to upload failed */
        if(sshc->actualcode == CURLE_SSH ||
           sshc->actualcode == CURLE_REMOTE_FILE_NOT_FOUND)
          sshc->actualcode = CURLE_UPLOAD_FAILED;
        break;
      }

      /* upload data */
      data->req.size = data->state.infilesize;
      Curl_pgrsSetUploadSize(data, data->state.infilesize);
      Curl_setup_transfer(data, -1, -1, FALSE, FIRSTSOCKET);

      /* 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:
    {
      curl_off_t bytecount;








|

|



|


|







|


|


|











|













|
|

















|












|







2492
2493
2494
2495
2496
2497
2498
2499
2500
2501
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
2539
2540
2541
2542
2543
2544
2545
2546
2547
2548
2549
2550
2551
2552
2553
2554
2555
2556
2557
2558
2559
2560
2561
2562
2563
2564
2565
2566
2567
2568
2569
2570
2571
2572
2573
2574
2575
2576
2577
2578
2579
2580
2581
2582
2583
2584
2585
2586
2587
        if(rc < 0) {
          infof(data, "Failed to stop libssh2 sftp subsystem\n");
        }
        sshc->sftp_session = NULL;
      }

      Curl_safefree(sshc->homedir);
      data->state.most_recent_ftp_entrypath = NULL;

      state(data, SSH_SESSION_DISCONNECT);
      break;

    case SSH_SCP_TRANS_INIT:
      result = Curl_getworkingpath(data, sshc->homedir, &sshp->path);
      if(result) {
        sshc->actualcode = result;
        state(data, 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(data, SSH_SCP_CHANNEL_FREE);
          break;
        }
        state(data, SSH_SCP_UPLOAD_INIT);
      }
      else {
        state(data, 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, sshp->path, data->set.new_file_perms,
                 data->state.infilesize);
      if(!sshc->ssh_channel) {
        int ssh_err;
        char *err_msg = NULL;

        if(libssh2_session_last_errno(sshc->ssh_session) ==
           LIBSSH2_ERROR_EAGAIN) {
          rc = LIBSSH2_ERROR_EAGAIN;
          break;
        }

        ssh_err = (int)(libssh2_session_last_error(sshc->ssh_session,
                                                   &err_msg, NULL, 0));
        failf(data, "%s", err_msg);
        state(data, SSH_SCP_CHANNEL_FREE);
        sshc->actualcode = libssh2_session_error_to_CURLE(ssh_err);
        /* Map generic errors to upload failed */
        if(sshc->actualcode == CURLE_SSH ||
           sshc->actualcode == CURLE_REMOTE_FILE_NOT_FOUND)
          sshc->actualcode = CURLE_UPLOAD_FAILED;
        break;
      }

      /* upload data */
      data->req.size = data->state.infilesize;
      Curl_pgrsSetUploadSize(data, data->state.infilesize);
      Curl_setup_transfer(data, -1, -1, FALSE, FIRSTSOCKET);

      /* not set by Curl_setup_transfer to preserve keepon bits */
      conn->sockfd = conn->writesockfd;

      if(result) {
        state(data, 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(data, SSH_STOP);
      }
      break;

    case SSH_SCP_DOWNLOAD_INIT:
    {
      curl_off_t bytecount;

2603
2604
2605
2606
2607
2608
2609
2610
2611
2612
2613
2614
2615
2616
2617
2618
2619
2620
2621
2622
2623
2624
2625
2626
2627
2628
2629
2630
2631
2632
2633
2634
2635
2636
2637
2638
2639
2640
2641
2642
2643
2644
2645
2646
2647
2648
2649
2650
2651
2652
2653
2654
2655
2656
2657
2658
2659
2660
2661
2662
2663
2664
2665
2666
2667
2668
2669
2670
2671
2672
2673
2674
2675
2676
2677
2678
2679
2680
2681
2682
2683
2684
2685
2686
2687
2688
2689
2690
2691
2692
2693
2694
2695
2696
2697
2698
2699
2700
2701
2702
2703
2704
2705
2706
2707
2708
2709
2710
2711
2712
2713
2714
2715
2716
2717
2718
2719
2720
2721
2722
2723
2724
2725
2726
2727
2728
2729
2730
2731
2732
2733
2734
2735
2736
2737
2738
2739
2740
2741
       */

      /* get a fresh new channel from the ssh layer */
#if LIBSSH2_VERSION_NUM < 0x010700
      struct stat sb;
      memset(&sb, 0, sizeof(struct stat));
      sshc->ssh_channel = libssh2_scp_recv(sshc->ssh_session,
                                           sftp_scp->path, &sb);
#else
      libssh2_struct_stat sb;
      memset(&sb, 0, sizeof(libssh2_struct_stat));
      sshc->ssh_channel = libssh2_scp_recv2(sshc->ssh_session,
                                            sftp_scp->path, &sb);
#endif

      if(!sshc->ssh_channel) {
        int ssh_err;
        char *err_msg = NULL;

        if(libssh2_session_last_errno(sshc->ssh_session) ==
           LIBSSH2_ERROR_EAGAIN) {
          rc = LIBSSH2_ERROR_EAGAIN;
          break;
        }


        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(data, FIRSTSOCKET, bytecount, FALSE, -1);

      /* 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;
        }
        if(rc) {
          char *err_msg = NULL;
          (void)libssh2_session_last_error(sshc->ssh_session,
                                           &err_msg, NULL, 0);
          infof(data, "Failed to send libssh2 channel EOF: %d %s\n",
                rc, err_msg);
        }
      }
      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;
        }
        if(rc) {
          char *err_msg = NULL;
          (void)libssh2_session_last_error(sshc->ssh_session,
                                           &err_msg, NULL, 0);
          infof(data, "Failed to get channel EOF: %d %s\n", rc, err_msg);
        }
      }
      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;
        }
        if(rc) {
          char *err_msg = NULL;
          (void)libssh2_session_last_error(sshc->ssh_session,
                                           &err_msg, NULL, 0);
          infof(data, "Channel failed to close: %d %s\n", rc, err_msg);
        }
      }
      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;
        }
        if(rc < 0) {
          char *err_msg = NULL;
          (void)libssh2_session_last_error(sshc->ssh_session,
                                           &err_msg, NULL, 0);
          infof(data, "Failed to free libssh2 scp subsystem: %d %s\n",
                rc, err_msg);
        }
        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 */







|




|















|
|


















|



|





|

|
















|















|















|



















|

|







2595
2596
2597
2598
2599
2600
2601
2602
2603
2604
2605
2606
2607
2608
2609
2610
2611
2612
2613
2614
2615
2616
2617
2618
2619
2620
2621
2622
2623
2624
2625
2626
2627
2628
2629
2630
2631
2632
2633
2634
2635
2636
2637
2638
2639
2640
2641
2642
2643
2644
2645
2646
2647
2648
2649
2650
2651
2652
2653
2654
2655
2656
2657
2658
2659
2660
2661
2662
2663
2664
2665
2666
2667
2668
2669
2670
2671
2672
2673
2674
2675
2676
2677
2678
2679
2680
2681
2682
2683
2684
2685
2686
2687
2688
2689
2690
2691
2692
2693
2694
2695
2696
2697
2698
2699
2700
2701
2702
2703
2704
2705
2706
2707
2708
2709
2710
2711
2712
2713
2714
2715
2716
2717
2718
2719
2720
2721
2722
2723
2724
2725
2726
2727
2728
2729
2730
2731
2732
2733
       */

      /* get a fresh new channel from the ssh layer */
#if LIBSSH2_VERSION_NUM < 0x010700
      struct stat sb;
      memset(&sb, 0, sizeof(struct stat));
      sshc->ssh_channel = libssh2_scp_recv(sshc->ssh_session,
                                           sshp->path, &sb);
#else
      libssh2_struct_stat sb;
      memset(&sb, 0, sizeof(libssh2_struct_stat));
      sshc->ssh_channel = libssh2_scp_recv2(sshc->ssh_session,
                                            sshp->path, &sb);
#endif

      if(!sshc->ssh_channel) {
        int ssh_err;
        char *err_msg = NULL;

        if(libssh2_session_last_errno(sshc->ssh_session) ==
           LIBSSH2_ERROR_EAGAIN) {
          rc = LIBSSH2_ERROR_EAGAIN;
          break;
        }


        ssh_err = (int)(libssh2_session_last_error(sshc->ssh_session,
                                                   &err_msg, NULL, 0));
        failf(data, "%s", err_msg);
        state(data, 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(data, FIRSTSOCKET, bytecount, FALSE, -1);

      /* 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(data, SSH_SCP_CHANNEL_FREE);
        sshc->actualcode = result;
      }
      else
        state(data, SSH_STOP);
    }
    break;

    case SSH_SCP_DONE:
      if(data->set.upload)
        state(data, SSH_SCP_SEND_EOF);
      else
        state(data, 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;
        }
        if(rc) {
          char *err_msg = NULL;
          (void)libssh2_session_last_error(sshc->ssh_session,
                                           &err_msg, NULL, 0);
          infof(data, "Failed to send libssh2 channel EOF: %d %s\n",
                rc, err_msg);
        }
      }
      state(data, 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;
        }
        if(rc) {
          char *err_msg = NULL;
          (void)libssh2_session_last_error(sshc->ssh_session,
                                           &err_msg, NULL, 0);
          infof(data, "Failed to get channel EOF: %d %s\n", rc, err_msg);
        }
      }
      state(data, 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;
        }
        if(rc) {
          char *err_msg = NULL;
          (void)libssh2_session_last_error(sshc->ssh_session,
                                           &err_msg, NULL, 0);
          infof(data, "Channel failed to close: %d %s\n", rc, err_msg);
        }
      }
      state(data, 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;
        }
        if(rc < 0) {
          char *err_msg = NULL;
          (void)libssh2_session_last_error(sshc->ssh_session,
                                           &err_msg, NULL, 0);
          infof(data, "Failed to free libssh2 scp subsystem: %d %s\n",
                rc, err_msg);
        }
        sshc->ssh_channel = NULL;
      }
      DEBUGF(infof(data, "SCP DONE phase complete\n"));
#if 0 /* PREV */
      state(data, SSH_SESSION_DISCONNECT);
#endif
      state(data, 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 */
2765
2766
2767
2768
2769
2770
2771
2772
2773
2774
2775
2776
2777
2778
2779
2780
2781
                                           &err_msg, NULL, 0);
          infof(data, "Failed to disconnect libssh2 session: %d %s\n",
                rc, err_msg);
        }
      }

      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;







|

|







2757
2758
2759
2760
2761
2762
2763
2764
2765
2766
2767
2768
2769
2770
2771
2772
2773
                                           &err_msg, NULL, 0);
          infof(data, "Failed to disconnect libssh2 session: %d %s\n",
                rc, err_msg);
        }
      }

      Curl_safefree(sshc->homedir);
      data->state.most_recent_ftp_entrypath = NULL;

      state(data, SSH_SESSION_FREE);
      break;

    case SSH_SESSION_FREE:
#ifdef HAVE_LIBSSH2_KNOWNHOST_API
      if(sshc->kh) {
        libssh2_knownhost_free(sshc->kh);
        sshc->kh = NULL;
2835
2836
2837
2838
2839
2840
2841
2842
2843
2844
2845
2846
2847
2848
2849
2850
2851
2852
2853
2854
2855
2856
2857
2858
2859
2860
2861
2862
2863
2864
2865
2866
2867
2868
2869
2870
2871
2872
2873
2874
2875
2876
2877
2878
2879
2880

2881
2882
2883
2884

2885
2886
2887
2888
2889
2890
2891
2892
2893
2894
2895
2896
2897
2898
2899
2900
2901
2902
2903
2904
2905
2906
2907
2908
2909
2910
2911
2912
2913
2914
2915

2916
2917
2918
2919
2920
2921
2922
2923
2924
2925
2926
2927
2928
2929
2930
2931
2932
2933
2934

2935
2936
2937
2938
2939
2940
2941
2942
2943
2944
2945
2946
2947
2948
2949
2950

2951
2952
2953
2954
2955
2956
2957
2958
2959
2960
2961
2962
2963
2964
2965
2966
2967
2968
2969
2970
2971
2972
2973
      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_dyn_free(&sshc->readdir);

      /* 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)
{
  int bitmap = GETSOCK_BLANK;


  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;
}

/* 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)
{
  /* 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);
}

/*
 * 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 = 0;
  if(block) {
    dir = libssh2_session_block_directions(sshc->ssh_session);
    if(dir) {
      /* 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);
    }
  }
  if(!dir)
    /* It didn't block or libssh2 didn't reveal in which direction, put back
       the original set */
    conn->waitfor = sshc->orig_waitfor;
}

/* 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 */
  do {
    result = ssh_statemach_act(conn, &block);
    *done = (sshc->state == SSH_STOP) ? TRUE : FALSE;
    /* if there's no error, it isn't done and it didn't EWOULDBLOCK, then
       try again */
  } while(!result && !*done && !block);
  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 Curl_easy *data = conn->data;

  while((sshc->state != SSH_STOP) && !result) {
    bool block;
    timediff_t left = 1000;
    struct curltime now = Curl_now();

    result = ssh_statemach_act(conn, &block);
    if(result)
      break;

    if(Curl_pgrsUpdate(conn))
      return CURLE_ABORTED_BY_CALLBACK;

    result = Curl_speedcheck(data, now);
    if(result)
      break;

    left = Curl_timeleft(data, NULL, duringconnect);







<
<
<

<









|







|
















>
|
|


>












<
<
<
<
<
<
<
<
<
<







|

>

















|

>





|




|




|
>
|



<






|



|







2827
2828
2829
2830
2831
2832
2833



2834

2835
2836
2837
2838
2839
2840
2841
2842
2843
2844
2845
2846
2847
2848
2849
2850
2851
2852
2853
2854
2855
2856
2857
2858
2859
2860
2861
2862
2863
2864
2865
2866
2867
2868
2869
2870
2871
2872
2873
2874
2875
2876
2877
2878
2879
2880
2881
2882
2883
2884
2885
2886










2887
2888
2889
2890
2891
2892
2893
2894
2895
2896
2897
2898
2899
2900
2901
2902
2903
2904
2905
2906
2907
2908
2909
2910
2911
2912
2913
2914
2915
2916
2917
2918
2919
2920
2921
2922
2923
2924
2925
2926
2927
2928
2929
2930
2931
2932
2933
2934
2935
2936
2937

2938
2939
2940
2941
2942
2943
2944
2945
2946
2947
2948
2949
2950
2951
2952
2953
2954
2955
      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_line);


      /* 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(data, SSH_STOP);
      break;

    case SSH_QUIT:
      /* fallthrough, just stop! */
    default:
      /* internal error */
      sshc->nextstate = SSH_NO_STATE;
      state(data, 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_getsock(struct Curl_easy *data,
                       struct connectdata *conn,
                       curl_socket_t *sock)
{
  int bitmap = GETSOCK_BLANK;
  (void)data;

  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;
}











/*
 * 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 Curl_easy *data, bool block)
{
  struct connectdata *conn = data->conn;
  struct ssh_conn *sshc = &conn->proto.sshc;
  int dir = 0;
  if(block) {
    dir = libssh2_session_block_directions(sshc->ssh_session);
    if(dir) {
      /* 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);
    }
  }
  if(!dir)
    /* It didn't block or libssh2 didn't reveal in which direction, put back
       the original set */
    conn->waitfor = sshc->orig_waitfor;
}

/* called repeatedly until done from multi.c */
static CURLcode ssh_multi_statemach(struct Curl_easy *data, bool *done)
{
  struct connectdata *conn = data->conn;
  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 */
  do {
    result = ssh_statemach_act(data, &block);
    *done = (sshc->state == SSH_STOP) ? TRUE : FALSE;
    /* if there's no error, it isn't done and it didn't EWOULDBLOCK, then
       try again */
  } while(!result && !*done && !block);
  ssh_block2waitfor(data, block);

  return result;
}

static CURLcode ssh_block_statemach(struct Curl_easy *data,
                                    struct connectdata *conn,
                                    bool duringconnect)
{
  struct ssh_conn *sshc = &conn->proto.sshc;
  CURLcode result = CURLE_OK;


  while((sshc->state != SSH_STOP) && !result) {
    bool block;
    timediff_t left = 1000;
    struct curltime now = Curl_now();

    result = ssh_statemach_act(data, &block);
    if(result)
      break;

    if(Curl_pgrsUpdate(data))
      return CURLE_ABORTED_BY_CALLBACK;

    result = Curl_speedcheck(data, now);
    if(result)
      break;

    left = Curl_timeleft(data, NULL, duringconnect);
2993
2994
2995
2996
2997
2998
2999
3000

3001
3002

3003
3004
3005
3006
3007
3008
3009
3010
3011
3012
3013
3014
3015
3016
3017
3018
3019
3020

3021
3022
3023
3024
3025
3026
3027
3028
3029
3030
3031
3032
3033
3034
3035
3036
3037
3038
3039
3040
3041
3042
3043

3044
3045
3046
3047
3048
3049
3050
3051
3052
3053
3054
3055
3056
3057
3058
3059
3060
3061
3062
3063
3064
3065
3066
3067
3068
3069
3070

3071
3072
3073
3074
3075
3076
3077




3078
3079
3080
3081
3082
3083
3084
3085
3086
3087
3088
3089
3090
3091
3092
3093
3094
3095
3096
3097
3098
3099
3100
3101
3102
3103
3104
3105

  return result;
}

/*
 * SSH setup and connection
 */
static CURLcode ssh_setup_connection(struct connectdata *conn)

{
  struct SSHPROTO *ssh;


  conn->data->req.p.ssh = 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;

#ifndef CURL_DISABLE_PROXY
static ssize_t ssh_tls_recv(libssh2_socket_t sock, void *buffer,
                            size_t length, int flags, void **abstract)
{
  struct connectdata *conn = (struct connectdata *)*abstract;
  ssize_t nread;
  CURLcode result;

  Curl_recv *backup = conn->recv[0];
  struct ssh_conn *ssh = &conn->proto.sshc;
  (void)flags;

  /* swap in the TLS reader function for this call only, and then swap back
     the SSH one again */
  conn->recv[0] = ssh->tls_recv;
  result = Curl_read(conn, sock, buffer, length, &nread);
  conn->recv[0] = backup;
  if(result == CURLE_AGAIN)
    return -EAGAIN; /* magic return code for libssh2 */
  else if(result)
    return -1; /* generic error */
  Curl_debug(conn->data, CURLINFO_DATA_IN, (char *)buffer, (size_t)nread);
  return nread;
}

static ssize_t ssh_tls_send(libssh2_socket_t sock, const void *buffer,
                            size_t length, int flags, void **abstract)
{
  struct connectdata *conn = (struct connectdata *)*abstract;
  ssize_t nwrite;
  CURLcode result;

  Curl_send *backup = conn->send[0];
  struct ssh_conn *ssh = &conn->proto.sshc;
  (void)flags;

  /* swap in the TLS writer function for this call only, and then swap back
     the SSH one again */
  conn->send[0] = ssh->tls_send;
  result = Curl_write(conn, sock, buffer, length, &nwrite);
  conn->send[0] = backup;
  if(result == CURLE_AGAIN)
    return -EAGAIN; /* magic return code for libssh2 */
  else if(result)
    return -1; /* error */
  Curl_debug(conn->data, CURLINFO_DATA_OUT, (char *)buffer, (size_t)nwrite);
  return nwrite;
}
#endif

/*
 * 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 Curl_easy *data = conn->data;

  /* initialize per-handle data if not already */
  if(!data->req.p.ssh)
    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");

  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;
  }

#ifndef CURL_DISABLE_PROXY
  if(conn->http_proxy.proxytype == CURLPROXY_HTTPS) {
    /*







|
>


>

|













|


>







|





|






|


>







|





|








|




>
|

|


|
|
>
>
>
>





|











|
|
|
|







2975
2976
2977
2978
2979
2980
2981
2982
2983
2984
2985
2986
2987
2988
2989
2990
2991
2992
2993
2994
2995
2996
2997
2998
2999
3000
3001
3002
3003
3004
3005
3006
3007
3008
3009
3010
3011
3012
3013
3014
3015
3016
3017
3018
3019
3020
3021
3022
3023
3024
3025
3026
3027
3028
3029
3030
3031
3032
3033
3034
3035
3036
3037
3038
3039
3040
3041
3042
3043
3044
3045
3046
3047
3048
3049
3050
3051
3052
3053
3054
3055
3056
3057
3058
3059
3060
3061
3062
3063
3064
3065
3066
3067
3068
3069
3070
3071
3072
3073
3074
3075
3076
3077
3078
3079
3080
3081
3082
3083
3084
3085
3086
3087
3088
3089
3090
3091
3092
3093
3094
3095
3096

  return result;
}

/*
 * SSH setup and connection
 */
static CURLcode ssh_setup_connection(struct Curl_easy *data,
                                     struct connectdata *conn)
{
  struct SSHPROTO *ssh;
  (void)conn;

  data->req.p.ssh = 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;

#ifndef CURL_DISABLE_PROXY
static ssize_t ssh_tls_recv(libssh2_socket_t sock, void *buffer,
                            size_t length, int flags, void **abstract)
{
  struct Curl_easy *data = (struct Curl_easy *)*abstract;
  ssize_t nread;
  CURLcode result;
  struct connectdata *conn = data->conn;
  Curl_recv *backup = conn->recv[0];
  struct ssh_conn *ssh = &conn->proto.sshc;
  (void)flags;

  /* swap in the TLS reader function for this call only, and then swap back
     the SSH one again */
  conn->recv[0] = ssh->tls_recv;
  result = Curl_read(data, sock, buffer, length, &nread);
  conn->recv[0] = backup;
  if(result == CURLE_AGAIN)
    return -EAGAIN; /* magic return code for libssh2 */
  else if(result)
    return -1; /* generic error */
  Curl_debug(data, CURLINFO_DATA_IN, (char *)buffer, (size_t)nread);
  return nread;
}

static ssize_t ssh_tls_send(libssh2_socket_t sock, const void *buffer,
                            size_t length, int flags, void **abstract)
{
  struct Curl_easy *data = (struct Curl_easy *)*abstract;
  ssize_t nwrite;
  CURLcode result;
  struct connectdata *conn = data->conn;
  Curl_send *backup = conn->send[0];
  struct ssh_conn *ssh = &conn->proto.sshc;
  (void)flags;

  /* swap in the TLS writer function for this call only, and then swap back
     the SSH one again */
  conn->send[0] = ssh->tls_send;
  result = Curl_write(data, sock, buffer, length, &nwrite);
  conn->send[0] = backup;
  if(result == CURLE_AGAIN)
    return -EAGAIN; /* magic return code for libssh2 */
  else if(result)
    return -1; /* error */
  Curl_debug(data, CURLINFO_DATA_OUT, (char *)buffer, (size_t)nwrite);
  return nwrite;
}
#endif

/*
 * 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 Curl_easy *data, bool *done)
{
#ifdef CURL_LIBSSH2_DEBUG
  curl_socket_t sock;
#endif
  struct SSHPROTO *sshp = data->req.p.ssh;
  struct ssh_conn *sshc;
  CURLcode result;
  struct connectdata *conn = data->conn;

  /* initialize per-handle data if not already */
  if(!sshp) {
    result = ssh_setup_connection(data, conn);
    if(result)
      return result;
    sshp = data->req.p.ssh;
  }

  /* 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");

  sshc = &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 */

  sshc->ssh_session = libssh2_session_init_ex(my_libssh2_malloc,
                                              my_libssh2_free,
                                              my_libssh2_realloc, data);
  if(sshc->ssh_session == NULL) {
    failf(data, "Failure initialising ssh session");
    return CURLE_FAILED_INIT;
  }

#ifndef CURL_DISABLE_PROXY
  if(conn->http_proxy.proxytype == CURLPROXY_HTTPS) {
    /*
3130
3131
3132
3133
3134
3135
3136
3137
3138
3139
3140
3141
3142
3143
3144
3145
3146
3147
3148
3149
3150
3151
3152
3153
3154
3155
3156
3157
3158
3159
3160
3161
3162
3163
3164
3165
3166
3167
3168
3169
3170
3171
3172
3173
3174
3175
3176
3177
3178
3179
3180
3181
3182
3183
3184
3185
3186
3187
3188
3189
3190
3191
3192
3193
3194
3195
3196
3197
3198
3199
3200
3201
3202
3203
3204
3205
3206
3207
3208
3209
3210

3211
3212
3213
3214
3215
3216
3217
3218
3219
3220
3221
3222
3223
3224
3225
3226
3227
3228
3229
3230
3231
3232
3233
3234
3235
3236
3237
3238
3239
3240
3241
3242
3243
3244
3245
3246
3247
3248
3249
3250
3251
3252
3253
3254
3255
3256
3257
3258
3259
3260
3261
3262
3263
3264
3265
3266
3267
3268
3269
3270
3271
3272
3273
3274
3275
3276
3277
3278
3279
3280


3281
3282
3283
3284
3285
3286
3287
3288
3289
3290
3291
3292
3293
3294
3295
3296
3297
3298
3299
3300
3301
3302

3303
3304
3305
3306
3307
3308
3309
3310
3311
3312




3313
3314
3315
3316
3317
3318
3319
3320
3321
3322
3323
3324
3325
3326
3327
3328
3329
3330
3331
3332
3333
3334
3335
3336


3337
3338
3339
3340
3341
3342
3343
3344
3345
3346
3347
3348
3349
3350
3351
3352
3353
3354
3355
3356
3357
3358
3359
3360


3361
3362
3363
3364
3365
3366
3367
3368
3369
3370
3371
3372
3373
3374
      int flags, void **abstract);

      ssize_t
      sendcb(libssh2_socket_t sock, const void *buffer, size_t length,
      int flags, void **abstract);

    */
    libssh2_session_callback_set(ssh->ssh_session,
                                 LIBSSH2_CALLBACK_RECV, sshrecv.recvp);
    libssh2_session_callback_set(ssh->ssh_session,
                                 LIBSSH2_CALLBACK_SEND, sshsend.sendp);

    /* Store the underlying TLS recv/send function pointers to be used when
       reading from the proxy */
    ssh->tls_recv = conn->recv[FIRSTSOCKET];
    ssh->tls_send = conn->send[FIRSTSOCKET];
  }

#endif /* CURL_DISABLE_PROXY */
  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;
  }

  if(data->set.ssh_compression) {
#if LIBSSH2_VERSION_NUM >= 0x010208
    if(libssh2_session_flag(ssh->ssh_session, LIBSSH2_FLAG_COMPRESS, 1) < 0)
#endif
      infof(data, "Failed to enable compression for ssh session\n");
  }

#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) {
      libssh2_session_free(ssh->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 Curl_easy *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;

  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.p.ssh;


  if(!status) {
    /* run the state-machine */
    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);

}

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;
}

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;
}







|

|




|
|














|







|
|
|




|









|



|

|














|
|
|


>

|




|


|




|






|
|


|


|









|



|
















|

|







|
>
>


|


|


|

|







|


|
>



|




<
|
>
>
>
>
|


|




|





|

|



|



>
>



|
<

|













|



>
>



|
<

|







3121
3122
3123
3124
3125
3126
3127
3128
3129
3130
3131
3132
3133
3134
3135
3136
3137
3138
3139
3140
3141
3142
3143
3144
3145
3146
3147
3148
3149
3150
3151
3152
3153
3154
3155
3156
3157
3158
3159
3160
3161
3162
3163
3164
3165
3166
3167
3168
3169
3170
3171
3172
3173
3174
3175
3176
3177
3178
3179
3180
3181
3182
3183
3184
3185
3186
3187
3188
3189
3190
3191
3192
3193
3194
3195
3196
3197
3198
3199
3200
3201
3202
3203
3204
3205
3206
3207
3208
3209
3210
3211
3212
3213
3214
3215
3216
3217
3218
3219
3220
3221
3222
3223
3224
3225
3226
3227
3228
3229
3230
3231
3232
3233
3234
3235
3236
3237
3238
3239
3240
3241
3242
3243
3244
3245
3246
3247
3248
3249
3250
3251
3252
3253
3254
3255
3256
3257
3258
3259
3260
3261
3262
3263
3264
3265
3266
3267
3268
3269
3270
3271
3272
3273
3274
3275
3276
3277
3278
3279
3280
3281
3282
3283
3284
3285
3286
3287
3288
3289
3290
3291
3292
3293
3294
3295
3296
3297
3298
3299
3300
3301
3302
3303
3304
3305

3306
3307
3308
3309
3310
3311
3312
3313
3314
3315
3316
3317
3318
3319
3320
3321
3322
3323
3324
3325
3326
3327
3328
3329
3330
3331
3332
3333
3334
3335
3336
3337
3338
3339
3340

3341
3342
3343
3344
3345
3346
3347
3348
3349
3350
3351
3352
3353
3354
3355
3356
3357
3358
3359
3360
3361
3362
3363
3364
3365

3366
3367
3368
3369
3370
3371
3372
3373
3374
      int flags, void **abstract);

      ssize_t
      sendcb(libssh2_socket_t sock, const void *buffer, size_t length,
      int flags, void **abstract);

    */
    libssh2_session_callback_set(sshc->ssh_session,
                                 LIBSSH2_CALLBACK_RECV, sshrecv.recvp);
    libssh2_session_callback_set(sshc->ssh_session,
                                 LIBSSH2_CALLBACK_SEND, sshsend.sendp);

    /* Store the underlying TLS recv/send function pointers to be used when
       reading from the proxy */
    sshc->tls_recv = conn->recv[FIRSTSOCKET];
    sshc->tls_send = conn->send[FIRSTSOCKET];
  }

#endif /* CURL_DISABLE_PROXY */
  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;
  }

  if(data->set.ssh_compression) {
#if LIBSSH2_VERSION_NUM >= 0x010208
    if(libssh2_session_flag(sshc->ssh_session, LIBSSH2_FLAG_COMPRESS, 1) < 0)
#endif
      infof(data, "Failed to enable compression for ssh session\n");
  }

#ifdef HAVE_LIBSSH2_KNOWNHOST_API
  if(data->set.str[STRING_SSH_KNOWNHOSTS]) {
    int rc;
    sshc->kh = libssh2_knownhost_init(sshc->ssh_session);
    if(!sshc->kh) {
      libssh2_session_free(sshc->ssh_session);
      return CURLE_FAILED_INIT;
    }

    /* read all known hosts from there */
    rc = libssh2_knownhost_readfile(sshc->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(sshc->ssh_session, ~0);
  infof(data, "SSH socket: %d\n", (int)sock);
#endif /* CURL_LIBSSH2_DEBUG */

  state(data, SSH_INIT);

  result = ssh_multi_statemach(data, 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 Curl_easy *data,
                     bool *connected,
                     bool *dophase_done)
{
  CURLcode result = CURLE_OK;
  struct connectdata *conn = data->conn;

  DEBUGF(infof(data, "DO phase starts\n"));

  *dophase_done = FALSE; /* not done yet */

  /* start the first command in the DO phase */
  state(data, SSH_SCP_TRANS_INIT);

  /* run the state-machine */
  result = ssh_multi_statemach(data, dophase_done);

  *connected = conn->bits.tcpconnect[FIRSTSOCKET];

  if(*dophase_done) {
    DEBUGF(infof(data, "DO phase is complete\n"));
  }

  return result;
}

/* called from multi.c while DOing */
static CURLcode scp_doing(struct Curl_easy *data,
                          bool *dophase_done)
{
  CURLcode result;
  result = ssh_multi_statemach(data, dophase_done);

  if(*dophase_done) {
    DEBUGF(infof(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 Curl_easy *data, bool *done)
{
  CURLcode result;
  bool connected = 0;
  struct connectdata *conn = data->conn;
  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(data, &connected,  done);
  else
    result = sftp_perform(data, &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 Curl_easy *data,
                               struct connectdata *conn,
                               bool dead_connection)
{
  CURLcode result = CURLE_OK;
  struct ssh_conn *sshc = &conn->proto.sshc;
  (void) dead_connection;

  if(sshc->ssh_session) {
    /* only if there's a session still around to use! */

    state(data, SSH_SESSION_DISCONNECT);

    result = ssh_block_statemach(data, conn, FALSE);
  }

  return result;
}

/* generic done function for both SCP and SFTP called from their specific
   done functions */
static CURLcode ssh_done(struct Curl_easy *data, CURLcode status)
{
  CURLcode result = CURLE_OK;
  struct SSHPROTO *sshp = data->req.p.ssh;
  struct connectdata *conn = data->conn;

  if(!status) {
    /* run the state-machine */
    result = ssh_block_statemach(data, conn, FALSE);
  }
  else
    result = status;


  Curl_safefree(sshp->path);
  Curl_safefree(sshp->readdir_filename);
  Curl_safefree(sshp->readdir_longentry);
  Curl_dyn_free(&sshp->readdir);

  if(Curl_pgrsDone(data))
    return CURLE_ABORTED_BY_CALLBACK;

  data->req.keepon = 0; /* clear all bits */
  return result;
}


static CURLcode scp_done(struct Curl_easy *data, CURLcode status,
                         bool premature)
{
  (void)premature; /* not used */

  if(!status)
    state(data, SSH_SCP_DONE);

  return ssh_done(data, status);

}

static ssize_t scp_send(struct Curl_easy *data, int sockindex,
                        const void *mem, size_t len, CURLcode *err)
{
  ssize_t nwrite;
  struct connectdata *conn = data->conn;
  struct ssh_conn *sshc = &conn->proto.sshc;
  (void)sockindex; /* we only support SCP on the fixed known primary socket */

  /* libssh2_channel_write() returns int! */
  nwrite = (ssize_t) libssh2_channel_write(sshc->ssh_channel, mem, len);


  ssh_block2waitfor(data, (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;
}

static ssize_t scp_recv(struct Curl_easy *data, int sockindex,
                        char *mem, size_t len, CURLcode *err)
{
  ssize_t nread;
  struct connectdata *conn = data->conn;
  struct ssh_conn *sshc = &conn->proto.sshc;
  (void)sockindex; /* we only support SCP on the fixed known primary socket */

  /* libssh2_channel_read() returns int */
  nread = (ssize_t) libssh2_channel_read(sshc->ssh_channel, mem, len);


  ssh_block2waitfor(data, (nread == LIBSSH2_ERROR_EAGAIN)?TRUE:FALSE);
  if(nread == LIBSSH2_ERROR_EAGAIN) {
    *err = CURLE_AGAIN;
    nread = -1;
  }

  return nread;
}
3383
3384
3385
3386
3387
3388
3389
3390
3391
3392
3393
3394
3395
3396
3397
3398
3399
3400
3401
3402
3403
3404
3405
3406
3407
3408
3409
3410
3411
3412
3413
3414
3415
3416
3417
3418
3419
3420
3421
3422
3423
3424
3425
3426
3427
3428
3429
3430

3431
3432

3433
3434
3435
3436
3437
3438
3439
3440
3441
3442
3443
3444
3445
3446
3447
3448
3449
3450
3451

3452
3453
3454
3455
3456
3457
3458
3459
3460
3461
3462
3463
3464
3465
3466
3467
3468
3469
3470
3471
3472
3473
3474
3475
3476
3477
3478
3479
3480
3481
3482
3483
3484
3485
3486
3487
3488
3489
3490
3491
3492
3493
3494
3495
3496
3497


3498
3499
3500
3501
3502
3503
3504
3505
3506
3507
3508
3509
 * 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"));

  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(!premature && conn->data->set.postquote && !conn->bits.retry)
      sshc->nextstate = SSH_SFTP_POSTQUOTE_INIT;
    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) {







|





|




|


|

|


|






|


|


|







|
>


>


|

|

|
|


|





|


>






|

|

|



|


|
|
|


|

|

















|



>
>


|

|







3383
3384
3385
3386
3387
3388
3389
3390
3391
3392
3393
3394
3395
3396
3397
3398
3399
3400
3401
3402
3403
3404
3405
3406
3407
3408
3409
3410
3411
3412
3413
3414
3415
3416
3417
3418
3419
3420
3421
3422
3423
3424
3425
3426
3427
3428
3429
3430
3431
3432
3433
3434
3435
3436
3437
3438
3439
3440
3441
3442
3443
3444
3445
3446
3447
3448
3449
3450
3451
3452
3453
3454
3455
3456
3457
3458
3459
3460
3461
3462
3463
3464
3465
3466
3467
3468
3469
3470
3471
3472
3473
3474
3475
3476
3477
3478
3479
3480
3481
3482
3483
3484
3485
3486
3487
3488
3489
3490
3491
3492
3493
3494
3495
3496
3497
3498
3499
3500
3501
3502
3503
3504
3505
3506
3507
3508
3509
3510
3511
3512
3513
3514
 * 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 Curl_easy *data,
                      bool *connected,
                      bool *dophase_done)
{
  CURLcode result = CURLE_OK;

  DEBUGF(infof(data, "DO phase starts\n"));

  *dophase_done = FALSE; /* not done yet */

  /* start the first command in the DO phase */
  state(data, SSH_SFTP_QUOTE_INIT);

  /* run the state-machine */
  result = ssh_multi_statemach(data, dophase_done);

  *connected = data->conn->bits.tcpconnect[FIRSTSOCKET];

  if(*dophase_done) {
    DEBUGF(infof(data, "DO phase is complete\n"));
  }

  return result;
}

/* called from multi.c while DOing */
static CURLcode sftp_doing(struct Curl_easy *data,
                           bool *dophase_done)
{
  CURLcode result = ssh_multi_statemach(data, dophase_done);

  if(*dophase_done) {
    DEBUGF(infof(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 Curl_easy *data,
                                struct connectdata *conn, bool dead_connection)
{
  CURLcode result = CURLE_OK;
  struct ssh_conn *sshc = &conn->proto.sshc;
  (void) dead_connection;

  DEBUGF(infof(data, "SSH DISCONNECT starts now\n"));

  if(sshc->ssh_session) {
    /* only if there's a session still around to use! */
    state(data, SSH_SFTP_SHUTDOWN);
    result = ssh_block_statemach(data, conn, FALSE);
  }

  DEBUGF(infof(data, "SSH DISCONNECT is done\n"));

  return result;

}

static CURLcode sftp_done(struct Curl_easy *data, CURLcode status,
                               bool premature)
{
  struct connectdata *conn = data->conn;
  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(!premature && data->set.postquote && !conn->bits.retry)
      sshc->nextstate = SSH_SFTP_POSTQUOTE_INIT;
    state(data, SSH_SFTP_CLOSE);
  }
  return ssh_done(data, status);
}

/* return number of sent bytes */
static ssize_t sftp_send(struct Curl_easy *data, int sockindex,
                         const void *mem, size_t len, CURLcode *err)
{
  ssize_t nwrite;
  struct connectdata *conn = data->conn;
  struct ssh_conn *sshc = &conn->proto.sshc;
  (void)sockindex;

  nwrite = libssh2_sftp_write(sshc->sftp_handle, mem, len);

  ssh_block2waitfor(data, (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 Curl_easy *data, int sockindex,
                         char *mem, size_t len, CURLcode *err)
{
  ssize_t nread;
  struct connectdata *conn = data->conn;
  struct ssh_conn *sshc = &conn->proto.sshc;
  (void)sockindex;

  nread = libssh2_sftp_read(sshc->sftp_handle, mem, len);

  ssh_block2waitfor(data, (nread == LIBSSH2_ERROR_EAGAIN)?TRUE:FALSE);

  if(nread == LIBSSH2_ERROR_EAGAIN) {
    *err = CURLE_AGAIN;
    nread = -1;

  }
  else if(nread < 0) {
Changes to jni/curl/lib/vssh/ssh.h.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#ifndef HEADER_CURL_SSH_H
#define HEADER_CURL_SSH_H
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2020, 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 https://curl.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









|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#ifndef HEADER_CURL_SSH_H
#define HEADER_CURL_SSH_H
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2021, 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 https://curl.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
107
108
109
110
111
112
113











114
115
116
117
118
119
120
121
122
123
124
125


126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145

146
147
148
149
150
151
152

/* this struct is used in the HandleData struct which is part of the
   Curl_easy, 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 */

  /* common */
  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;

  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 */
  char *readdir_line;
  /* 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 */

  int orig_waitfor;             /* default READ/WRITE bits wait for */


#if defined(USE_LIBSSH)
  char *readdir_linkPath;
  size_t readdir_len, readdir_totalLen, readdir_currLen;
/* our variables */
  unsigned kbd_state; /* 0 or 1 */
  ssh_key privkey;







>
>
>
>
>
>
>
>
>
>
>












>
>







<
<








<
<

>







107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145


146
147
148
149
150
151
152
153


154
155
156
157
158
159
160
161
162

/* this struct is used in the HandleData struct which is part of the
   Curl_easy, 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 */
#ifdef USE_LIBSSH2
  struct dynbuf readdir_link;
  struct dynbuf readdir;
  char *readdir_filename;
  char *readdir_longentry;

  LIBSSH2_SFTP_ATTRIBUTES quote_attrs; /* used by the SFTP_QUOTE state */

  /* Here's a set of struct members used by the SFTP_READDIR state */
  LIBSSH2_SFTP_ATTRIBUTES readdir_attrs;
#endif
};

/* 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 */

  /* common */
  const char *passphrase;     /* pass-phrase to use */
  char *rsa_pub;              /* path name */
  char *rsa;                  /* path name */
  bool authed;                /* the connection has been authenticated fine */
  bool acceptfail;            /* used by the SFTP_QUOTE (continue if
                                 quote command fails) */
  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;



  char *homedir;              /* when doing SFTP we figure out home dir in the
                                 connect phase */
  char *readdir_line;
  /* 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 */


  int orig_waitfor;             /* default READ/WRITE bits wait for */
  char *slash_pos;              /* used by the SFTP_CREATE_DIRS state */

#if defined(USE_LIBSSH)
  char *readdir_linkPath;
  size_t readdir_len, readdir_totalLen, readdir_currLen;
/* our variables */
  unsigned kbd_state; /* 0 or 1 */
  ssh_key privkey;
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
  sftp_attributes readdir_link_attrs; /* used by the SFTP readdir actions */
  sftp_attributes quote_attrs; /* used by the SFTP_QUOTE state */

  const char *readdir_filename; /* points within readdir_attrs */
  const char *readdir_longentry;
  char *readdir_tmp;
#elif defined(USE_LIBSSH2)
  struct dynbuf readdir_link;
  struct dynbuf readdir;
  char *readdir_filename;
  char *readdir_longentry;

  LIBSSH2_SFTP_ATTRIBUTES quote_attrs; /* used by the SFTP_QUOTE state */

  /* Here's a set of struct members used by the SFTP_READDIR state */
  LIBSSH2_SFTP_ATTRIBUTES readdir_attrs;
  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;

#ifndef CURL_DISABLE_PROXY
  /* for HTTPS proxy storage */







<
<
<
<
<
<
<
<
<







174
175
176
177
178
179
180









181
182
183
184
185
186
187
  sftp_attributes readdir_link_attrs; /* used by the SFTP readdir actions */
  sftp_attributes quote_attrs; /* used by the SFTP_QUOTE state */

  const char *readdir_filename; /* points within readdir_attrs */
  const char *readdir_longentry;
  char *readdir_tmp;
#elif defined(USE_LIBSSH2)









  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;

#ifndef CURL_DISABLE_PROXY
  /* for HTTPS proxy storage */
Changes to jni/curl/lib/vssh/wolfssh.c.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 2019 - 2020, 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 https://curl.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







|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 2019 - 2021, 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 https://curl.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
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56

57
58
59
60
61
62
63


64
65
66
67
68

69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
#include "warnless.h"

/* The last 3 #include files should be in this order */
#include "curl_printf.h"
#include "curl_memory.h"
#include "memdebug.h"

static CURLcode wssh_connect(struct connectdata *conn, bool *done);
static CURLcode wssh_multi_statemach(struct connectdata *conn, bool *done);
static CURLcode wssh_do(struct connectdata *conn, bool *done);
#if 0
static CURLcode wscp_done(struct connectdata *conn,
                          CURLcode, bool premature);
static CURLcode wscp_doing(struct connectdata *conn,
                           bool *dophase_done);
static CURLcode wscp_disconnect(struct connectdata *conn,

                                bool dead_connection);
#endif
static CURLcode wsftp_done(struct connectdata *conn,
                           CURLcode, bool premature);
static CURLcode wsftp_doing(struct connectdata *conn,
                            bool *dophase_done);
static CURLcode wsftp_disconnect(struct connectdata *conn, bool dead);


static int wssh_getsock(struct connectdata *conn,
                        curl_socket_t *sock);
static int wssh_perform_getsock(const struct connectdata *conn,
                                curl_socket_t *sock);
static CURLcode wssh_setup_connection(struct connectdata *conn);


#if 0
/*
 * SCP protocol handler.
 */

const struct Curl_handler Curl_handler_scp = {
  "SCP",                                /* scheme */
  wssh_setup_connection,                /* setup_connection */
  wssh_do,                              /* do_it */
  wscp_done,                            /* done */
  ZERO_NULL,                            /* do_more */
  wssh_connect,                         /* connect_it */
  wssh_multi_statemach,                 /* connecting */
  wscp_doing,                           /* doing */
  wssh_getsock,                         /* proto_getsock */
  wssh_getsock,                         /* doing_getsock */
  ZERO_NULL,                            /* domore_getsock */
  wssh_perform_getsock,                 /* perform_getsock */
  wscp_disconnect,                      /* disconnect */
  ZERO_NULL,                            /* readwrite */
  ZERO_NULL,                            /* connection_check */
  PORT_SSH,                             /* defport */
  CURLPROTO_SCP,                        /* protocol */
  PROTOPT_DIRLOCK | PROTOPT_CLOSEACTION
  | PROTOPT_NOURLQUERY                  /* flags */







|
|
|

|

|

|
>


|

|

|
>
>
|
<
|
|
|
>


















|







41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67

68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
#include "warnless.h"

/* The last 3 #include files should be in this order */
#include "curl_printf.h"
#include "curl_memory.h"
#include "memdebug.h"

static CURLcode wssh_connect(struct Curl_easy *data, bool *done);
static CURLcode wssh_multi_statemach(struct Curl_easy *data, bool *done);
static CURLcode wssh_do(struct Curl_easy *data, bool *done);
#if 0
static CURLcode wscp_done(struct Curl_easy *data,
                          CURLcode, bool premature);
static CURLcode wscp_doing(struct Curl_easy *data,
                           bool *dophase_done);
static CURLcode wscp_disconnect(struct Curl_easy *data,
                                struct connectdata *conn,
                                bool dead_connection);
#endif
static CURLcode wsftp_done(struct Curl_easy *data,
                           CURLcode, bool premature);
static CURLcode wsftp_doing(struct Curl_easy *data,
                            bool *dophase_done);
static CURLcode wsftp_disconnect(struct Curl_easy *data,
                                 struct connectdata *conn,
                                 bool dead);
static int wssh_getsock(struct Curl_easy *data,

                        struct connectdata *conn,
                        curl_socket_t *sock);
static CURLcode wssh_setup_connection(struct Curl_easy *data,
                                      struct connectdata *conn);

#if 0
/*
 * SCP protocol handler.
 */

const struct Curl_handler Curl_handler_scp = {
  "SCP",                                /* scheme */
  wssh_setup_connection,                /* setup_connection */
  wssh_do,                              /* do_it */
  wscp_done,                            /* done */
  ZERO_NULL,                            /* do_more */
  wssh_connect,                         /* connect_it */
  wssh_multi_statemach,                 /* connecting */
  wscp_doing,                           /* doing */
  wssh_getsock,                         /* proto_getsock */
  wssh_getsock,                         /* doing_getsock */
  ZERO_NULL,                            /* domore_getsock */
  wssh_getsock,                         /* perform_getsock */
  wscp_disconnect,                      /* disconnect */
  ZERO_NULL,                            /* readwrite */
  ZERO_NULL,                            /* connection_check */
  PORT_SSH,                             /* defport */
  CURLPROTO_SCP,                        /* protocol */
  PROTOPT_DIRLOCK | PROTOPT_CLOSEACTION
  | PROTOPT_NOURLQUERY                  /* flags */
108
109
110
111
112
113
114
115
116
117
118
119
120

121
122
123
124
125
126
127
128
129
130

131
132
133
134
135
136
137
  ZERO_NULL,                            /* do_more */
  wssh_connect,                         /* connect_it */
  wssh_multi_statemach,                 /* connecting */
  wsftp_doing,                          /* doing */
  wssh_getsock,                         /* proto_getsock */
  wssh_getsock,                         /* doing_getsock */
  ZERO_NULL,                            /* domore_getsock */
  wssh_perform_getsock,                 /* perform_getsock */
  wsftp_disconnect,                     /* disconnect */
  ZERO_NULL,                            /* readwrite */
  ZERO_NULL,                            /* connection_check */
  PORT_SSH,                             /* defport */
  CURLPROTO_SFTP,                       /* protocol */

  PROTOPT_DIRLOCK | PROTOPT_CLOSEACTION
  | PROTOPT_NOURLQUERY                  /* flags */
};

/*
 * 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",







|





>








|

>







111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
  ZERO_NULL,                            /* do_more */
  wssh_connect,                         /* connect_it */
  wssh_multi_statemach,                 /* connecting */
  wsftp_doing,                          /* doing */
  wssh_getsock,                         /* proto_getsock */
  wssh_getsock,                         /* doing_getsock */
  ZERO_NULL,                            /* domore_getsock */
  wssh_getsock,                         /* perform_getsock */
  wsftp_disconnect,                     /* disconnect */
  ZERO_NULL,                            /* readwrite */
  ZERO_NULL,                            /* connection_check */
  PORT_SSH,                             /* defport */
  CURLPROTO_SFTP,                       /* protocol */
  CURLPROTO_SFTP,                       /* family */
  PROTOPT_DIRLOCK | PROTOPT_CLOSEACTION
  | PROTOPT_NOURLQUERY                  /* flags */
};

/*
 * SSH State machine related code
 */
/* This is the ONLY way to change SSH state! */
static void state(struct Curl_easy *data, sshstate nowstate)
{
  struct connectdata *conn = data->conn;
  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",
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238

239
240
241
242
243
244
245
    "QUIT"
  };

  /* a precaution to make sure the lists are in sync */
  DEBUGASSERT(sizeof(names)/sizeof(names[0]) == SSH_LAST);

  if(sshc->state != nowstate) {
    infof(conn->data, "wolfssh %p state change from %s to %s\n",
          (void *)sshc, names[sshc->state], names[nowstate]);
  }
#endif

  sshc->state = nowstate;
}

static ssize_t wscp_send(struct connectdata *conn, int sockindex,
                         const void *mem, size_t len, CURLcode *err)
{
  ssize_t nwrite = 0;
  (void)conn;
  (void)sockindex; /* we only support SCP on the fixed known primary socket */
  (void)mem;
  (void)len;
  (void)err;

  return nwrite;
}

static ssize_t wscp_recv(struct connectdata *conn, int sockindex,
                         char *mem, size_t len, CURLcode *err)
{
  ssize_t nread = 0;
  (void)conn;
  (void)sockindex; /* we only support SCP on the fixed known primary socket */
  (void)mem;
  (void)len;
  (void)err;

  return nread;
}

/* return number of sent bytes */
static ssize_t wsftp_send(struct connectdata *conn, int sockindex,
                          const void *mem, size_t len, CURLcode *err)
{

  struct ssh_conn *sshc = &conn->proto.sshc;
  word32 offset[2];
  int rc;
  (void)sockindex;

  offset[0] = (word32)sshc->offset&0xFFFFFFFF;
  offset[1] = (word32)(sshc->offset>>32)&0xFFFFFFFF;







|







|



|








|



|









|


>







199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
    "QUIT"
  };

  /* a precaution to make sure the lists are in sync */
  DEBUGASSERT(sizeof(names)/sizeof(names[0]) == SSH_LAST);

  if(sshc->state != nowstate) {
    infof(data, "wolfssh %p state change from %s to %s\n",
          (void *)sshc, names[sshc->state], names[nowstate]);
  }
#endif

  sshc->state = nowstate;
}

static ssize_t wscp_send(struct Curl_easy *data, int sockindex,
                         const void *mem, size_t len, CURLcode *err)
{
  ssize_t nwrite = 0;
  (void)data;
  (void)sockindex; /* we only support SCP on the fixed known primary socket */
  (void)mem;
  (void)len;
  (void)err;

  return nwrite;
}

static ssize_t wscp_recv(struct Curl_easy *data, int sockindex,
                         char *mem, size_t len, CURLcode *err)
{
  ssize_t nread = 0;
  (void)data;
  (void)sockindex; /* we only support SCP on the fixed known primary socket */
  (void)mem;
  (void)len;
  (void)err;

  return nread;
}

/* return number of sent bytes */
static ssize_t wsftp_send(struct Curl_easy *data, int sockindex,
                          const void *mem, size_t len, CURLcode *err)
{
  struct connectdata *conn = data->conn;
  struct ssh_conn *sshc = &conn->proto.sshc;
  word32 offset[2];
  int rc;
  (void)sockindex;

  offset[0] = (word32)sshc->offset&0xFFFFFFFF;
  offset[1] = (word32)(sshc->offset>>32)&0xFFFFFFFF;
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282

283
284
285
286
287
288
289
  }
  else if(rc == WS_WANT_WRITE) {
    conn->waitfor = KEEP_SEND;
    *err = CURLE_AGAIN;
    return -1;
  }
  if(rc < 0) {
    failf(conn->data, "wolfSSH_SFTP_SendWritePacket returned %d\n", rc);
    return -1;
  }
  DEBUGASSERT(rc == (int)len);
  infof(conn->data, "sent %zd bytes SFTP from offset %zd\n",
        len, sshc->offset);
  sshc->offset += len;
  return (ssize_t)rc;
}

/*
 * Return number of received (decrypted) bytes
 * or <0 on error
 */
static ssize_t wsftp_recv(struct connectdata *conn, int sockindex,
                          char *mem, size_t len, CURLcode *err)
{
  int rc;

  struct ssh_conn *sshc = &conn->proto.sshc;
  word32 offset[2];
  (void)sockindex;

  offset[0] = (word32)sshc->offset&0xFFFFFFFF;
  offset[1] = (word32)(sshc->offset>>32)&0xFFFFFFFF;








|



|









|



>







264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
  }
  else if(rc == WS_WANT_WRITE) {
    conn->waitfor = KEEP_SEND;
    *err = CURLE_AGAIN;
    return -1;
  }
  if(rc < 0) {
    failf(data, "wolfSSH_SFTP_SendWritePacket returned %d", rc);
    return -1;
  }
  DEBUGASSERT(rc == (int)len);
  infof(data, "sent %zd bytes SFTP from offset %zd\n",
        len, sshc->offset);
  sshc->offset += len;
  return (ssize_t)rc;
}

/*
 * Return number of received (decrypted) bytes
 * or <0 on error
 */
static ssize_t wsftp_recv(struct Curl_easy *data, int sockindex,
                          char *mem, size_t len, CURLcode *err)
{
  int rc;
  struct connectdata *conn = data->conn;
  struct ssh_conn *sshc = &conn->proto.sshc;
  word32 offset[2];
  (void)sockindex;

  offset[0] = (word32)sshc->offset&0xFFFFFFFF;
  offset[1] = (word32)(sshc->offset>>32)&0xFFFFFFFF;

303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321

322
323

324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
    *err = CURLE_AGAIN;
    return -1;
  }

  DEBUGASSERT(rc <= (int)len);

  if(rc < 0) {
    failf(conn->data, "wolfSSH_SFTP_SendReadPacket returned %d\n", rc);
    return -1;
  }
  sshc->offset += len;

  return (ssize_t)rc;
}

/*
 * SSH setup and connection
 */
static CURLcode wssh_setup_connection(struct connectdata *conn)

{
  struct SSHPROTO *ssh;


  conn->data->req.p.ssh = ssh = calloc(1, sizeof(struct SSHPROTO));
  if(!ssh)
    return CURLE_OUT_OF_MEMORY;

  return CURLE_OK;
}

static Curl_recv wscp_recv, wsftp_recv;
static Curl_send wscp_send, wsftp_send;

static int userauth(byte authtype,
                    WS_UserAuthData* authdata,
                    void *ctx)
{
  struct connectdata *conn = ctx;
  DEBUGF(infof(conn->data, "wolfssh callback: type %s\n",
               authtype == WOLFSSH_USERAUTH_PASSWORD ? "PASSWORD" :
               "PUBLICCKEY"));
  if(authtype == WOLFSSH_USERAUTH_PASSWORD) {
    authdata->sf.password.password = (byte *)conn->passwd;
    authdata->sf.password.passwordSz = (word32) strlen(conn->passwd);
  }

  return 0;
}

static CURLcode wssh_connect(struct connectdata *conn, bool *done)
{
  struct Curl_easy *data = conn->data;
  struct ssh_conn *sshc;
  curl_socket_t sock = conn->sock[FIRSTSOCKET];
  int rc;

  /* initialize per-handle data if not already */
  if(!data->req.p.ssh)
    wssh_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] = wscp_recv;







|










|
>


>

|













|
|



|
|





|

|






|







310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
    *err = CURLE_AGAIN;
    return -1;
  }

  DEBUGASSERT(rc <= (int)len);

  if(rc < 0) {
    failf(data, "wolfSSH_SFTP_SendReadPacket returned %d", rc);
    return -1;
  }
  sshc->offset += len;

  return (ssize_t)rc;
}

/*
 * SSH setup and connection
 */
static CURLcode wssh_setup_connection(struct Curl_easy *data,
                                      struct connectdata *conn)
{
  struct SSHPROTO *ssh;
  (void)conn;

  data->req.p.ssh = ssh = calloc(1, sizeof(struct SSHPROTO));
  if(!ssh)
    return CURLE_OUT_OF_MEMORY;

  return CURLE_OK;
}

static Curl_recv wscp_recv, wsftp_recv;
static Curl_send wscp_send, wsftp_send;

static int userauth(byte authtype,
                    WS_UserAuthData* authdata,
                    void *ctx)
{
  struct Curl_easy *data = ctx;
  DEBUGF(infof(data, "wolfssh callback: type %s\n",
               authtype == WOLFSSH_USERAUTH_PASSWORD ? "PASSWORD" :
               "PUBLICCKEY"));
  if(authtype == WOLFSSH_USERAUTH_PASSWORD) {
    authdata->sf.password.password = (byte *)data->conn->passwd;
    authdata->sf.password.passwordSz = (word32) strlen(data->conn->passwd);
  }

  return 0;
}

static CURLcode wssh_connect(struct Curl_easy *data, bool *done)
{
  struct connectdata *conn = data->conn;
  struct ssh_conn *sshc;
  curl_socket_t sock = conn->sock[FIRSTSOCKET];
  int rc;

  /* initialize per-handle data if not already */
  if(!data->req.p.ssh)
    wssh_setup_connection(data, 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] = wscp_recv;
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429

430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
  if(rc != WS_SUCCESS) {
    failf(data, "wolfSSH failed to set user name");
    goto error;
  }

  /* set callback for authentication */
  wolfSSH_SetUserAuth(sshc->ctx, userauth);
  wolfSSH_SetUserAuthCtx(sshc->ssh_session, conn);

  rc = wolfSSH_set_fd(sshc->ssh_session, (int)sock);
  if(rc) {
    failf(data, "wolfSSH failed to set socket");
    goto error;
  }

#if 0
  wolfSSH_Debugging_ON();
#endif

  *done = TRUE;
  if(conn->handler->protocol & CURLPROTO_SCP)
    state(conn, SSH_INIT);
  else
    state(conn, SSH_SFTP_INIT);

  return wssh_multi_statemach(conn, done);
  error:
  wolfSSH_free(sshc->ssh_session);
  wolfSSH_CTX_free(sshc->ctx);
  return CURLE_FAILED_INIT;
}

/*
 * wssh_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 wolfssh function returns EAGAIN meaning it
 * wants to be called again when the socket is ready
 */

static CURLcode wssh_statemach_act(struct connectdata *conn, bool *block)
{
  CURLcode result = CURLE_OK;

  struct ssh_conn *sshc = &conn->proto.sshc;
  struct Curl_easy *data = conn->data;
  struct SSHPROTO *sftp_scp = data->req.p.ssh;
  WS_SFTPNAME *name;
  int rc = 0;
  *block = FALSE; /* we're not blocking by default */

  do {
    switch(sshc->state) {
    case SSH_INIT:
      state(conn, SSH_S_STARTUP);
      /* FALLTHROUGH */
    case SSH_S_STARTUP:
      rc = wolfSSH_connect(sshc->ssh_session);
      if(rc != WS_SUCCESS)
        rc = wolfSSH_get_error(sshc->ssh_session);
      if(rc == WS_WANT_READ) {
        *block = TRUE;
        conn->waitfor = KEEP_RECV;
        return CURLE_OK;
      }
      else if(rc == WS_WANT_WRITE) {
        *block = TRUE;
        conn->waitfor = KEEP_SEND;
        return CURLE_OK;
      }
      else if(rc != WS_SUCCESS) {
        state(conn, SSH_STOP);
        return CURLE_SSH;
      }
      infof(data, "wolfssh connected!\n");
      state(conn, SSH_STOP);
      break;
    case SSH_STOP:
      break;

    case SSH_SFTP_INIT:
      rc = wolfSSH_SFTP_connect(sshc->ssh_session);
      if(rc != WS_SUCCESS)
        rc = wolfSSH_get_error(sshc->ssh_session);
      if(rc == WS_WANT_READ) {
        *block = TRUE;
        conn->waitfor = KEEP_RECV;
        return CURLE_OK;
      }
      else if(rc == WS_WANT_WRITE) {
        *block = TRUE;
        conn->waitfor = KEEP_SEND;
        return CURLE_OK;
      }
      else if(rc == WS_SUCCESS) {
        infof(data, "wolfssh SFTP connected!\n");
        state(conn, SSH_SFTP_REALPATH);
      }
      else {
        failf(data, "wolfssh SFTP connect error %d", rc);
        return CURLE_SSH;
      }
      break;
    case SSH_SFTP_REALPATH:







|













|

|

|













|


>

<








|
















|



|




















|







397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440

441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
  if(rc != WS_SUCCESS) {
    failf(data, "wolfSSH failed to set user name");
    goto error;
  }

  /* set callback for authentication */
  wolfSSH_SetUserAuth(sshc->ctx, userauth);
  wolfSSH_SetUserAuthCtx(sshc->ssh_session, data);

  rc = wolfSSH_set_fd(sshc->ssh_session, (int)sock);
  if(rc) {
    failf(data, "wolfSSH failed to set socket");
    goto error;
  }

#if 0
  wolfSSH_Debugging_ON();
#endif

  *done = TRUE;
  if(conn->handler->protocol & CURLPROTO_SCP)
    state(data, SSH_INIT);
  else
    state(data, SSH_SFTP_INIT);

  return wssh_multi_statemach(data, done);
  error:
  wolfSSH_free(sshc->ssh_session);
  wolfSSH_CTX_free(sshc->ctx);
  return CURLE_FAILED_INIT;
}

/*
 * wssh_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 wolfssh function returns EAGAIN meaning it
 * wants to be called again when the socket is ready
 */

static CURLcode wssh_statemach_act(struct Curl_easy *data, bool *block)
{
  CURLcode result = CURLE_OK;
  struct connectdata *conn = data->conn;
  struct ssh_conn *sshc = &conn->proto.sshc;

  struct SSHPROTO *sftp_scp = data->req.p.ssh;
  WS_SFTPNAME *name;
  int rc = 0;
  *block = FALSE; /* we're not blocking by default */

  do {
    switch(sshc->state) {
    case SSH_INIT:
      state(data, SSH_S_STARTUP);
      /* FALLTHROUGH */
    case SSH_S_STARTUP:
      rc = wolfSSH_connect(sshc->ssh_session);
      if(rc != WS_SUCCESS)
        rc = wolfSSH_get_error(sshc->ssh_session);
      if(rc == WS_WANT_READ) {
        *block = TRUE;
        conn->waitfor = KEEP_RECV;
        return CURLE_OK;
      }
      else if(rc == WS_WANT_WRITE) {
        *block = TRUE;
        conn->waitfor = KEEP_SEND;
        return CURLE_OK;
      }
      else if(rc != WS_SUCCESS) {
        state(data, SSH_STOP);
        return CURLE_SSH;
      }
      infof(data, "wolfssh connected!\n");
      state(data, SSH_STOP);
      break;
    case SSH_STOP:
      break;

    case SSH_SFTP_INIT:
      rc = wolfSSH_SFTP_connect(sshc->ssh_session);
      if(rc != WS_SUCCESS)
        rc = wolfSSH_get_error(sshc->ssh_session);
      if(rc == WS_WANT_READ) {
        *block = TRUE;
        conn->waitfor = KEEP_RECV;
        return CURLE_OK;
      }
      else if(rc == WS_WANT_WRITE) {
        *block = TRUE;
        conn->waitfor = KEEP_SEND;
        return CURLE_OK;
      }
      else if(rc == WS_SUCCESS) {
        infof(data, "wolfssh SFTP connected!\n");
        state(data, SSH_SFTP_REALPATH);
      }
      else {
        failf(data, "wolfssh SFTP connect error %d", rc);
        return CURLE_SSH;
      }
      break;
    case SSH_SFTP_REALPATH:
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
        }
        else {
          memcpy(sshc->homedir, name->fName, name->fSz);
          sshc->homedir[name->fSz] = 0;
          infof(data, "wolfssh SFTP realpath succeeded!\n");
        }
        wolfSSH_SFTPNAME_list_free(name);
        state(conn, SSH_STOP);
        return CURLE_OK;
      }
      failf(data, "wolfssh SFTP realpath %d", rc);
      return CURLE_SSH;

    case SSH_SFTP_QUOTE_INIT:
      result = Curl_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_GETINFO);
      }
      break;
    case SSH_SFTP_GETINFO:
      if(data->set.get_filetime) {
        state(conn, SSH_SFTP_FILETIME);
      }
      else {
        state(conn, SSH_SFTP_TRANS_INIT);
      }
      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: {
      word32 flags;
      WS_SFTP_FILEATRB createattrs;
      if(data->state.resume_from) {
        WS_SFTP_FILEATRB attrs;







|






|


|






|


|




|


|




|


|

|







515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
        }
        else {
          memcpy(sshc->homedir, name->fName, name->fSz);
          sshc->homedir[name->fSz] = 0;
          infof(data, "wolfssh SFTP realpath succeeded!\n");
        }
        wolfSSH_SFTPNAME_list_free(name);
        state(data, SSH_STOP);
        return CURLE_OK;
      }
      failf(data, "wolfssh SFTP realpath %d", rc);
      return CURLE_SSH;

    case SSH_SFTP_QUOTE_INIT:
      result = Curl_getworkingpath(data, sshc->homedir, &sftp_scp->path);
      if(result) {
        sshc->actualcode = result;
        state(data, SSH_STOP);
        break;
      }

      if(data->set.quote) {
        infof(data, "Sending quote commands\n");
        sshc->quote_item = data->set.quote;
        state(data, SSH_SFTP_QUOTE);
      }
      else {
        state(data, SSH_SFTP_GETINFO);
      }
      break;
    case SSH_SFTP_GETINFO:
      if(data->set.get_filetime) {
        state(data, SSH_SFTP_FILETIME);
      }
      else {
        state(data, SSH_SFTP_TRANS_INIT);
      }
      break;
    case SSH_SFTP_TRANS_INIT:
      if(data->set.upload)
        state(data, SSH_SFTP_UPLOAD_INIT);
      else {
        if(sftp_scp->path[strlen(sftp_scp->path)-1] == '/')
          state(data, SSH_SFTP_READDIR_INIT);
        else
          state(data, SSH_SFTP_DOWNLOAD_INIT);
      }
      break;
    case SSH_SFTP_UPLOAD_INIT: {
      word32 flags;
      WS_SFTP_FILEATRB createattrs;
      if(data->state.resume_from) {
        WS_SFTP_FILEATRB attrs;
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
      if(data->set.ftp_append)
        /* Try to open for append, but create if nonexisting */
        flags = WOLFSSH_FXF_WRITE|WOLFSSH_FXF_CREAT|WOLFSSH_FXF_APPEND;
      else if(data->state.resume_from > 0)
        /* If we have restart position then open for append */
        flags = WOLFSSH_FXF_WRITE|WOLFSSH_FXF_APPEND;
      else
        /* Clear file before writing (normal behaviour) */
        flags = WOLFSSH_FXF_WRITE|WOLFSSH_FXF_CREAT|WOLFSSH_FXF_TRUNC;

      memset(&createattrs, 0, sizeof(createattrs));
      createattrs.per = (word32)data->set.new_file_perms;
      sshc->handleSz = sizeof(sshc->handle);
      rc = wolfSSH_SFTP_Open(sshc->ssh_session, sftp_scp->path,
                             flags, &createattrs,







|







588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
      if(data->set.ftp_append)
        /* Try to open for append, but create if nonexisting */
        flags = WOLFSSH_FXF_WRITE|WOLFSSH_FXF_CREAT|WOLFSSH_FXF_APPEND;
      else if(data->state.resume_from > 0)
        /* If we have restart position then open for append */
        flags = WOLFSSH_FXF_WRITE|WOLFSSH_FXF_APPEND;
      else
        /* Clear file before writing (normal behavior) */
        flags = WOLFSSH_FXF_WRITE|WOLFSSH_FXF_CREAT|WOLFSSH_FXF_TRUNC;

      memset(&createattrs, 0, sizeof(createattrs));
      createattrs.per = (word32)data->set.new_file_perms;
      sshc->handleSz = sizeof(sshc->handle);
      rc = wolfSSH_SFTP_Open(sshc->ssh_session, sftp_scp->path,
                             flags, &createattrs,
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
      else if(rc == WS_SUCCESS) {
        infof(data, "wolfssh SFTP open succeeded!\n");
      }
      else {
        failf(data, "wolfssh SFTP upload open failed: %d", rc);
        return CURLE_SSH;
      }
      state(conn, SSH_SFTP_DOWNLOAD_STAT);

      /* 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. */
        int seekerr = CURL_SEEKFUNC_OK;
        if(conn->seek_func) {







|







616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
      else if(rc == WS_SUCCESS) {
        infof(data, "wolfssh SFTP open succeeded!\n");
      }
      else {
        failf(data, "wolfssh SFTP upload open failed: %d", rc);
        return CURLE_SSH;
      }
      state(data, SSH_SFTP_DOWNLOAD_STAT);

      /* 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. */
        int seekerr = CURL_SEEKFUNC_OK;
        if(conn->seek_func) {
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
      /* upload data */
      Curl_setup_transfer(data, -1, -1, FALSE, FIRSTSOCKET);

      /* 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, 0, EXPIRE_RUN_NOW);

        state(conn, SSH_STOP);
      }
      break;
    }
    case SSH_SFTP_DOWNLOAD_INIT:
      sshc->handleSz = sizeof(sshc->handle);
      rc = wolfSSH_SFTP_Open(sshc->ssh_session, sftp_scp->path,
                             WOLFSSH_FXF_READ, NULL,







|

















|







681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
      /* upload data */
      Curl_setup_transfer(data, -1, -1, FALSE, FIRSTSOCKET);

      /* not set by Curl_setup_transfer to preserve keepon bits */
      conn->sockfd = conn->writesockfd;

      if(result) {
        state(data, 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, 0, EXPIRE_RUN_NOW);

        state(data, SSH_STOP);
      }
      break;
    }
    case SSH_SFTP_DOWNLOAD_INIT:
      sshc->handleSz = sizeof(sshc->handle);
      rc = wolfSSH_SFTP_Open(sshc->ssh_session, sftp_scp->path,
                             WOLFSSH_FXF_READ, NULL,
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
      else if(rc == WS_WANT_WRITE) {
        *block = TRUE;
        conn->waitfor = KEEP_SEND;
        return CURLE_OK;
      }
      else if(rc == WS_SUCCESS) {
        infof(data, "wolfssh SFTP open succeeded!\n");
        state(conn, SSH_SFTP_DOWNLOAD_STAT);
        return CURLE_OK;
      }

      failf(data, "wolfssh SFTP open failed: %d", rc);
      return CURLE_SSH;

    case SSH_SFTP_DOWNLOAD_STAT: {







|







722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
      else if(rc == WS_WANT_WRITE) {
        *block = TRUE;
        conn->waitfor = KEEP_SEND;
        return CURLE_OK;
      }
      else if(rc == WS_SUCCESS) {
        infof(data, "wolfssh SFTP open succeeded!\n");
        state(data, SSH_SFTP_DOWNLOAD_STAT);
        return CURLE_OK;
      }

      failf(data, "wolfssh SFTP open failed: %d", rc);
      return CURLE_SSH;

    case SSH_SFTP_DOWNLOAD_STAT: {
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
      data->req.maxdownload = size;
      Curl_pgrsSetDownloadSize(data, size);

      infof(data, "SFTP download %" CURL_FORMAT_CURL_OFF_T " bytes\n", size);

      /* We cannot seek with wolfSSH so resuming and range requests are not
         possible */
      if(conn->data->state.use_range || data->state.resume_from) {
        infof(data, "wolfSSH cannot do range/seek on SFTP\n");
        return CURLE_BAD_DOWNLOAD_RESUME;
      }

      /* Setup the actual download */
      if(data->req.size == 0) {
        /* no data to transfer */
        Curl_setup_transfer(data, -1, -1, FALSE, -1);
        infof(data, "File already completely downloaded\n");
        state(conn, SSH_STOP);
        break;
      }
      Curl_setup_transfer(data, FIRSTSOCKET, data->req.size, FALSE, -1);

      /* 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->handleSz)
        rc = wolfSSH_SFTP_Close(sshc->ssh_session, sshc->handle,
                                sshc->handleSz);
      else
        rc = WS_SUCCESS; /* directory listing */
      if(rc == WS_WANT_READ) {
        *block = TRUE;
        conn->waitfor = KEEP_RECV;
        return CURLE_OK;
      }
      else if(rc == WS_WANT_WRITE) {
        *block = TRUE;
        conn->waitfor = KEEP_SEND;
        return CURLE_OK;
      }
      else if(rc == WS_SUCCESS) {
        state(conn, SSH_STOP);
        return CURLE_OK;
      }

      failf(data, "wolfssh SFTP CLOSE failed: %d", rc);
      return CURLE_SSH;

    case SSH_SFTP_READDIR_INIT:
      Curl_pgrsSetDownloadSize(data, -1);
      if(data->set.opt_no_body) {
        state(conn, SSH_STOP);
        break;
      }
      state(conn, SSH_SFTP_READDIR);
      /* FALLTHROUGH */
    case SSH_SFTP_READDIR:
      name = wolfSSH_SFTP_LS(sshc->ssh_session, sftp_scp->path);
      if(!name)
        rc = wolfSSH_get_error(sshc->ssh_session);
      else
        rc = WS_SUCCESS;







|









|















|



|




















|









|


|







767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
      data->req.maxdownload = size;
      Curl_pgrsSetDownloadSize(data, size);

      infof(data, "SFTP download %" CURL_FORMAT_CURL_OFF_T " bytes\n", size);

      /* We cannot seek with wolfSSH so resuming and range requests are not
         possible */
      if(data->state.use_range || data->state.resume_from) {
        infof(data, "wolfSSH cannot do range/seek on SFTP\n");
        return CURLE_BAD_DOWNLOAD_RESUME;
      }

      /* Setup the actual download */
      if(data->req.size == 0) {
        /* no data to transfer */
        Curl_setup_transfer(data, -1, -1, FALSE, -1);
        infof(data, "File already completely downloaded\n");
        state(data, SSH_STOP);
        break;
      }
      Curl_setup_transfer(data, FIRSTSOCKET, data->req.size, FALSE, -1);

      /* 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(data, SSH_SFTP_CLOSE);
        sshc->actualcode = result;
      }
      else {
        state(data, SSH_STOP);
      }
      break;
    }
    case SSH_SFTP_CLOSE:
      if(sshc->handleSz)
        rc = wolfSSH_SFTP_Close(sshc->ssh_session, sshc->handle,
                                sshc->handleSz);
      else
        rc = WS_SUCCESS; /* directory listing */
      if(rc == WS_WANT_READ) {
        *block = TRUE;
        conn->waitfor = KEEP_RECV;
        return CURLE_OK;
      }
      else if(rc == WS_WANT_WRITE) {
        *block = TRUE;
        conn->waitfor = KEEP_SEND;
        return CURLE_OK;
      }
      else if(rc == WS_SUCCESS) {
        state(data, SSH_STOP);
        return CURLE_OK;
      }

      failf(data, "wolfssh SFTP CLOSE failed: %d", rc);
      return CURLE_SSH;

    case SSH_SFTP_READDIR_INIT:
      Curl_pgrsSetDownloadSize(data, -1);
      if(data->set.opt_no_body) {
        state(data, SSH_STOP);
        break;
      }
      state(data, SSH_SFTP_READDIR);
      /* FALLTHROUGH */
    case SSH_SFTP_READDIR:
      name = wolfSSH_SFTP_LS(sshc->ssh_session, sftp_scp->path);
      if(!name)
        rc = wolfSSH_get_error(sshc->ssh_session);
      else
        rc = WS_SUCCESS;
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891

892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925

926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977

978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
        WS_SFTPNAME *origname = name;
        result = CURLE_OK;
        while(name) {
          char *line = aprintf("%s\n",
                               data->set.ftp_list_only ?
                               name->fName : name->lName);
          if(line == NULL) {
            state(conn, SSH_SFTP_CLOSE);
            sshc->actualcode = CURLE_OUT_OF_MEMORY;
            break;
          }
          result = Curl_client_write(conn, CLIENTWRITE_BODY,
                                     line, strlen(line));
          free(line);
          if(result) {
            sshc->actualcode = result;
            break;
          }
          name = name->next;
        }
        wolfSSH_SFTPNAME_list_free(origname);
        state(conn, SSH_STOP);
        return result;
      }
      failf(data, "wolfssh SFTP ls failed: %d", rc);
      return CURLE_SSH;

    case SSH_SFTP_SHUTDOWN:
      Curl_safefree(sshc->homedir);
      wolfSSH_free(sshc->ssh_session);
      wolfSSH_CTX_free(sshc->ctx);
      state(conn, SSH_STOP);
      return CURLE_OK;
    default:
      break;
    }
  } while(!rc && (sshc->state != SSH_STOP));
  return result;
}

/* called repeatedly until done from multi.c */
static CURLcode wssh_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 */
  do {
    result = wssh_statemach_act(conn, &block);
    *done = (sshc->state == SSH_STOP) ? TRUE : FALSE;
    /* if there's no error, it isn't done and it didn't EWOULDBLOCK, then
       try again */
    if(*done) {
      DEBUGF(infof(conn->data, "wssh_statemach_act says DONE\n"));
    }
  } while(!result && !*done && !block);

  return result;
}

static
CURLcode wscp_perform(struct connectdata *conn,
                      bool *connected,
                      bool *dophase_done)
{
  (void)conn;
  (void)connected;
  (void)dophase_done;
  return CURLE_OK;
}

static
CURLcode wsftp_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 = wssh_multi_statemach(conn, dophase_done);

  *connected = conn->bits.tcpconnect[FIRSTSOCKET];

  if(*dophase_done) {
    DEBUGF(infof(conn->data, "DO phase is complete\n"));
  }

  return result;
}

/*
 * The DO function is generic for both protocols.
 */
static CURLcode wssh_do(struct connectdata *conn, bool *done)
{
  CURLcode result;
  bool connected = 0;
  struct Curl_easy *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 = wscp_perform(conn, &connected,  done);
  else
    result = wsftp_perform(conn, &connected,  done);

  return result;
}

static CURLcode wssh_block_statemach(struct connectdata *conn,
                                    bool disconnect)
{

  struct ssh_conn *sshc = &conn->proto.sshc;
  CURLcode result = CURLE_OK;
  struct Curl_easy *data = conn->data;

  while((sshc->state != SSH_STOP) && !result) {
    bool block;
    timediff_t left = 1000;
    struct curltime now = Curl_now();

    result = wssh_statemach_act(conn, &block);
    if(result)
      break;

    if(!disconnect) {
      if(Curl_pgrsUpdate(conn))
        return CURLE_ABORTED_BY_CALLBACK;

      result = Curl_speedcheck(data, now);
      if(result)
        break;

      left = Curl_timeleft(data, NULL, FALSE);







|



|









|









|









|

>





|




|







|



|






|




>

|




|


|




|








|



|














|

|




|


>


<






|




|







858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991

992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
        WS_SFTPNAME *origname = name;
        result = CURLE_OK;
        while(name) {
          char *line = aprintf("%s\n",
                               data->set.ftp_list_only ?
                               name->fName : name->lName);
          if(line == NULL) {
            state(data, SSH_SFTP_CLOSE);
            sshc->actualcode = CURLE_OUT_OF_MEMORY;
            break;
          }
          result = Curl_client_write(data, CLIENTWRITE_BODY,
                                     line, strlen(line));
          free(line);
          if(result) {
            sshc->actualcode = result;
            break;
          }
          name = name->next;
        }
        wolfSSH_SFTPNAME_list_free(origname);
        state(data, SSH_STOP);
        return result;
      }
      failf(data, "wolfssh SFTP ls failed: %d", rc);
      return CURLE_SSH;

    case SSH_SFTP_SHUTDOWN:
      Curl_safefree(sshc->homedir);
      wolfSSH_free(sshc->ssh_session);
      wolfSSH_CTX_free(sshc->ctx);
      state(data, SSH_STOP);
      return CURLE_OK;
    default:
      break;
    }
  } while(!rc && (sshc->state != SSH_STOP));
  return result;
}

/* called repeatedly until done from multi.c */
static CURLcode wssh_multi_statemach(struct Curl_easy *data, bool *done)
{
  struct connectdata *conn = data->conn;
  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 */
  do {
    result = wssh_statemach_act(data, &block);
    *done = (sshc->state == SSH_STOP) ? TRUE : FALSE;
    /* if there's no error, it isn't done and it didn't EWOULDBLOCK, then
       try again */
    if(*done) {
      DEBUGF(infof(data, "wssh_statemach_act says DONE\n"));
    }
  } while(!result && !*done && !block);

  return result;
}

static
CURLcode wscp_perform(struct Curl_easy *data,
                      bool *connected,
                      bool *dophase_done)
{
  (void)data;
  (void)connected;
  (void)dophase_done;
  return CURLE_OK;
}

static
CURLcode wsftp_perform(struct Curl_easy *data,
                       bool *connected,
                       bool *dophase_done)
{
  CURLcode result = CURLE_OK;
  struct connectdata *conn = data->conn;

  DEBUGF(infof(data, "DO phase starts\n"));

  *dophase_done = FALSE; /* not done yet */

  /* start the first command in the DO phase */
  state(data, SSH_SFTP_QUOTE_INIT);

  /* run the state-machine */
  result = wssh_multi_statemach(data, dophase_done);

  *connected = conn->bits.tcpconnect[FIRSTSOCKET];

  if(*dophase_done) {
    DEBUGF(infof(data, "DO phase is complete\n"));
  }

  return result;
}

/*
 * The DO function is generic for both protocols.
 */
static CURLcode wssh_do(struct Curl_easy *data, bool *done)
{
  CURLcode result;
  bool connected = 0;
  struct connectdata *conn = data->conn;
  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 = wscp_perform(data, &connected,  done);
  else
    result = wsftp_perform(data, &connected,  done);

  return result;
}

static CURLcode wssh_block_statemach(struct Curl_easy *data,
                                    bool disconnect)
{
  struct connectdata *conn = data->conn;
  struct ssh_conn *sshc = &conn->proto.sshc;
  CURLcode result = CURLE_OK;


  while((sshc->state != SSH_STOP) && !result) {
    bool block;
    timediff_t left = 1000;
    struct curltime now = Curl_now();

    result = wssh_statemach_act(data, &block);
    if(result)
      break;

    if(!disconnect) {
      if(Curl_pgrsUpdate(data))
        return CURLE_ABORTED_BY_CALLBACK;

      result = Curl_speedcheck(data, now);
      if(result)
        break;

      left = Curl_timeleft(data, NULL, FALSE);
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070

1071
1072

1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100


1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127

1128
1129
1130
1131
1132
1133
1134
  }

  return result;
}

/* generic done function for both SCP and SFTP called from their specific
   done functions */
static CURLcode wssh_done(struct connectdata *conn, CURLcode status)
{
  CURLcode result = CURLE_OK;
  struct SSHPROTO *sftp_scp = conn->data->req.p.ssh;

  if(!status) {
    /* run the state-machine */
    result = wssh_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;
}

#if 0
static CURLcode wscp_done(struct connectdata *conn,
                         CURLcode code, bool premature)
{
  CURLcode result = CURLE_OK;
  (void)conn;
  (void)code;
  (void)premature;

  return result;
}

static CURLcode wscp_doing(struct connectdata *conn,
                          bool *dophase_done)
{
  CURLcode result = CURLE_OK;
  (void)conn;
  (void)dophase_done;

  return result;
}

static CURLcode wscp_disconnect(struct connectdata *conn, bool dead_connection)

{
  CURLcode result = CURLE_OK;

  (void)conn;
  (void)dead_connection;

  return result;
}
#endif

static CURLcode wsftp_done(struct connectdata *conn,
                          CURLcode code, bool premature)
{
  (void)premature;
  state(conn, SSH_SFTP_CLOSE);

  return wssh_done(conn, code);
}

static CURLcode wsftp_doing(struct connectdata *conn,
                           bool *dophase_done)
{
  CURLcode result = wssh_multi_statemach(conn, dophase_done);

  if(*dophase_done) {
    DEBUGF(infof(conn->data, "DO phase is complete\n"));
  }
  return result;
}

static CURLcode wsftp_disconnect(struct connectdata *conn, bool dead)


{
  CURLcode result = CURLE_OK;
  (void)dead;

  DEBUGF(infof(conn->data, "SSH DISCONNECT starts now\n"));

  if(conn->proto.sshc.ssh_session) {
    /* only if there's a session still around to use! */
    state(conn, SSH_SFTP_SHUTDOWN);
    result = wssh_block_statemach(conn, TRUE);
  }

  DEBUGF(infof(conn->data, "SSH DISCONNECT is done\n"));
  return result;
}

static int wssh_getsock(struct connectdata *conn,
                        curl_socket_t *sock)
{
  return wssh_perform_getsock(conn, sock);
}

static int wssh_perform_getsock(const struct connectdata *conn,
                                curl_socket_t *sock)
{
  int bitmap = GETSOCK_BLANK;
  int dir = conn->waitfor;

  sock[0] = conn->sock[FIRSTSOCKET];

  if(dir == KEEP_RECV)
    bitmap |= GETSOCK_READSOCK(FIRSTSOCKET);
  else if(dir == KEEP_SEND)
    bitmap |= GETSOCK_WRITESOCK(FIRSTSOCKET);








|


|



|






|


|




|










|









|
>


>







|



|

|


|


|


|




|
>
>




|



|
|


|



|
<
<
<
<
<
|
|



>







1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132





1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
  }

  return result;
}

/* generic done function for both SCP and SFTP called from their specific
   done functions */
static CURLcode wssh_done(struct Curl_easy *data, CURLcode status)
{
  CURLcode result = CURLE_OK;
  struct SSHPROTO *sftp_scp = data->req.p.ssh;

  if(!status) {
    /* run the state-machine */
    result = wssh_block_statemach(data, FALSE);
  }
  else
    result = status;

  if(sftp_scp)
    Curl_safefree(sftp_scp->path);
  if(Curl_pgrsDone(data))
    return CURLE_ABORTED_BY_CALLBACK;

  data->req.keepon = 0; /* clear all bits */
  return result;
}

#if 0
static CURLcode wscp_done(struct Curl_easy *data,
                         CURLcode code, bool premature)
{
  CURLcode result = CURLE_OK;
  (void)conn;
  (void)code;
  (void)premature;

  return result;
}

static CURLcode wscp_doing(struct Curl_easy *data,
                          bool *dophase_done)
{
  CURLcode result = CURLE_OK;
  (void)conn;
  (void)dophase_done;

  return result;
}

static CURLcode wscp_disconnect(struct Curl_easy *data,
                                struct connectdata *conn, bool dead_connection)
{
  CURLcode result = CURLE_OK;
  (void)data;
  (void)conn;
  (void)dead_connection;

  return result;
}
#endif

static CURLcode wsftp_done(struct Curl_easy *data,
                          CURLcode code, bool premature)
{
  (void)premature;
  state(data, SSH_SFTP_CLOSE);

  return wssh_done(data, code);
}

static CURLcode wsftp_doing(struct Curl_easy *data,
                           bool *dophase_done)
{
  CURLcode result = wssh_multi_statemach(data, dophase_done);

  if(*dophase_done) {
    DEBUGF(infof(data, "DO phase is complete\n"));
  }
  return result;
}

static CURLcode wsftp_disconnect(struct Curl_easy *data,
                                 struct connectdata *conn,
                                 bool dead)
{
  CURLcode result = CURLE_OK;
  (void)dead;

  DEBUGF(infof(data, "SSH DISCONNECT starts now\n"));

  if(conn->proto.sshc.ssh_session) {
    /* only if there's a session still around to use! */
    state(data, SSH_SFTP_SHUTDOWN);
    result = wssh_block_statemach(data, TRUE);
  }

  DEBUGF(infof(data, "SSH DISCONNECT is done\n"));
  return result;
}

static int wssh_getsock(struct Curl_easy *data,





                        struct connectdata *conn,
                        curl_socket_t *sock)
{
  int bitmap = GETSOCK_BLANK;
  int dir = conn->waitfor;
  (void)data;
  sock[0] = conn->sock[FIRSTSOCKET];

  if(dir == KEEP_RECV)
    bitmap |= GETSOCK_READSOCK(FIRSTSOCKET);
  else if(dir == KEEP_SEND)
    bitmap |= GETSOCK_WRITESOCK(FIRSTSOCKET);

Changes to jni/curl/lib/vtls/bearssl.c.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 2019 - 2020, Michael Forney, <mforney@mforney.org>
 *
 * 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 https://curl.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







|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 2019 - 2021, Michael Forney, <mforney@mforney.org>
 *
 * 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 https://curl.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
290
291
292
293
294
295
296
297

298
299
300
301
302
303
304
305
306
  x509_start_cert,
  x509_append,
  x509_end_cert,
  x509_end_chain,
  x509_get_pkey
};

static CURLcode bearssl_connect_step1(struct connectdata *conn, int sockindex)

{
  struct Curl_easy *data = conn->data;
  struct ssl_connect_data *connssl = &conn->ssl[sockindex];
  struct ssl_backend_data *backend = connssl->backend;
  const char * const ssl_cafile = SSL_CONN_CONFIG(CAfile);
#ifndef CURL_DISABLE_PROXY
  const char *hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name :
    conn->host.name;
#else







|
>

<







290
291
292
293
294
295
296
297
298
299

300
301
302
303
304
305
306
  x509_start_cert,
  x509_append,
  x509_end_cert,
  x509_end_chain,
  x509_get_pkey
};

static CURLcode bearssl_connect_step1(struct Curl_easy *data,
                                      struct connectdata *conn, int sockindex)
{

  struct ssl_connect_data *connssl = &conn->ssl[sockindex];
  struct ssl_backend_data *backend = connssl->backend;
  const char * const ssl_cafile = SSL_CONN_CONFIG(CAfile);
#ifndef CURL_DISABLE_PROXY
  const char *hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name :
    conn->host.name;
#else
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
    return CURLE_SSL_CONNECT_ERROR;
  }

  if(ssl_cafile) {
    ret = load_cafile(ssl_cafile, &backend->anchors, &backend->anchors_len);
    if(ret != CURLE_OK) {
      if(verifypeer) {
        failf(data, "error setting certificate verify locations:\n"
              "  CAfile: %s\n", ssl_cafile);
        return ret;
      }
      infof(data, "error setting certificate verify locations,"
            " continuing anyway:\n");
    }
  }








|
|







345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
    return CURLE_SSL_CONNECT_ERROR;
  }

  if(ssl_cafile) {
    ret = load_cafile(ssl_cafile, &backend->anchors, &backend->anchors_len);
    if(ret != CURLE_OK) {
      if(verifypeer) {
        failf(data, "error setting certificate verify locations."
              " CAfile: %s", ssl_cafile);
        return ret;
      }
      infof(data, "error setting certificate verify locations,"
            " continuing anyway:\n");
    }
  }

370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
  backend->x509.verifypeer = verifypeer;
  backend->x509.verifyhost = verifyhost;
  br_ssl_engine_set_x509(&backend->ctx.eng, &backend->x509.vtable);

  if(SSL_SET_OPTION(primary.sessionid)) {
    void *session;

    Curl_ssl_sessionid_lock(conn);
    if(!Curl_ssl_getsessionid(conn, &session, NULL, sockindex)) {
      br_ssl_engine_set_session_parameters(&backend->ctx.eng, session);
      infof(data, "BearSSL: re-using session ID\n");
    }
    Curl_ssl_sessionid_unlock(conn);
  }

  if(conn->bits.tls_enable_alpn) {
    int cur = 0;

    /* NOTE: when adding more protocols here, increase the size of the
     * protocols array in `struct ssl_backend_data`.







|
|



|







370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
  backend->x509.verifypeer = verifypeer;
  backend->x509.verifyhost = verifyhost;
  br_ssl_engine_set_x509(&backend->ctx.eng, &backend->x509.vtable);

  if(SSL_SET_OPTION(primary.sessionid)) {
    void *session;

    Curl_ssl_sessionid_lock(data);
    if(!Curl_ssl_getsessionid(data, conn, &session, NULL, sockindex)) {
      br_ssl_engine_set_session_parameters(&backend->ctx.eng, session);
      infof(data, "BearSSL: re-using session ID\n");
    }
    Curl_ssl_sessionid_unlock(data);
  }

  if(conn->bits.tls_enable_alpn) {
    int cur = 0;

    /* NOTE: when adding more protocols here, increase the size of the
     * protocols array in `struct ssl_backend_data`.
425
426
427
428
429
430
431
432

433
434
435
436
437
438
439
440
441
442
  backend->active = TRUE;

  connssl->connecting_state = ssl_connect_2;

  return CURLE_OK;
}

static CURLcode bearssl_run_until(struct connectdata *conn, int sockindex,

                                  unsigned target)
{
  struct Curl_easy *data = conn->data;
  struct ssl_connect_data *connssl = &conn->ssl[sockindex];
  struct ssl_backend_data *backend = connssl->backend;
  curl_socket_t sockfd = conn->sock[sockindex];
  unsigned state;
  unsigned char *buf;
  size_t len;
  ssize_t ret;







|
>


<







425
426
427
428
429
430
431
432
433
434
435

436
437
438
439
440
441
442
  backend->active = TRUE;

  connssl->connecting_state = ssl_connect_2;

  return CURLE_OK;
}

static CURLcode bearssl_run_until(struct Curl_easy *data,
                                  struct connectdata *conn, int sockindex,
                                  unsigned target)
{

  struct ssl_connect_data *connssl = &conn->ssl[sockindex];
  struct ssl_backend_data *backend = connssl->backend;
  curl_socket_t sockfd = conn->sock[sockindex];
  unsigned state;
  unsigned char *buf;
  size_t len;
  ssize_t ret;
503
504
505
506
507
508
509
510

511
512
513
514
515
516

517
518
519
520
521
522
523
524
525
526
527
528
529
530

531
532
533
534
535
536
537
538
539
        return CURLE_READ_ERROR;
      }
      br_ssl_engine_recvrec_ack(&backend->ctx.eng, ret);
    }
  }
}

static CURLcode bearssl_connect_step2(struct connectdata *conn, int sockindex)

{
  struct Curl_easy *data = conn->data;
  struct ssl_connect_data *connssl = &conn->ssl[sockindex];
  struct ssl_backend_data *backend = connssl->backend;
  CURLcode ret;


  ret = bearssl_run_until(conn, sockindex, BR_SSL_SENDAPP | BR_SSL_RECVAPP);
  if(ret == CURLE_AGAIN)
    return CURLE_OK;
  if(ret == CURLE_OK) {
    if(br_ssl_engine_current_state(&backend->ctx.eng) == BR_SSL_CLOSED) {
      failf(data, "SSL: connection closed during handshake");
      return CURLE_SSL_CONNECT_ERROR;
    }
    connssl->connecting_state = ssl_connect_3;
  }
  return ret;
}

static CURLcode bearssl_connect_step3(struct connectdata *conn, int sockindex)

{
  struct Curl_easy *data = conn->data;
  struct ssl_connect_data *connssl = &conn->ssl[sockindex];
  struct ssl_backend_data *backend = connssl->backend;
  CURLcode ret;

  DEBUGASSERT(ssl_connect_3 == connssl->connecting_state);

  if(conn->bits.tls_enable_alpn) {







|
>

<




>
|












|
>

<







503
504
505
506
507
508
509
510
511
512

513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533

534
535
536
537
538
539
540
        return CURLE_READ_ERROR;
      }
      br_ssl_engine_recvrec_ack(&backend->ctx.eng, ret);
    }
  }
}

static CURLcode bearssl_connect_step2(struct Curl_easy *data,
                                      struct connectdata *conn, int sockindex)
{

  struct ssl_connect_data *connssl = &conn->ssl[sockindex];
  struct ssl_backend_data *backend = connssl->backend;
  CURLcode ret;

  ret = bearssl_run_until(data, conn, sockindex,
                          BR_SSL_SENDAPP | BR_SSL_RECVAPP);
  if(ret == CURLE_AGAIN)
    return CURLE_OK;
  if(ret == CURLE_OK) {
    if(br_ssl_engine_current_state(&backend->ctx.eng) == BR_SSL_CLOSED) {
      failf(data, "SSL: connection closed during handshake");
      return CURLE_SSL_CONNECT_ERROR;
    }
    connssl->connecting_state = ssl_connect_3;
  }
  return ret;
}

static CURLcode bearssl_connect_step3(struct Curl_easy *data,
                                      struct connectdata *conn, int sockindex)
{

  struct ssl_connect_data *connssl = &conn->ssl[sockindex];
  struct ssl_backend_data *backend = connssl->backend;
  CURLcode ret;

  DEBUGASSERT(ssl_connect_3 == connssl->connecting_state);

  if(conn->bits.tls_enable_alpn) {
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572

573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
        conn->negnpn = CURL_HTTP_VERSION_2;
      else
#endif
      if(!strcmp(protocol, ALPN_HTTP_1_1))
        conn->negnpn = CURL_HTTP_VERSION_1_1;
      else
        infof(data, "ALPN, unrecognized protocol %s\n", protocol);
      Curl_multiuse_state(conn, conn->negnpn == CURL_HTTP_VERSION_2 ?
                          BUNDLE_MULTIPLEX : BUNDLE_NO_MULTIUSE);
    }
    else
      infof(data, "ALPN, server did not agree to a protocol\n");
  }

  if(SSL_SET_OPTION(primary.sessionid)) {
    bool incache;
    void *oldsession;
    br_ssl_session_parameters *session;

    session = malloc(sizeof(*session));
    if(!session)
      return CURLE_OUT_OF_MEMORY;
    br_ssl_engine_get_session_parameters(&backend->ctx.eng, session);
    Curl_ssl_sessionid_lock(conn);
    incache = !(Curl_ssl_getsessionid(conn, &oldsession, NULL, sockindex));

    if(incache)
      Curl_ssl_delsessionid(conn, oldsession);
    ret = Curl_ssl_addsessionid(conn, session, 0, sockindex);
    Curl_ssl_sessionid_unlock(conn);
    if(ret) {
      free(session);
      return CURLE_OUT_OF_MEMORY;
    }
  }

  connssl->connecting_state = ssl_connect_done;

  return CURLE_OK;
}

static ssize_t bearssl_send(struct connectdata *conn, int sockindex,
                            const void *buf, size_t len, CURLcode *err)
{
  struct Curl_easy *data = conn->data;
  struct ssl_connect_data *connssl = &conn->ssl[sockindex];
  struct ssl_backend_data *backend = connssl->backend;
  unsigned char *app;
  size_t applen;

  for(;;) {
    *err = bearssl_run_until(conn, sockindex, BR_SSL_SENDAPP);
    if (*err != CURLE_OK)
      return -1;
    app = br_ssl_engine_sendapp_buf(&backend->ctx.eng, &applen);
    if(!app) {
      failf(data, "SSL: connection closed during write");
      *err = CURLE_SEND_ERROR;
      return -1;







|















|
|
>

|
|
|











|


|






|







549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
        conn->negnpn = CURL_HTTP_VERSION_2;
      else
#endif
      if(!strcmp(protocol, ALPN_HTTP_1_1))
        conn->negnpn = CURL_HTTP_VERSION_1_1;
      else
        infof(data, "ALPN, unrecognized protocol %s\n", protocol);
      Curl_multiuse_state(data, conn->negnpn == CURL_HTTP_VERSION_2 ?
                          BUNDLE_MULTIPLEX : BUNDLE_NO_MULTIUSE);
    }
    else
      infof(data, "ALPN, server did not agree to a protocol\n");
  }

  if(SSL_SET_OPTION(primary.sessionid)) {
    bool incache;
    void *oldsession;
    br_ssl_session_parameters *session;

    session = malloc(sizeof(*session));
    if(!session)
      return CURLE_OUT_OF_MEMORY;
    br_ssl_engine_get_session_parameters(&backend->ctx.eng, session);
    Curl_ssl_sessionid_lock(data);
    incache = !(Curl_ssl_getsessionid(data, conn,
                                      &oldsession, NULL, sockindex));
    if(incache)
      Curl_ssl_delsessionid(data, oldsession);
    ret = Curl_ssl_addsessionid(data, conn, session, 0, sockindex);
    Curl_ssl_sessionid_unlock(data);
    if(ret) {
      free(session);
      return CURLE_OUT_OF_MEMORY;
    }
  }

  connssl->connecting_state = ssl_connect_done;

  return CURLE_OK;
}

static ssize_t bearssl_send(struct Curl_easy *data, int sockindex,
                            const void *buf, size_t len, CURLcode *err)
{
  struct connectdata *conn = data->conn;
  struct ssl_connect_data *connssl = &conn->ssl[sockindex];
  struct ssl_backend_data *backend = connssl->backend;
  unsigned char *app;
  size_t applen;

  for(;;) {
    *err = bearssl_run_until(data, conn, sockindex, BR_SSL_SENDAPP);
    if (*err != CURLE_OK)
      return -1;
    app = br_ssl_engine_sendapp_buf(&backend->ctx.eng, &applen);
    if(!app) {
      failf(data, "SSL: connection closed during write");
      *err = CURLE_SEND_ERROR;
      return -1;
614
615
616
617
618
619
620
621
622
623

624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643

644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
    memcpy(app, buf, applen);
    br_ssl_engine_sendapp_ack(&backend->ctx.eng, applen);
    br_ssl_engine_flush(&backend->ctx.eng, 0);
    backend->pending_write = applen;
  }
}

static ssize_t bearssl_recv(struct connectdata *conn, int sockindex,
                            char *buf, size_t len, CURLcode *err)
{

  struct ssl_connect_data *connssl = &conn->ssl[sockindex];
  struct ssl_backend_data *backend = connssl->backend;
  unsigned char *app;
  size_t applen;

  *err = bearssl_run_until(conn, sockindex, BR_SSL_RECVAPP);
  if(*err != CURLE_OK)
    return -1;
  app = br_ssl_engine_recvapp_buf(&backend->ctx.eng, &applen);
  if(!app)
    return 0;
  if(applen > len)
    applen = len;
  memcpy(buf, app, applen);
  br_ssl_engine_recvapp_ack(&backend->ctx.eng, applen);

  return applen;
}

static CURLcode bearssl_connect_common(struct connectdata *conn,

                                       int sockindex,
                                       bool nonblocking,
                                       bool *done)
{
  CURLcode ret;
  struct Curl_easy *data = conn->data;
  struct ssl_connect_data *connssl = &conn->ssl[sockindex];
  curl_socket_t sockfd = conn->sock[sockindex];
  timediff_t 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) {
    ret = bearssl_connect_step1(conn, sockindex);
    if(ret)
      return ret;
  }

  while(ssl_connect_2 == connssl->connecting_state ||
        ssl_connect_2_reading == connssl->connecting_state ||
        ssl_connect_2_writing == connssl->connecting_state) {







|


>





|













|
>





<












|







616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652

653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
    memcpy(app, buf, applen);
    br_ssl_engine_sendapp_ack(&backend->ctx.eng, applen);
    br_ssl_engine_flush(&backend->ctx.eng, 0);
    backend->pending_write = applen;
  }
}

static ssize_t bearssl_recv(struct Curl_easy *data, int sockindex,
                            char *buf, size_t len, CURLcode *err)
{
  struct connectdata *conn = data->conn;
  struct ssl_connect_data *connssl = &conn->ssl[sockindex];
  struct ssl_backend_data *backend = connssl->backend;
  unsigned char *app;
  size_t applen;

  *err = bearssl_run_until(data, conn, sockindex, BR_SSL_RECVAPP);
  if(*err != CURLE_OK)
    return -1;
  app = br_ssl_engine_recvapp_buf(&backend->ctx.eng, &applen);
  if(!app)
    return 0;
  if(applen > len)
    applen = len;
  memcpy(buf, app, applen);
  br_ssl_engine_recvapp_ack(&backend->ctx.eng, applen);

  return applen;
}

static CURLcode bearssl_connect_common(struct Curl_easy *data,
                                       struct connectdata *conn,
                                       int sockindex,
                                       bool nonblocking,
                                       bool *done)
{
  CURLcode ret;

  struct ssl_connect_data *connssl = &conn->ssl[sockindex];
  curl_socket_t sockfd = conn->sock[sockindex];
  timediff_t 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) {
    ret = bearssl_connect_step1(data, conn, sockindex);
    if(ret)
      return ret;
  }

  while(ssl_connect_2 == connssl->connecting_state ||
        ssl_connect_2_reading == connssl->connecting_state ||
        ssl_connect_2_writing == connssl->connecting_state) {
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776

777
778
779
780
781
782
783
784
785
786
787
788
789
790

791
792
793
794
795
796
797
798
799
800
801
802
803

804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877

    /* 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.
     */
    ret = bearssl_connect_step2(conn, sockindex);
    if(ret || (nonblocking &&
               (ssl_connect_2 == connssl->connecting_state ||
                ssl_connect_2_reading == connssl->connecting_state ||
                ssl_connect_2_writing == connssl->connecting_state)))
      return ret;
  }

  if(ssl_connect_3 == connssl->connecting_state) {
    ret = bearssl_connect_step3(conn, sockindex);
    if(ret)
      return ret;
  }

  if(ssl_connect_done == connssl->connecting_state) {
    connssl->state = ssl_connection_complete;
    conn->recv[sockindex] = bearssl_recv;
    conn->send[sockindex] = bearssl_send;
    *done = TRUE;
  }
  else
    *done = FALSE;

  /* Reset our connect state machine */
  connssl->connecting_state = ssl_connect_1;

  return CURLE_OK;
}

static size_t Curl_bearssl_version(char *buffer, size_t size)
{
  return msnprintf(buffer, size, "BearSSL");
}

static bool Curl_bearssl_data_pending(const struct connectdata *conn,
                                      int connindex)
{
  const struct ssl_connect_data *connssl = &conn->ssl[connindex];
  struct ssl_backend_data *backend = connssl->backend;
  return br_ssl_engine_current_state(&backend->ctx.eng) & BR_SSL_RECVAPP;
}

static CURLcode Curl_bearssl_random(struct Curl_easy *data UNUSED_PARAM,
                                    unsigned char *entropy, size_t length)
{
  static br_hmac_drbg_context ctx;
  static bool seeded = FALSE;

  if(!seeded) {
    br_prng_seeder seeder;

    br_hmac_drbg_init(&ctx, &br_sha256_vtable, NULL, 0);
    seeder = br_prng_seeder_system(NULL);
    if(!seeder || !seeder(&ctx.vtable))
      return CURLE_FAILED_INIT;
    seeded = TRUE;
  }
  br_hmac_drbg_generate(&ctx, entropy, length);

  return CURLE_OK;
}


static CURLcode Curl_bearssl_connect(struct connectdata *conn, int sockindex)
{
  CURLcode ret;
  bool done = FALSE;

  ret = bearssl_connect_common(conn, sockindex, FALSE, &done);
  if(ret)
    return ret;

  DEBUGASSERT(done);

  return CURLE_OK;
}


static CURLcode Curl_bearssl_connect_nonblocking(struct connectdata *conn,
                                                 int sockindex, bool *done)
{
  return bearssl_connect_common(conn, sockindex, TRUE, done);
}

static void *Curl_bearssl_get_internals(struct ssl_connect_data *connssl,
                                        CURLINFO info UNUSED_PARAM)
{
  struct ssl_backend_data *backend = connssl->backend;
  return &backend->ctx;
}


static void Curl_bearssl_close(struct connectdata *conn, int sockindex)
{
  struct ssl_connect_data *connssl = &conn->ssl[sockindex];
  struct ssl_backend_data *backend = connssl->backend;
  size_t i;

  if(backend->active) {
    br_ssl_engine_close(&backend->ctx.eng);
    (void)bearssl_run_until(conn, sockindex, BR_SSL_CLOSED);
  }
  for(i = 0; i < backend->anchors_len; ++i)
    free(backend->anchors[i].dn.data);
  free(backend->anchors);
}

static void Curl_bearssl_session_free(void *ptr)
{
  free(ptr);
}

static CURLcode Curl_bearssl_md5sum(unsigned char *input,
                                    size_t inputlen,
                                    unsigned char *md5sum,
                                    size_t md5len UNUSED_PARAM)
{
  br_md5_context ctx;

  br_md5_init(&ctx);
  br_md5_update(&ctx, input, inputlen);
  br_md5_out(&ctx, md5sum);
  return CURLE_OK;
}

static CURLcode Curl_bearssl_sha256sum(const unsigned char *input,
                                       size_t inputlen,
                                       unsigned char *sha256sum,
                                       size_t sha256len UNUSED_PARAM)
{
  br_sha256_context ctx;

  br_sha256_init(&ctx);
  br_sha256_update(&ctx, input, inputlen);
  br_sha256_out(&ctx, sha256sum);
  return CURLE_OK;
}

const struct Curl_ssl Curl_ssl_bearssl = {
  { CURLSSLBACKEND_BEARSSL, "bearssl" },
  0,
  sizeof(struct ssl_backend_data),

  Curl_none_init,
  Curl_none_cleanup,
  Curl_bearssl_version,
  Curl_none_check_cxn,
  Curl_none_shutdown,
  Curl_bearssl_data_pending,
  Curl_bearssl_random,
  Curl_none_cert_status_request,
  Curl_bearssl_connect,
  Curl_bearssl_connect_nonblocking,
  Curl_bearssl_get_internals,
  Curl_bearssl_close,
  Curl_none_close_all,
  Curl_bearssl_session_free,
  Curl_none_set_engine,
  Curl_none_set_engine_default,
  Curl_none_engines_list,
  Curl_none_false_start,
  Curl_bearssl_md5sum,
  Curl_bearssl_sha256sum
};

#endif /* USE_BEARSSL */







|








|



















|




|
|






|
|


















>
|




|








>
|
|

|


|
|





>
|







|






|




<
<
<
<
<
<
<
<
<
<
<
<
<
|
|
|
|
















|


|
|

|
|
|
|

|




<
|



711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829













830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865

866
867
868
869

    /* 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.
     */
    ret = bearssl_connect_step2(data, conn, sockindex);
    if(ret || (nonblocking &&
               (ssl_connect_2 == connssl->connecting_state ||
                ssl_connect_2_reading == connssl->connecting_state ||
                ssl_connect_2_writing == connssl->connecting_state)))
      return ret;
  }

  if(ssl_connect_3 == connssl->connecting_state) {
    ret = bearssl_connect_step3(data, conn, sockindex);
    if(ret)
      return ret;
  }

  if(ssl_connect_done == connssl->connecting_state) {
    connssl->state = ssl_connection_complete;
    conn->recv[sockindex] = bearssl_recv;
    conn->send[sockindex] = bearssl_send;
    *done = TRUE;
  }
  else
    *done = FALSE;

  /* Reset our connect state machine */
  connssl->connecting_state = ssl_connect_1;

  return CURLE_OK;
}

static size_t bearssl_version(char *buffer, size_t size)
{
  return msnprintf(buffer, size, "BearSSL");
}

static bool bearssl_data_pending(const struct connectdata *conn,
                                 int connindex)
{
  const struct ssl_connect_data *connssl = &conn->ssl[connindex];
  struct ssl_backend_data *backend = connssl->backend;
  return br_ssl_engine_current_state(&backend->ctx.eng) & BR_SSL_RECVAPP;
}

static CURLcode bearssl_random(struct Curl_easy *data UNUSED_PARAM,
                               unsigned char *entropy, size_t length)
{
  static br_hmac_drbg_context ctx;
  static bool seeded = FALSE;

  if(!seeded) {
    br_prng_seeder seeder;

    br_hmac_drbg_init(&ctx, &br_sha256_vtable, NULL, 0);
    seeder = br_prng_seeder_system(NULL);
    if(!seeder || !seeder(&ctx.vtable))
      return CURLE_FAILED_INIT;
    seeded = TRUE;
  }
  br_hmac_drbg_generate(&ctx, entropy, length);

  return CURLE_OK;
}

static CURLcode bearssl_connect(struct Curl_easy *data,
                                struct connectdata *conn, int sockindex)
{
  CURLcode ret;
  bool done = FALSE;

  ret = bearssl_connect_common(data, conn, sockindex, FALSE, &done);
  if(ret)
    return ret;

  DEBUGASSERT(done);

  return CURLE_OK;
}

static CURLcode bearssl_connect_nonblocking(struct Curl_easy *data,
                                            struct connectdata *conn,
                                            int sockindex, bool *done)
{
  return bearssl_connect_common(data, conn, sockindex, TRUE, done);
}

static void *bearssl_get_internals(struct ssl_connect_data *connssl,
                                   CURLINFO info UNUSED_PARAM)
{
  struct ssl_backend_data *backend = connssl->backend;
  return &backend->ctx;
}

static void bearssl_close(struct Curl_easy *data,
                          struct connectdata *conn, int sockindex)
{
  struct ssl_connect_data *connssl = &conn->ssl[sockindex];
  struct ssl_backend_data *backend = connssl->backend;
  size_t i;

  if(backend->active) {
    br_ssl_engine_close(&backend->ctx.eng);
    (void)bearssl_run_until(data, conn, sockindex, BR_SSL_CLOSED);
  }
  for(i = 0; i < backend->anchors_len; ++i)
    free(backend->anchors[i].dn.data);
  free(backend->anchors);
}

static void bearssl_session_free(void *ptr)
{
  free(ptr);
}














static CURLcode bearssl_sha256sum(const unsigned char *input,
                                  size_t inputlen,
                                  unsigned char *sha256sum,
                                  size_t sha256len UNUSED_PARAM)
{
  br_sha256_context ctx;

  br_sha256_init(&ctx);
  br_sha256_update(&ctx, input, inputlen);
  br_sha256_out(&ctx, sha256sum);
  return CURLE_OK;
}

const struct Curl_ssl Curl_ssl_bearssl = {
  { CURLSSLBACKEND_BEARSSL, "bearssl" },
  0,
  sizeof(struct ssl_backend_data),

  Curl_none_init,
  Curl_none_cleanup,
  bearssl_version,
  Curl_none_check_cxn,
  Curl_none_shutdown,
  bearssl_data_pending,
  bearssl_random,
  Curl_none_cert_status_request,
  bearssl_connect,
  bearssl_connect_nonblocking,
  bearssl_get_internals,
  bearssl_close,
  Curl_none_close_all,
  bearssl_session_free,
  Curl_none_set_engine,
  Curl_none_set_engine_default,
  Curl_none_engines_list,
  Curl_none_false_start,

  bearssl_sha256sum
};

#endif /* USE_BEARSSL */
Changes to jni/curl/lib/vtls/gskit.c.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2020, 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 https://curl.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







|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2021, 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 https://curl.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
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
    failf(data, "gsk_attribute_set_callback(): %s", gsk_strerror(rc));
    break;
  }
  return CURLE_SSL_CONNECT_ERROR;
}


static CURLcode set_ciphers(struct connectdata *conn,
                                        gsk_handle h, unsigned int *protoflags)
{
  struct Curl_easy *data = conn->data;
  const char *cipherlist = SSL_CONN_CONFIG(cipher_list);
  const char *clp;
  const struct gskit_cipher *ctp;
  int i;
  int l;
  bool unsupported;
  CURLcode result;







|


<







297
298
299
300
301
302
303
304
305
306

307
308
309
310
311
312
313
    failf(data, "gsk_attribute_set_callback(): %s", gsk_strerror(rc));
    break;
  }
  return CURLE_SSL_CONNECT_ERROR;
}


static CURLcode set_ciphers(struct Curl_easy *data,
                                        gsk_handle h, unsigned int *protoflags)
{

  const char *cipherlist = SSL_CONN_CONFIG(cipher_list);
  const char *clp;
  const struct gskit_cipher *ctp;
  int i;
  int l;
  bool unsupported;
  CURLcode result;
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
  for(i = 0; i < CURL_GSKPROTO_LAST; i++)
    free(ciphers[i].buf);

  return result;
}


static int Curl_gskit_init(void)
{
  /* No initialisation needed. */

  return 1;
}


static void Curl_gskit_cleanup(void)
{
  /* Nothing to do. */
}


static CURLcode init_environment(struct Curl_easy *data,
                                 gsk_handle *envir, const char *appid,







|







|







430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
  for(i = 0; i < CURL_GSKPROTO_LAST; i++)
    free(ciphers[i].buf);

  return result;
}


static int gskit_init(void)
{
  /* No initialisation needed. */

  return 1;
}


static void gskit_cleanup(void)
{
  /* Nothing to do. */
}


static CURLcode init_environment(struct Curl_easy *data,
                                 gsk_handle *envir, const char *appid,
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616

617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641

642
643
644
645
646
647
648
649
650
    }
  }

  return ret;  /* OK */
}


static void close_one(struct ssl_connect_data *connssl,
                      struct connectdata *conn, int sockindex)
{
  if(BACKEND->handle) {
    gskit_status(conn->data, gsk_secure_soc_close(&BACKEND->handle),
              "gsk_secure_soc_close()", 0);
    /* Last chance to drain output. */
    while(pipe_ssloverssl(conn, sockindex, SOS_WRITE) > 0)
      ;
    BACKEND->handle = (gsk_handle) NULL;
    if(BACKEND->localfd >= 0) {
      close(BACKEND->localfd);
      BACKEND->localfd = -1;
    }
    if(BACKEND->remotefd >= 0) {
      close(BACKEND->remotefd);
      BACKEND->remotefd = -1;
    }
  }
  if(BACKEND->iocport >= 0)
    close_async_handshake(connssl);
}


static ssize_t gskit_send(struct connectdata *conn, int sockindex,
                           const void *mem, size_t len, CURLcode *curlcode)
{

  struct ssl_connect_data *connssl = &conn->ssl[sockindex];
  struct Curl_easy *data = conn->data;
  CURLcode cc = CURLE_SEND_ERROR;
  int written;

  if(pipe_ssloverssl(conn, sockindex, SOS_WRITE) >= 0) {
    cc = gskit_status(data,
                      gsk_secure_soc_write(BACKEND->handle,
                                           (char *) mem, (int) len, &written),
                      "gsk_secure_soc_write()", CURLE_SEND_ERROR);
    if(cc == CURLE_OK)
      if(pipe_ssloverssl(conn, sockindex, SOS_WRITE) < 0)
        cc = 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 ssl_connect_data *connssl = &conn->ssl[num];
  struct Curl_easy *data = conn->data;
  int nread;
  CURLcode cc = CURLE_RECV_ERROR;

  if(pipe_ssloverssl(conn, num, SOS_READ) >= 0) {
    int buffsize = buffersize > (size_t) INT_MAX? INT_MAX: (int) buffersize;
    cc = gskit_status(data, gsk_secure_soc_read(BACKEND->handle,
                                                buf, buffsize, &nread),







|



|




















|

>

<




















|
|

>

<







582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617

618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642

643
644
645
646
647
648
649
    }
  }

  return ret;  /* OK */
}


static void close_one(struct ssl_connect_data *connssl, struct Curl_easy *data,
                      struct connectdata *conn, int sockindex)
{
  if(BACKEND->handle) {
    gskit_status(data, gsk_secure_soc_close(&BACKEND->handle),
              "gsk_secure_soc_close()", 0);
    /* Last chance to drain output. */
    while(pipe_ssloverssl(conn, sockindex, SOS_WRITE) > 0)
      ;
    BACKEND->handle = (gsk_handle) NULL;
    if(BACKEND->localfd >= 0) {
      close(BACKEND->localfd);
      BACKEND->localfd = -1;
    }
    if(BACKEND->remotefd >= 0) {
      close(BACKEND->remotefd);
      BACKEND->remotefd = -1;
    }
  }
  if(BACKEND->iocport >= 0)
    close_async_handshake(connssl);
}


static ssize_t gskit_send(struct connectdata *conn, int sockindex,
                          const void *mem, size_t len, CURLcode *curlcode)
{
  struct connectdata *conn = data->conn;
  struct ssl_connect_data *connssl = &conn->ssl[sockindex];

  CURLcode cc = CURLE_SEND_ERROR;
  int written;

  if(pipe_ssloverssl(conn, sockindex, SOS_WRITE) >= 0) {
    cc = gskit_status(data,
                      gsk_secure_soc_write(BACKEND->handle,
                                           (char *) mem, (int) len, &written),
                      "gsk_secure_soc_write()", CURLE_SEND_ERROR);
    if(cc == CURLE_OK)
      if(pipe_ssloverssl(conn, sockindex, SOS_WRITE) < 0)
        cc = CURLE_SEND_ERROR;
  }
  if(cc != CURLE_OK) {
    *curlcode = cc;
    written = -1;
  }
  return (ssize_t) written; /* number of bytes */
}


static ssize_t gskit_recv(struct Curl_easy *data, int num, char *buf,
                               size_t buffersize, CURLcode *curlcode)
{
  struct connectdata *conn = data->conn;
  struct ssl_connect_data *connssl = &conn->ssl[num];

  int nread;
  CURLcode cc = CURLE_RECV_ERROR;

  if(pipe_ssloverssl(conn, num, SOS_READ) >= 0) {
    int buffsize = buffersize > (size_t) INT_MAX? INT_MAX: (int) buffersize;
    cc = gskit_status(data, gsk_secure_soc_read(BACKEND->handle,
                                                buf, buffsize, &nread),
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
    nread = -1;
    break;
  }
  return (ssize_t) nread;
}

static CURLcode
set_ssl_version_min_max(unsigned int *protoflags, struct connectdata *conn)
{
  struct Curl_easy *data = conn->data;
  long ssl_version = SSL_CONN_CONFIG(version);
  long ssl_version_max = SSL_CONN_CONFIG(version_max);
  long i = ssl_version;
  switch(ssl_version_max) {
    case CURL_SSLVERSION_MAX_NONE:
    case CURL_SSLVERSION_MAX_DEFAULT:
      ssl_version_max = CURL_SSLVERSION_TLSv1_2;







|

<







659
660
661
662
663
664
665
666
667

668
669
670
671
672
673
674
    nread = -1;
    break;
  }
  return (ssize_t) nread;
}

static CURLcode
set_ssl_version_min_max(unsigned int *protoflags, struct Curl_easy *data)
{

  long ssl_version = SSL_CONN_CONFIG(version);
  long ssl_version_max = SSL_CONN_CONFIG(version_max);
  long i = ssl_version;
  switch(ssl_version_max) {
    case CURL_SSLVERSION_MAX_NONE:
    case CURL_SSLVERSION_MAX_DEFAULT:
      ssl_version_max = CURL_SSLVERSION_TLSv1_2;
692
693
694
695
696
697
698
699

700
701
702
703
704
705
706
707
708
        return CURLE_SSL_CONNECT_ERROR;
    }
  }

  return CURLE_OK;
}

static CURLcode gskit_connect_step1(struct connectdata *conn, int sockindex)

{
  struct Curl_easy *data = conn->data;
  struct ssl_connect_data *connssl = &conn->ssl[sockindex];
  gsk_handle envir;
  CURLcode result;
  int rc;
  const char * const keyringfile = SSL_CONN_CONFIG(CAfile);
  const char * const keyringpwd = SSL_SET_OPTION(key_passwd);
  const char * const keyringlabel = SSL_SET_OPTION(primary.clientcert);







|
>

<







690
691
692
693
694
695
696
697
698
699

700
701
702
703
704
705
706
        return CURLE_SSL_CONNECT_ERROR;
    }
  }

  return CURLE_OK;
}

static CURLcode gskit_connect_step1(struct Curl_easy *data,
                                    struct connectdata *conn, int sockindex)
{

  struct ssl_connect_data *connssl = &conn->ssl[sockindex];
  gsk_handle envir;
  CURLcode result;
  int rc;
  const char * const keyringfile = SSL_CONN_CONFIG(CAfile);
  const char * const keyringpwd = SSL_SET_OPTION(key_passwd);
  const char * const keyringlabel = SSL_SET_OPTION(primary.clientcert);
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
    protoflags = CURL_GSKPROTO_TLSV10_MASK |
                 CURL_GSKPROTO_TLSV11_MASK | CURL_GSKPROTO_TLSV12_MASK;
    break;
  case CURL_SSLVERSION_TLSv1_0:
  case CURL_SSLVERSION_TLSv1_1:
  case CURL_SSLVERSION_TLSv1_2:
  case CURL_SSLVERSION_TLSv1_3:
    result = set_ssl_version_min_max(&protoflags, conn);
    if(result != CURLE_OK)
      return result;
    break;
  default:
    failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION");
    return CURLE_SSL_CONNECT_ERROR;
  }







|







792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
    protoflags = CURL_GSKPROTO_TLSV10_MASK |
                 CURL_GSKPROTO_TLSV11_MASK | CURL_GSKPROTO_TLSV12_MASK;
    break;
  case CURL_SSLVERSION_TLSv1_0:
  case CURL_SSLVERSION_TLSv1_1:
  case CURL_SSLVERSION_TLSv1_2:
  case CURL_SSLVERSION_TLSv1_3:
    result = set_ssl_version_min_max(&protoflags, data);
    if(result != CURLE_OK)
      return result;
    break;
  default:
    failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION");
    return CURLE_SSL_CONNECT_ERROR;
  }
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
  }
  if(!result)
    result = set_numeric(data, BACKEND->handle, GSK_OS400_READ_TIMEOUT, 1);
  if(!result)
    result = set_numeric(data, BACKEND->handle, GSK_FD, BACKEND->localfd >= 0?
                         BACKEND->localfd: conn->sock[sockindex]);
  if(!result)
    result = set_ciphers(conn, BACKEND->handle, &protoflags);
  if(!protoflags) {
    failf(data, "No SSL protocol/cipher combination enabled");
    result = CURLE_SSL_CIPHER;
  }
  if(!result)
    result = set_enum(data, BACKEND->handle, GSK_PROTOCOL_SSLV2,
                      (protoflags & CURL_GSKPROTO_SSLV2_MASK)?







|







826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
  }
  if(!result)
    result = set_numeric(data, BACKEND->handle, GSK_OS400_READ_TIMEOUT, 1);
  if(!result)
    result = set_numeric(data, BACKEND->handle, GSK_FD, BACKEND->localfd >= 0?
                         BACKEND->localfd: conn->sock[sockindex]);
  if(!result)
    result = set_ciphers(data, BACKEND->handle, &protoflags);
  if(!protoflags) {
    failf(data, "No SSL protocol/cipher combination enabled");
    result = CURLE_SSL_CIPHER;
  }
  if(!result)
    result = set_enum(data, BACKEND->handle, GSK_PROTOCOL_SSLV2,
                      (protoflags & CURL_GSKPROTO_SSLV2_MASK)?
911
912
913
914
915
916
917
918
919
920
921
922
923

924
925
926
927
928
929
930
931
932
933
        connssl->connecting_state = ssl_connect_3;
        return CURLE_OK;
      }
    }
  }

  /* Error: rollback. */
  close_one(connssl, conn, sockindex);
  return result;
}


static CURLcode gskit_connect_step2(struct connectdata *conn, int sockindex,

                                    bool nonblocking)
{
  struct Curl_easy *data = conn->data;
  struct ssl_connect_data *connssl = &conn->ssl[sockindex];
  Qso_OverlappedIO_t cstat;
  struct timeval stmv;
  CURLcode result;

  /* Poll or wait for end of SSL asynchronous handshake. */








|




|
>


<







909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924

925
926
927
928
929
930
931
        connssl->connecting_state = ssl_connect_3;
        return CURLE_OK;
      }
    }
  }

  /* Error: rollback. */
  close_one(connssl, data, conn, sockindex);
  return result;
}


static CURLcode gskit_connect_step2(struct Curl_easy *data,
                                    struct connectdata *conn, int sockindex,
                                    bool nonblocking)
{

  struct ssl_connect_data *connssl = &conn->ssl[sockindex];
  Qso_OverlappedIO_t cstat;
  struct timeval stmv;
  CURLcode result;

  /* Poll or wait for end of SSL asynchronous handshake. */

967
968
969
970
971
972
973
974

975
976
977
978
979
980
981
982
983
  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 Curl_easy *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;







|
>

<







965
966
967
968
969
970
971
972
973
974

975
976
977
978
979
980
981
  if(!result)
    connssl->connecting_state = ssl_connect_3;
  close_async_handshake(connssl);
  return result;
}


static CURLcode gskit_connect_step3(struct Curl_easy *data,
                                    struct connectdata *conn, int sockindex)
{

  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;
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
      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 = SSL_IS_PROXY() ? data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY] :







|














|







1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
      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(data, 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(data, 0, cert, certend);
      if(result)
        return result;
    }
  }

  /* Check pinned public key. */
  ptr = SSL_IS_PROXY() ? data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY] :
1055
1056
1057
1058
1059
1060
1061
1062

1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129

1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141

1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157

1158
1159
1160
1161
1162
1163
1164

1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
  }

  connssl->connecting_state = ssl_connect_done;
  return CURLE_OK;
}


static CURLcode gskit_connect_common(struct connectdata *conn, int sockindex,

                                     bool nonblocking, bool *done)
{
  struct Curl_easy *data = conn->data;
  struct ssl_connect_data *connssl = &conn->ssl[sockindex];
  timediff_t timeout_ms;
  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);
  }

  /* Handle handshake pipelining. */
  if(!result)
    if(pipe_ssloverssl(conn, sockindex, SOS_READ | SOS_WRITE) < 0)
      result = CURLE_SSL_CONNECT_ERROR;

  /* 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);
  }

  /* Handle handshake pipelining. */
  if(!result)
    if(pipe_ssloverssl(conn, sockindex, SOS_READ | SOS_WRITE) < 0)
      result = CURLE_SSL_CONNECT_ERROR;

  /* 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, conn, sockindex);
  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;
}



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;
}



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;
}



static void Curl_gskit_close(struct connectdata *conn, int sockindex)
{
  close_one(&conn->ssl[sockindex], conn, sockindex);
  close_one(&conn->proxy_ssl[sockindex], conn, sockindex);
}



static int Curl_gskit_shutdown(struct connectdata *conn, int sockindex)
{
  struct ssl_connect_data *connssl = &conn->ssl[sockindex];
  struct Curl_easy *data = conn->data;
  int what;
  int rc;
  char buf[120];

  if(!BACKEND->handle)
    return 0;

#ifndef CURL_DISABLE_FTP
  if(data->set.ftp_ccc != CURLFTPSSL_CCC_ACTIVE)
    return 0;
#endif

  close_one(connssl, conn, sockindex);
  rc = 0;
  what = SOCKET_READABLE(conn->sock[sockindex],
                         SSL_SHUTDOWN_TIMEOUT);

  for(;;) {
    ssize_t nread;








|
>


<



















|


















|









|


|












>
|
|



|






>
|





|









>
|

|
|



>
|


<












|







1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063

1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169

1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
  }

  connssl->connecting_state = ssl_connect_done;
  return CURLE_OK;
}


static CURLcode gskit_connect_common(struct Curl_easy *data,
                                     struct connectdata *conn, int sockindex,
                                     bool nonblocking, bool *done)
{

  struct ssl_connect_data *connssl = &conn->ssl[sockindex];
  timediff_t timeout_ms;
  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(data, conn, sockindex);
  }

  /* Handle handshake pipelining. */
  if(!result)
    if(pipe_ssloverssl(conn, sockindex, SOS_READ | SOS_WRITE) < 0)
      result = CURLE_SSL_CONNECT_ERROR;

  /* 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(data, conn, sockindex, nonblocking);
  }

  /* Handle handshake pipelining. */
  if(!result)
    if(pipe_ssloverssl(conn, sockindex, SOS_READ | SOS_WRITE) < 0)
      result = CURLE_SSL_CONNECT_ERROR;

  /* Step 3: gather certificate info, verify host. */
  if(!result && connssl->connecting_state == ssl_connect_3)
    result = gskit_connect_step3(data, conn, sockindex);

  if(result)
    close_one(connssl, data, conn, sockindex);
  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;
}


static CURLcode gskit_connect_nonblocking(struct Curl_easy *data,
                                          struct connectdata *conn,
                                          int sockindex, bool *done)
{
  CURLcode result;

  result = gskit_connect_common(data, conn, sockindex, TRUE, done);
  if(*done || result)
    conn->ssl[sockindex].connecting_state = ssl_connect_1;
  return result;
}


static CURLcode gskit_connect(struct Curl_easy *data,
                              struct connectdata *conn, int sockindex)
{
  CURLcode result;
  bool done;

  conn->ssl[sockindex].connecting_state = ssl_connect_1;
  result = gskit_connect_common(data, conn, sockindex, FALSE, &done);
  if(result)
    return result;

  DEBUGASSERT(done);

  return CURLE_OK;
}


static void gskit_close(struct Curl_easy *data, struct connectdata *conn,
                        int sockindex)
{
  close_one(&conn->ssl[sockindex], data, conn, sockindex);
  close_one(&conn->proxy_ssl[sockindex], data, conn, sockindex);
}


static int gskit_shutdown(struct Curl_easy *data,
                          struct connectdata *conn, int sockindex)
{
  struct ssl_connect_data *connssl = &conn->ssl[sockindex];

  int what;
  int rc;
  char buf[120];

  if(!BACKEND->handle)
    return 0;

#ifndef CURL_DISABLE_FTP
  if(data->set.ftp_ccc != CURLFTPSSL_CCC_ACTIVE)
    return 0;
#endif

  close_one(connssl, data, conn, sockindex);
  rc = 0;
  what = SOCKET_READABLE(conn->sock[sockindex],
                         SSL_SHUTDOWN_TIMEOUT);

  for(;;) {
    ssize_t nread;

1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
    what = SOCKET_READABLE(conn->sock[sockindex], 0);
  }

  return rc;
}


static size_t Curl_gskit_version(char *buffer, size_t size)
{
  return msnprintf(buffer, size, "GSKit");
}


static int Curl_gskit_check_cxn(struct connectdata *cxn)
{
  struct ssl_connect_data *connssl = &cxn->ssl[FIRSTSOCKET];
  int err;
  int errlen;

  /* The only thing that can be tested here is at the socket level. */








|





|







1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
    what = SOCKET_READABLE(conn->sock[sockindex], 0);
  }

  return rc;
}


static size_t gskit_version(char *buffer, size_t size)
{
  return msnprintf(buffer, size, "GSKit");
}


static int gskit_check_cxn(struct connectdata *cxn)
{
  struct ssl_connect_data *connssl = &cxn->ssl[FIRSTSOCKET];
  int err;
  int errlen;

  /* The only thing that can be tested here is at the socket level. */

1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
                 (unsigned char *) &err, &errlen) ||
     errlen != sizeof(err) || err)
    return 0; /* connection has been closed */

  return -1;  /* connection status unknown */
}

static void *Curl_gskit_get_internals(struct ssl_connect_data *connssl,
                                      CURLINFO info UNUSED_PARAM)
{
  (void)info;
  return BACKEND->handle;
}

const struct Curl_ssl Curl_ssl_gskit = {
  { CURLSSLBACKEND_GSKIT, "gskit" }, /* info */

  SSLSUPP_CERTINFO |
  SSLSUPP_PINNEDPUBKEY,

  sizeof(struct ssl_backend_data),

  Curl_gskit_init,                /* init */
  Curl_gskit_cleanup,             /* cleanup */
  Curl_gskit_version,             /* version */
  Curl_gskit_check_cxn,           /* check_cxn */
  Curl_gskit_shutdown,            /* shutdown */
  Curl_none_data_pending,         /* data_pending */
  Curl_none_random,               /* random */
  Curl_none_cert_status_request,  /* cert_status_request */
  Curl_gskit_connect,             /* connect */
  Curl_gskit_connect_nonblocking, /* connect_nonblocking */
  Curl_gskit_get_internals,       /* get_internals */
  Curl_gskit_close,               /* close_one */
  Curl_none_close_all,            /* close_all */
  /* No session handling for GSKit */
  Curl_none_session_free,         /* session_free */
  Curl_none_set_engine,           /* set_engine */
  Curl_none_set_engine_default,   /* set_engine_default */
  Curl_none_engines_list,         /* engines_list */
  Curl_none_false_start,          /* false_start */
  Curl_none_md5sum,               /* md5sum */
  NULL                            /* sha256sum */
};

#endif /* USE_GSKIT */







|
|













|
|
|
|
|



|
|
|
|







<




1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284

1285
1286
1287
1288
                 (unsigned char *) &err, &errlen) ||
     errlen != sizeof(err) || err)
    return 0; /* connection has been closed */

  return -1;  /* connection status unknown */
}

static void *gskit_get_internals(struct ssl_connect_data *connssl,
                                 CURLINFO info UNUSED_PARAM)
{
  (void)info;
  return BACKEND->handle;
}

const struct Curl_ssl Curl_ssl_gskit = {
  { CURLSSLBACKEND_GSKIT, "gskit" }, /* info */

  SSLSUPP_CERTINFO |
  SSLSUPP_PINNEDPUBKEY,

  sizeof(struct ssl_backend_data),

  gskit_init,                     /* init */
  gskit_cleanup,                  /* cleanup */
  gskit_version,                  /* version */
  gskit_check_cxn,                /* check_cxn */
  gskit_shutdown,                 /* shutdown */
  Curl_none_data_pending,         /* data_pending */
  Curl_none_random,               /* random */
  Curl_none_cert_status_request,  /* cert_status_request */
  gskit_connect,                  /* connect */
  gskit_connect_nonblocking,      /* connect_nonblocking */
  gskit_get_internals,            /* get_internals */
  gskit_close,                    /* close_one */
  Curl_none_close_all,            /* close_all */
  /* No session handling for GSKit */
  Curl_none_session_free,         /* session_free */
  Curl_none_set_engine,           /* set_engine */
  Curl_none_set_engine_default,   /* set_engine_default */
  Curl_none_engines_list,         /* engines_list */
  Curl_none_false_start,          /* false_start */

  NULL                            /* sha256sum */
};

#endif /* USE_GSKIT */
Changes to jni/curl/lib/vtls/gtls.c.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2020, 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 https://curl.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







|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2021, 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 https://curl.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
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
  gnutls_session_t session;
  gnutls_certificate_credentials_t cred;
#ifdef HAVE_GNUTLS_SRP
  gnutls_srp_client_credentials_t srp_client_cred;
#endif
};

static ssize_t Curl_gtls_push(void *s, const void *buf, size_t len)
{
  curl_socket_t sock = *(curl_socket_t *)s;
  ssize_t ret = swrite(sock, buf, len);
  return ret;
}

static ssize_t Curl_gtls_pull(void *s, void *buf, size_t len)
{
  curl_socket_t sock = *(curl_socket_t *)s;
  ssize_t ret = sread(sock, buf, len);
  return ret;
}

static ssize_t Curl_gtls_push_ssl(void *s, const void *buf, size_t len)
{
  return gnutls_record_send((gnutls_session_t) s, buf, len);
}

static ssize_t Curl_gtls_pull_ssl(void *s, void *buf, size_t len)
{
  return gnutls_record_recv((gnutls_session_t) s, buf, len);
}

/* 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!
 */
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;
}

static void Curl_gtls_cleanup(void)
{
  if(gtls_inited) {
    gnutls_global_deinit();
    gtls_inited = FALSE;
  }
}








|






|






|




|




|






|













|







82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
  gnutls_session_t session;
  gnutls_certificate_credentials_t cred;
#ifdef HAVE_GNUTLS_SRP
  gnutls_srp_client_credentials_t srp_client_cred;
#endif
};

static ssize_t gtls_push(void *s, const void *buf, size_t len)
{
  curl_socket_t sock = *(curl_socket_t *)s;
  ssize_t ret = swrite(sock, buf, len);
  return ret;
}

static ssize_t gtls_pull(void *s, void *buf, size_t len)
{
  curl_socket_t sock = *(curl_socket_t *)s;
  ssize_t ret = sread(sock, buf, len);
  return ret;
}

static ssize_t gtls_push_ssl(void *s, const void *buf, size_t len)
{
  return gnutls_record_send((gnutls_session_t) s, buf, len);
}

static ssize_t gtls_pull_ssl(void *s, void *buf, size_t len)
{
  return gnutls_record_recv((gnutls_session_t) s, buf, len);
}

/* 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!
 */
static int 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;
}

static void gtls_cleanup(void)
{
  if(gtls_inited) {
    gnutls_global_deinit();
    gtls_inited = FALSE;
  }
}

196
197
198
199
200
201
202
203

204
205
206
207
208
209
210
211
212
213
214
215
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 Curl_easy *data = conn->data;
  struct ssl_connect_data *connssl = &conn->ssl[sockindex];
  struct ssl_backend_data *backend = connssl->backend;
  gnutls_session_t session = backend->session;
  curl_socket_t sockfd = conn->sock[sockindex];

  for(;;) {
    timediff_t timeout_ms;







|
>




<







196
197
198
199
200
201
202
203
204
205
206
207
208

209
210
211
212
213
214
215
static void unload_file(gnutls_datum_t data)
{
  free(data.data);
}


/* this function does a SSL/TLS (re-)handshake */
static CURLcode handshake(struct Curl_easy *data,
                          struct connectdata *conn,
                          int sockindex,
                          bool duringconnect,
                          bool nonblocking)
{

  struct ssl_connect_data *connssl = &conn->ssl[sockindex];
  struct ssl_backend_data *backend = connssl->backend;
  gnutls_session_t session = backend->session;
  curl_socket_t sockfd = conn->sock[sockindex];

  for(;;) {
    timediff_t timeout_ms;
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
#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"

static CURLcode
set_ssl_version_min_max(const char **prioritylist, struct connectdata *conn)
{
  struct Curl_easy *data = conn->data;
  long ssl_version = SSL_CONN_CONFIG(version);
  long ssl_version_max = SSL_CONN_CONFIG(version_max);

  if(ssl_version_max == CURL_SSLVERSION_MAX_NONE) {
    ssl_version_max = CURL_SSLVERSION_MAX_DEFAULT;
  }
  switch(ssl_version | ssl_version_max) {







|

|







310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
#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"

static CURLcode
set_ssl_version_min_max(const char **prioritylist, struct Curl_easy *data)
{
  struct connectdata *conn = data->conn;
  long ssl_version = SSL_CONN_CONFIG(version);
  long ssl_version_max = SSL_CONN_CONFIG(version_max);

  if(ssl_version_max == CURL_SSLVERSION_MAX_NONE) {
    ssl_version_max = CURL_SSLVERSION_MAX_DEFAULT;
  }
  switch(ssl_version | ssl_version_max) {
375
376
377
378
379
380
381
382

383
384
385
386
387
388
389
390
391
392
  }

  failf(data, "GnuTLS: cannot set ssl protocol");
  return CURLE_SSL_CONNECT_ERROR;
}

static CURLcode
gtls_connect_step1(struct connectdata *conn,

                   int sockindex)
{
  struct Curl_easy *data = conn->data;
  struct ssl_connect_data *connssl = &conn->ssl[sockindex];
  struct ssl_backend_data *backend = connssl->backend;
  unsigned int init_flags;
  gnutls_session_t session;
  int rc;
  bool sni = TRUE; /* default is SNI enabled */
  void *transport_ptr = NULL;







|
>


<







375
376
377
378
379
380
381
382
383
384
385

386
387
388
389
390
391
392
  }

  failf(data, "GnuTLS: cannot set ssl protocol");
  return CURLE_SSL_CONNECT_ERROR;
}

static CURLcode
gtls_connect_step1(struct Curl_easy *data,
                   struct connectdata *conn,
                   int sockindex)
{

  struct ssl_connect_data *connssl = &conn->ssl[sockindex];
  struct ssl_backend_data *backend = connssl->backend;
  unsigned int init_flags;
  gnutls_session_t session;
  int rc;
  bool sni = TRUE; /* default is SNI enabled */
  void *transport_ptr = NULL;
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418

  if(connssl->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();

  /* Initialize certverifyresult to OK */
  *certverifyresult = 0;

  if(SSL_CONN_CONFIG(version) == CURL_SSLVERSION_SSLv2) {
    failf(data, "GnuTLS does not support SSLv2");
    return CURLE_SSL_CONNECT_ERROR;







|







404
405
406
407
408
409
410
411
412
413
414
415
416
417
418

  if(connssl->state == ssl_connection_complete)
    /* to make us tolerant against being called more than once for the
       same connection */
    return CURLE_OK;

  if(!gtls_inited)
    gtls_init();

  /* Initialize certverifyresult to OK */
  *certverifyresult = 0;

  if(SSL_CONN_CONFIG(version) == CURL_SSLVERSION_SSLv2) {
    failf(data, "GnuTLS does not support SSLv2");
    return CURLE_SSL_CONNECT_ERROR;
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
                     ;
      break;
    case CURL_SSLVERSION_TLSv1_0:
    case CURL_SSLVERSION_TLSv1_1:
    case CURL_SSLVERSION_TLSv1_2:
    case CURL_SSLVERSION_TLSv1_3:
      {
        CURLcode result = set_ssl_version_min_max(&prioritylist, conn);
        if(result != CURLE_OK)
          return result;
        break;
      }
    case CURL_SSLVERSION_SSLv2:
      failf(data, "GnuTLS does not support SSLv2");
      return CURLE_SSL_CONNECT_ERROR;







|







564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
                     ;
      break;
    case CURL_SSLVERSION_TLSv1_0:
    case CURL_SSLVERSION_TLSv1_1:
    case CURL_SSLVERSION_TLSv1_2:
    case CURL_SSLVERSION_TLSv1_3:
      {
        CURLcode result = set_ssl_version_min_max(&prioritylist, data);
        if(result != CURLE_OK)
          return result;
        break;
      }
    case CURL_SSLVERSION_SSLv2:
      failf(data, "GnuTLS does not support SSLv2");
      return CURLE_SSL_CONNECT_ERROR;
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
      return CURLE_SSL_CONNECT_ERROR;
    }
  }

#ifndef CURL_DISABLE_PROXY
  if(conn->proxy_ssl[sockindex].use) {
    transport_ptr = conn->proxy_ssl[sockindex].backend->session;
    gnutls_transport_push = Curl_gtls_push_ssl;
    gnutls_transport_pull = Curl_gtls_pull_ssl;
  }
  else
#endif
  {
    /* file descriptor for the socket */
    transport_ptr = &conn->sock[sockindex];
    gnutls_transport_push = Curl_gtls_push;
    gnutls_transport_pull = Curl_gtls_pull;
  }

  /* set the connection handle */
  gnutls_transport_set_ptr(session, transport_ptr);

  /* register callback functions to send and receive data. */
  gnutls_transport_set_push_function(session, gnutls_transport_push);







|
|






|
|







694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
      return CURLE_SSL_CONNECT_ERROR;
    }
  }

#ifndef CURL_DISABLE_PROXY
  if(conn->proxy_ssl[sockindex].use) {
    transport_ptr = conn->proxy_ssl[sockindex].backend->session;
    gnutls_transport_push = gtls_push_ssl;
    gnutls_transport_pull = gtls_pull_ssl;
  }
  else
#endif
  {
    /* file descriptor for the socket */
    transport_ptr = &conn->sock[sockindex];
    gnutls_transport_push = gtls_push;
    gnutls_transport_pull = gtls_pull;
  }

  /* set the connection handle */
  gnutls_transport_set_ptr(session, transport_ptr);

  /* register callback functions to send and receive data. */
  gnutls_transport_set_push_function(session, gnutls_transport_push);
727
728
729
730
731
732
733
734

735
736
737
738
739
740
741
742
743
744
745
746
747
748
749

  /* This might be a reconnect, so we check for a session ID in the cache
     to speed up things */
  if(SSL_SET_OPTION(primary.sessionid)) {
    void *ssl_sessionid;
    size_t ssl_idsize;

    Curl_ssl_sessionid_lock(conn);

    if(!Curl_ssl_getsessionid(conn, &ssl_sessionid, &ssl_idsize, sockindex)) {
      /* 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");
    }
    Curl_ssl_sessionid_unlock(conn);
  }

  return CURLE_OK;
}

static CURLcode pkp_pin_peer_pubkey(struct Curl_easy *data,
                                    gnutls_x509_crt_t cert,







|
>
|






|







727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750

  /* This might be a reconnect, so we check for a session ID in the cache
     to speed up things */
  if(SSL_SET_OPTION(primary.sessionid)) {
    void *ssl_sessionid;
    size_t ssl_idsize;

    Curl_ssl_sessionid_lock(data);
    if(!Curl_ssl_getsessionid(data, conn,
                              &ssl_sessionid, &ssl_idsize, sockindex)) {
      /* 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");
    }
    Curl_ssl_sessionid_unlock(data);
  }

  return CURLE_OK;
}

static CURLcode pkp_pin_peer_pubkey(struct Curl_easy *data,
                                    gnutls_x509_crt_t cert,
803
804
805
806
807
808
809
810

811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
  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;
  gnutls_datum_t certfields;
  char certname[65] = ""; /* limited to 64 chars by ASN.1 */
  size_t size;
  time_t certclock;
  const char *ptr;
  struct Curl_easy *data = conn->data;
  struct ssl_connect_data *connssl = &conn->ssl[sockindex];
  struct ssl_backend_data *backend = connssl->backend;
  gnutls_session_t session = backend->session;
  int rc;
  gnutls_datum_t proto;
  CURLcode result = CURLE_OK;
#ifndef CURL_DISABLE_VERBOSE_STRINGS







|
>












<







804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824

825
826
827
828
829
830
831
  return result;
}

static Curl_recv gtls_recv;
static Curl_send gtls_send;

static CURLcode
gtls_connect_step3(struct Curl_easy *data,
                   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;
  gnutls_datum_t certfields;
  char certname[65] = ""; /* limited to 64 chars by ASN.1 */
  size_t size;
  time_t certclock;
  const char *ptr;

  struct ssl_connect_data *connssl = &conn->ssl[sockindex];
  struct ssl_backend_data *backend = connssl->backend;
  gnutls_session_t session = backend->session;
  int rc;
  gnutls_datum_t proto;
  CURLcode result = CURLE_OK;
#ifndef CURL_DISABLE_VERBOSE_STRINGS
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
    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(SSL_CONN_CONFIG(verifypeer)) {
    /* This function will try to verify the peer's certificate and return its







|







882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
    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(data, i, beg, end);
      if(result)
        return result;
    }
  }

  if(SSL_CONN_CONFIG(verifypeer)) {
    /* This function will try to verify the peer's certificate and return its
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
         !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");

    Curl_multiuse_state(conn, conn->negnpn == CURL_HTTP_VERSION_2 ?
                        BUNDLE_MULTIPLEX : BUNDLE_NO_MULTIUSE);
  }

  conn->ssl[sockindex].state = ssl_connection_complete;
  conn->recv[sockindex] = gtls_recv;
  conn->send[sockindex] = gtls_send;








|







1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
         !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");

    Curl_multiuse_state(data, conn->negnpn == CURL_HTTP_VERSION_2 ?
                        BUNDLE_MULTIPLEX : BUNDLE_NO_MULTIUSE);
  }

  conn->ssl[sockindex].state = ssl_connection_complete;
  conn->recv[sockindex] = gtls_recv;
  conn->send[sockindex] = gtls_send;

1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
    if(connect_sessionid) {
      bool incache;
      void *ssl_sessionid;

      /* extract session ID to the allocated buffer */
      gnutls_session_get_data(session, connect_sessionid, &connect_idsize);

      Curl_ssl_sessionid_lock(conn);
      incache = !(Curl_ssl_getsessionid(conn, &ssl_sessionid, NULL,
                                        sockindex));
      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,
                                     sockindex);
      Curl_ssl_sessionid_unlock(conn);
      if(result) {
        free(connect_sessionid);
        result = CURLE_OUT_OF_MEMORY;
      }
    }
    else
      result = CURLE_OUT_OF_MEMORY;







|
|




|



|
|
|







1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
    if(connect_sessionid) {
      bool incache;
      void *ssl_sessionid;

      /* extract session ID to the allocated buffer */
      gnutls_session_get_data(session, connect_sessionid, &connect_idsize);

      Curl_ssl_sessionid_lock(data);
      incache = !(Curl_ssl_getsessionid(data, conn, &ssl_sessionid, NULL,
                                        sockindex));
      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(data, ssl_sessionid);
      }

      /* store this session id */
      result = Curl_ssl_addsessionid(data, conn, connect_sessionid,
                                     connect_idsize, sockindex);
      Curl_ssl_sessionid_unlock(data);
      if(result) {
        free(connect_sessionid);
        result = CURLE_OUT_OF_MEMORY;
      }
    }
    else
      result = CURLE_OUT_OF_MEMORY;
1322
1323
1324
1325
1326
1327
1328
1329

1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360

1361
1362
1363
1364
1365
1366

1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407

1408
1409
1410
1411
1412
1413
1414
 */
/* 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;
}


static CURLcode Curl_gtls_connect_nonblocking(struct connectdata *conn,
                                              int sockindex, bool *done)
{
  return gtls_connect_common(conn, sockindex, TRUE, done);
}


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 bool Curl_gtls_data_pending(const struct connectdata *conn,
                                   int connindex)
{
  const struct ssl_connect_data *connssl = &conn->ssl[connindex];
  bool res = FALSE;
  struct ssl_backend_data *backend = connssl->backend;
  if(backend->session &&
     0 != gnutls_record_check_pending(backend->session))
    res = TRUE;

#ifndef CURL_DISABLE_PROXY
  connssl = &conn->proxy_ssl[connindex];
  backend = connssl->backend;
  if(backend->session &&
     0 != gnutls_record_check_pending(backend->session))
    res = TRUE;
#endif

  return res;
}

static ssize_t gtls_send(struct connectdata *conn,
                         int sockindex,
                         const void *mem,
                         size_t len,
                         CURLcode *curlcode)
{

  struct ssl_connect_data *connssl = &conn->ssl[sockindex];
  struct ssl_backend_data *backend = connssl->backend;
  ssize_t rc = gnutls_record_send(backend->session, mem, len);

  if(rc < 0) {
    *curlcode = (rc == GNUTLS_E_AGAIN)
      ? CURLE_AGAIN







|
>









|




|






|









>
|
|

|


>
|




|








|
|



















|





>







1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
 */
/* 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 Curl_easy *data,
                    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(data, conn, sockindex);
    if(rc)
      return rc;
  }

  rc = handshake(data, 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(data, conn, sockindex);
    if(rc)
      return rc;
  }

  *done = ssl_connect_1 == connssl->connecting_state;

  return CURLE_OK;
}

static CURLcode gtls_connect_nonblocking(struct Curl_easy *data,
                                         struct connectdata *conn,
                                         int sockindex, bool *done)
{
  return gtls_connect_common(data, conn, sockindex, TRUE, done);
}

static CURLcode gtls_connect(struct Curl_easy *data, struct connectdata *conn,
                             int sockindex)
{
  CURLcode result;
  bool done = FALSE;

  result = gtls_connect_common(data, conn, sockindex, FALSE, &done);
  if(result)
    return result;

  DEBUGASSERT(done);

  return CURLE_OK;
}

static bool gtls_data_pending(const struct connectdata *conn,
                              int connindex)
{
  const struct ssl_connect_data *connssl = &conn->ssl[connindex];
  bool res = FALSE;
  struct ssl_backend_data *backend = connssl->backend;
  if(backend->session &&
     0 != gnutls_record_check_pending(backend->session))
    res = TRUE;

#ifndef CURL_DISABLE_PROXY
  connssl = &conn->proxy_ssl[connindex];
  backend = connssl->backend;
  if(backend->session &&
     0 != gnutls_record_check_pending(backend->session))
    res = TRUE;
#endif

  return res;
}

static ssize_t gtls_send(struct Curl_easy *data,
                         int sockindex,
                         const void *mem,
                         size_t len,
                         CURLcode *curlcode)
{
  struct connectdata *conn = data->conn;
  struct ssl_connect_data *connssl = &conn->ssl[sockindex];
  struct ssl_backend_data *backend = connssl->backend;
  ssize_t rc = gnutls_record_send(backend->session, mem, len);

  if(rc < 0) {
    *curlcode = (rc == GNUTLS_E_AGAIN)
      ? CURLE_AGAIN
1436
1437
1438
1439
1440
1441
1442

1443
1444

1445
1446
1447
1448
1449
1450
1451
1452
1453
1454

1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
  if(backend->srp_client_cred) {
    gnutls_srp_free_client_credentials(backend->srp_client_cred);
    backend->srp_client_cred = NULL;
  }
#endif
}


static void Curl_gtls_close(struct connectdata *conn, int sockindex)
{

  close_one(&conn->ssl[sockindex]);
#ifndef CURL_DISABLE_PROXY
  close_one(&conn->proxy_ssl[sockindex]);
#endif
}

/*
 * This function is called to shut down the SSL layer but keep the
 * socket open (CCC - Clear Command Channel)
 */

static int Curl_gtls_shutdown(struct connectdata *conn, int sockindex)
{
  struct ssl_connect_data *connssl = &conn->ssl[sockindex];
  struct ssl_backend_data *backend = connssl->backend;
  int retval = 0;
  struct Curl_easy *data = conn->data;

#ifndef CURL_DISABLE_FTP
  /* 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... */








>
|

>










>
|




<







1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467

1468
1469
1470
1471
1472
1473
1474
  if(backend->srp_client_cred) {
    gnutls_srp_free_client_credentials(backend->srp_client_cred);
    backend->srp_client_cred = NULL;
  }
#endif
}

static void gtls_close(struct Curl_easy *data, struct connectdata *conn,
                       int sockindex)
{
  (void) data;
  close_one(&conn->ssl[sockindex]);
#ifndef CURL_DISABLE_PROXY
  close_one(&conn->proxy_ssl[sockindex]);
#endif
}

/*
 * This function is called to shut down the SSL layer but keep the
 * socket open (CCC - Clear Command Channel)
 */
static int gtls_shutdown(struct Curl_easy *data, struct connectdata *conn,
                         int sockindex)
{
  struct ssl_connect_data *connssl = &conn->ssl[sockindex];
  struct ssl_backend_data *backend = connssl->backend;
  int retval = 0;


#ifndef CURL_DISABLE_FTP
  /* 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... */

1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534

1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698

  backend->cred = NULL;
  backend->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)
{

  struct ssl_connect_data *connssl = &conn->ssl[num];
  struct ssl_backend_data *backend = connssl->backend;
  ssize_t ret;

  ret = gnutls_record_recv(backend->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;
}

static void Curl_gtls_session_free(void *ptr)
{
  free(ptr);
}

static size_t Curl_gtls_version(char *buffer, size_t size)
{
  return msnprintf(buffer, size, "GnuTLS/%s", gnutls_check_version(NULL));
}

#ifndef USE_GNUTLS_NETTLE
static int Curl_gtls_seed(struct Curl_easy *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]) {
    ssl_seeded = TRUE;
  }
  return 0;
}
#endif

/* data might be NULL! */
static CURLcode Curl_gtls_random(struct Curl_easy *data,
                                 unsigned char *entropy, size_t length)
{
#if defined(USE_GNUTLS_NETTLE)
  int rc;
  (void)data;
  rc = gnutls_rnd(GNUTLS_RND_RANDOM, entropy, length);
  return rc?CURLE_FAILED_INIT:CURLE_OK;
#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 CURLE_OK;
}

static CURLcode 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
  return CURLE_OK;
}

static CURLcode Curl_gtls_sha256sum(const unsigned char *tmp, /* input */
                                size_t tmplen,
                                unsigned char *sha256sum, /* output */
                                size_t sha256len)
{
#if defined(USE_GNUTLS_NETTLE)
  struct sha256_ctx SHA256pw;
  sha256_init(&SHA256pw);
  sha256_update(&SHA256pw, (unsigned int)tmplen, tmp);
  sha256_digest(&SHA256pw, (unsigned int)sha256len, sha256sum);
#elif defined(USE_GNUTLS)
  gcry_md_hd_t SHA256pw;
  gcry_md_open(&SHA256pw, GCRY_MD_SHA256, 0);
  gcry_md_write(SHA256pw, tmp, tmplen);
  memcpy(sha256sum, gcry_md_read(SHA256pw, 0), sha256len);
  gcry_md_close(SHA256pw);
#endif
  return CURLE_OK;
}

static bool Curl_gtls_cert_status_request(void)
{
  return TRUE;
}

static void *Curl_gtls_get_internals(struct ssl_connect_data *connssl,
                                     CURLINFO info UNUSED_PARAM)
{
  struct ssl_backend_data *backend = connssl->backend;
  (void)info;
  return backend->session;
}

const struct Curl_ssl Curl_ssl_gnutls = {
  { CURLSSLBACKEND_GNUTLS, "gnutls" }, /* info */

  SSLSUPP_CA_PATH  |
  SSLSUPP_CERTINFO |
  SSLSUPP_PINNEDPUBKEY |
  SSLSUPP_HTTPS_PROXY,

  sizeof(struct ssl_backend_data),

  Curl_gtls_init,                /* init */
  Curl_gtls_cleanup,             /* cleanup */
  Curl_gtls_version,             /* version */
  Curl_none_check_cxn,           /* check_cxn */
  Curl_gtls_shutdown,            /* shutdown */
  Curl_gtls_data_pending,        /* data_pending */
  Curl_gtls_random,              /* random */
  Curl_gtls_cert_status_request, /* cert_status_request */
  Curl_gtls_connect,             /* connect */
  Curl_gtls_connect_nonblocking, /* connect_nonblocking */
  Curl_gtls_get_internals,       /* get_internals */
  Curl_gtls_close,               /* close_one */
  Curl_none_close_all,           /* close_all */
  Curl_gtls_session_free,        /* session_free */
  Curl_none_set_engine,          /* set_engine */
  Curl_none_set_engine_default,  /* set_engine_default */
  Curl_none_engines_list,        /* engines_list */
  Curl_none_false_start,         /* false_start */
  Curl_gtls_md5sum,              /* md5sum */
  Curl_gtls_sha256sum            /* sha256sum */
};

#endif /* USE_GNUTLS */







|





>













|









|









|




|





|

















|
|








|





<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
|
|
|
















|




|

















|
|
|

|
|
|
|
|
|
|
|

|




<
|



1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620




















1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681

1682
1683
1684
1685

  backend->cred = NULL;
  backend->session = NULL;

  return retval;
}

static ssize_t gtls_recv(struct Curl_easy *data, /* connection data */
                         int num,                  /* socketindex */
                         char *buf,                /* store read data here */
                         size_t buffersize,        /* max amount to read */
                         CURLcode *curlcode)
{
  struct connectdata *conn = data->conn;
  struct ssl_connect_data *connssl = &conn->ssl[num];
  struct ssl_backend_data *backend = connssl->backend;
  ssize_t ret;

  ret = gnutls_record_recv(backend->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(data, 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(data, "GnuTLS recv error (%d): %s",

          (int)ret, gnutls_strerror((int)ret));
    *curlcode = CURLE_RECV_ERROR;
    return -1;
  }

  return ret;
}

static void gtls_session_free(void *ptr)
{
  free(ptr);
}

static size_t gtls_version(char *buffer, size_t size)
{
  return msnprintf(buffer, size, "GnuTLS/%s", gnutls_check_version(NULL));
}

#ifndef USE_GNUTLS_NETTLE
static int gtls_seed(struct Curl_easy *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]) {
    ssl_seeded = TRUE;
  }
  return 0;
}
#endif

/* data might be NULL! */
static CURLcode gtls_random(struct Curl_easy *data,
                            unsigned char *entropy, size_t length)
{
#if defined(USE_GNUTLS_NETTLE)
  int rc;
  (void)data;
  rc = gnutls_rnd(GNUTLS_RND_RANDOM, entropy, length);
  return rc?CURLE_FAILED_INIT:CURLE_OK;
#elif defined(USE_GNUTLS)
  if(data)
    gtls_seed(data); /* Initiate the seed if not already done */
  gcry_randomize(entropy, length, GCRY_STRONG_RANDOM);
#endif
  return CURLE_OK;
}





















static CURLcode gtls_sha256sum(const unsigned char *tmp, /* input */
                               size_t tmplen,
                               unsigned char *sha256sum, /* output */
                               size_t sha256len)
{
#if defined(USE_GNUTLS_NETTLE)
  struct sha256_ctx SHA256pw;
  sha256_init(&SHA256pw);
  sha256_update(&SHA256pw, (unsigned int)tmplen, tmp);
  sha256_digest(&SHA256pw, (unsigned int)sha256len, sha256sum);
#elif defined(USE_GNUTLS)
  gcry_md_hd_t SHA256pw;
  gcry_md_open(&SHA256pw, GCRY_MD_SHA256, 0);
  gcry_md_write(SHA256pw, tmp, tmplen);
  memcpy(sha256sum, gcry_md_read(SHA256pw, 0), sha256len);
  gcry_md_close(SHA256pw);
#endif
  return CURLE_OK;
}

static bool gtls_cert_status_request(void)
{
  return TRUE;
}

static void *gtls_get_internals(struct ssl_connect_data *connssl,
                                     CURLINFO info UNUSED_PARAM)
{
  struct ssl_backend_data *backend = connssl->backend;
  (void)info;
  return backend->session;
}

const struct Curl_ssl Curl_ssl_gnutls = {
  { CURLSSLBACKEND_GNUTLS, "gnutls" }, /* info */

  SSLSUPP_CA_PATH  |
  SSLSUPP_CERTINFO |
  SSLSUPP_PINNEDPUBKEY |
  SSLSUPP_HTTPS_PROXY,

  sizeof(struct ssl_backend_data),

  gtls_init,                     /* init */
  gtls_cleanup,                  /* cleanup */
  gtls_version,                  /* version */
  Curl_none_check_cxn,           /* check_cxn */
  gtls_shutdown,                 /* shutdown */
  gtls_data_pending,             /* data_pending */
  gtls_random,                   /* random */
  gtls_cert_status_request,      /* cert_status_request */
  gtls_connect,                  /* connect */
  gtls_connect_nonblocking,      /* connect_nonblocking */
  gtls_get_internals,            /* get_internals */
  gtls_close,                    /* close_one */
  Curl_none_close_all,           /* close_all */
  gtls_session_free,             /* session_free */
  Curl_none_set_engine,          /* set_engine */
  Curl_none_set_engine_default,  /* set_engine_default */
  Curl_none_engines_list,        /* engines_list */
  Curl_none_false_start,         /* false_start */

  gtls_sha256sum                 /* sha256sum */
};

#endif /* USE_GNUTLS */
Changes to jni/curl/lib/vtls/mbedtls.c.
1
2
3
4
5
6
7

8
9
10
11
12
13
14
15
16
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *

 * Copyright (C) 2010 - 2011, Hoi-Ho Chan, <hoiho.chan@gmail.com>
 * Copyright (C) 2012 - 2020, 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 https://curl.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







>

<







1
2
3
4
5
6
7
8
9

10
11
12
13
14
15
16
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 2012 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
 * Copyright (C) 2010 - 2011, Hoi-Ho Chan, <hoiho.chan@gmail.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 https://curl.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
192
193
194
195
196
197
198
199

200
201
202
203
204
205
206
207
208
    case CURL_SSLVERSION_TLSv1_3:
      break;
  }
  return CURLE_SSL_CONNECT_ERROR;
}

static CURLcode
set_ssl_version_min_max(struct connectdata *conn, int sockindex)

{
  struct Curl_easy *data = conn->data;
  struct ssl_connect_data *connssl = &conn->ssl[sockindex];
  struct ssl_backend_data *backend = connssl->backend;
  int mbedtls_ver_min = MBEDTLS_SSL_MINOR_VERSION_1;
  int mbedtls_ver_max = MBEDTLS_SSL_MINOR_VERSION_1;
  long ssl_version = SSL_CONN_CONFIG(version);
  long ssl_version_max = SSL_CONN_CONFIG(version_max);
  CURLcode result = CURLE_OK;







|
>

<







192
193
194
195
196
197
198
199
200
201

202
203
204
205
206
207
208
    case CURL_SSLVERSION_TLSv1_3:
      break;
  }
  return CURLE_SSL_CONNECT_ERROR;
}

static CURLcode
set_ssl_version_min_max(struct Curl_easy *data, struct connectdata *conn,
                        int sockindex)
{

  struct ssl_connect_data *connssl = &conn->ssl[sockindex];
  struct ssl_backend_data *backend = connssl->backend;
  int mbedtls_ver_min = MBEDTLS_SSL_MINOR_VERSION_1;
  int mbedtls_ver_max = MBEDTLS_SSL_MINOR_VERSION_1;
  long ssl_version = SSL_CONN_CONFIG(version);
  long ssl_version_max = SSL_CONN_CONFIG(version_max);
  CURLcode result = CURLE_OK;
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
  mbedtls_ssl_conf_max_version(&backend->config, MBEDTLS_SSL_MAJOR_VERSION_3,
                               mbedtls_ver_max);

  return result;
}

static CURLcode
mbed_connect_step1(struct connectdata *conn,
                   int sockindex)
{
  struct Curl_easy *data = conn->data;
  struct ssl_connect_data *connssl = &conn->ssl[sockindex];
  struct ssl_backend_data *backend = connssl->backend;
  const char * const ssl_cafile = SSL_CONN_CONFIG(CAfile);
  const bool verifypeer = SSL_CONN_CONFIG(verifypeer);
  const char * const ssl_capath = SSL_CONN_CONFIG(CApath);
  char * const ssl_cert = SSL_SET_OPTION(primary.clientcert);
  const char * const ssl_crlfile = SSL_SET_OPTION(CRLfile);







|


<







237
238
239
240
241
242
243
244
245
246

247
248
249
250
251
252
253
  mbedtls_ssl_conf_max_version(&backend->config, MBEDTLS_SSL_MAJOR_VERSION_3,
                               mbedtls_ver_max);

  return result;
}

static CURLcode
mbed_connect_step1(struct Curl_easy *data, struct connectdata *conn,
                   int sockindex)
{

  struct ssl_connect_data *connssl = &conn->ssl[sockindex];
  struct ssl_backend_data *backend = connssl->backend;
  const char * const ssl_cafile = SSL_CONN_CONFIG(CAfile);
  const bool verifypeer = SSL_CONN_CONFIG(verifypeer);
  const char * const ssl_capath = SSL_CONN_CONFIG(CApath);
  char * const ssl_cert = SSL_SET_OPTION(primary.clientcert);
  const char * const ssl_crlfile = SSL_SET_OPTION(CRLfile);
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303

  ret = mbedtls_ctr_drbg_seed(&backend->ctr_drbg, entropy_func_mutex,
                              &ts_entropy, NULL, 0);
  if(ret) {
#ifdef MBEDTLS_ERROR_C
    mbedtls_strerror(ret, errorbuf, sizeof(errorbuf));
#endif /* MBEDTLS_ERROR_C */
    failf(data, "Failed - mbedTLS: ctr_drbg_init returned (-0x%04X) %s\n",
          -ret, errorbuf);
  }
#else
  mbedtls_entropy_init(&backend->entropy);
  mbedtls_ctr_drbg_init(&backend->ctr_drbg);

  ret = mbedtls_ctr_drbg_seed(&backend->ctr_drbg, mbedtls_entropy_func,
                              &backend->entropy, NULL, 0);
  if(ret) {
#ifdef MBEDTLS_ERROR_C
    mbedtls_strerror(ret, errorbuf, sizeof(errorbuf));
#endif /* MBEDTLS_ERROR_C */
    failf(data, "Failed - mbedTLS: ctr_drbg_init returned (-0x%04X) %s\n",
          -ret, errorbuf);
  }
#endif /* THREADING_SUPPORT */

  /* Load the trusted CA */
  mbedtls_x509_crt_init(&backend->cacert);








|












|







275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302

  ret = mbedtls_ctr_drbg_seed(&backend->ctr_drbg, entropy_func_mutex,
                              &ts_entropy, NULL, 0);
  if(ret) {
#ifdef MBEDTLS_ERROR_C
    mbedtls_strerror(ret, errorbuf, sizeof(errorbuf));
#endif /* MBEDTLS_ERROR_C */
    failf(data, "Failed - mbedTLS: ctr_drbg_init returned (-0x%04X) %s",
          -ret, errorbuf);
  }
#else
  mbedtls_entropy_init(&backend->entropy);
  mbedtls_ctr_drbg_init(&backend->ctr_drbg);

  ret = mbedtls_ctr_drbg_seed(&backend->ctr_drbg, mbedtls_entropy_func,
                              &backend->entropy, NULL, 0);
  if(ret) {
#ifdef MBEDTLS_ERROR_C
    mbedtls_strerror(ret, errorbuf, sizeof(errorbuf));
#endif /* MBEDTLS_ERROR_C */
    failf(data, "Failed - mbedTLS: ctr_drbg_init returned (-0x%04X) %s",
          -ret, errorbuf);
  }
#endif /* THREADING_SUPPORT */

  /* Load the trusted CA */
  mbedtls_x509_crt_init(&backend->cacert);

423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
    infof(data, "mbedTLS: Set SSL version to SSLv3\n");
    break;
  case CURL_SSLVERSION_TLSv1_0:
  case CURL_SSLVERSION_TLSv1_1:
  case CURL_SSLVERSION_TLSv1_2:
  case CURL_SSLVERSION_TLSv1_3:
    {
      CURLcode result = set_ssl_version_min_max(conn, sockindex);
      if(result != CURLE_OK)
        return result;
      break;
    }
  default:
    failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION");
    return CURLE_SSL_CONNECT_ERROR;







|







422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
    infof(data, "mbedTLS: Set SSL version to SSLv3\n");
    break;
  case CURL_SSLVERSION_TLSv1_0:
  case CURL_SSLVERSION_TLSv1_1:
  case CURL_SSLVERSION_TLSv1_2:
  case CURL_SSLVERSION_TLSv1_3:
    {
      CURLcode result = set_ssl_version_min_max(data, conn, sockindex);
      if(result != CURLE_OK)
        return result;
      break;
    }
  default:
    failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION");
    return CURLE_SSL_CONNECT_ERROR;
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
                                   MBEDTLS_SSL_SESSION_TICKETS_DISABLED);
#endif

  /* Check if there's a cached ID we can/should use here! */
  if(SSL_SET_OPTION(primary.sessionid)) {
    void *old_session = NULL;

    Curl_ssl_sessionid_lock(conn);
    if(!Curl_ssl_getsessionid(conn, &old_session, NULL, sockindex)) {
      ret = mbedtls_ssl_set_session(&backend->ssl, old_session);
      if(ret) {
        Curl_ssl_sessionid_unlock(conn);
        failf(data, "mbedtls_ssl_set_session returned -0x%x", -ret);
        return CURLE_SSL_CONNECT_ERROR;
      }
      infof(data, "mbedTLS re-using session\n");
    }
    Curl_ssl_sessionid_unlock(conn);
  }

  mbedtls_ssl_conf_ca_chain(&backend->config,
                            &backend->cacert,
                            &backend->crl);

  if(SSL_SET_OPTION(key)) {







|
|


|





|







458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
                                   MBEDTLS_SSL_SESSION_TICKETS_DISABLED);
#endif

  /* Check if there's a cached ID we can/should use here! */
  if(SSL_SET_OPTION(primary.sessionid)) {
    void *old_session = NULL;

    Curl_ssl_sessionid_lock(data);
    if(!Curl_ssl_getsessionid(data, conn, &old_session, NULL, sockindex)) {
      ret = mbedtls_ssl_set_session(&backend->ssl, old_session);
      if(ret) {
        Curl_ssl_sessionid_unlock(data);
        failf(data, "mbedtls_ssl_set_session returned -0x%x", -ret);
        return CURLE_SSL_CONNECT_ERROR;
      }
      infof(data, "mbedTLS re-using session\n");
    }
    Curl_ssl_sessionid_unlock(data);
  }

  mbedtls_ssl_conf_ca_chain(&backend->config,
                            &backend->cacert,
                            &backend->crl);

  if(SSL_SET_OPTION(key)) {
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555

  connssl->connecting_state = ssl_connect_2;

  return CURLE_OK;
}

static CURLcode
mbed_connect_step2(struct connectdata *conn,
                   int sockindex)
{
  int ret;
  struct Curl_easy *data = conn->data;
  struct ssl_connect_data *connssl = &conn->ssl[sockindex];
  struct ssl_backend_data *backend = connssl->backend;
  const mbedtls_x509_crt *peercert;
#ifndef CURL_DISABLE_PROXY
  const char * const pinnedpubkey = SSL_IS_PROXY() ?
    data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY] :
    data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG];







|



<







536
537
538
539
540
541
542
543
544
545
546

547
548
549
550
551
552
553

  connssl->connecting_state = ssl_connect_2;

  return CURLE_OK;
}

static CURLcode
mbed_connect_step2(struct Curl_easy *data, struct connectdata *conn,
                   int sockindex)
{
  int ret;

  struct ssl_connect_data *connssl = &conn->ssl[sockindex];
  struct ssl_backend_data *backend = connssl->backend;
  const mbedtls_x509_crt *peercert;
#ifndef CURL_DISABLE_PROXY
  const char * const pinnedpubkey = SSL_IS_PROXY() ?
    data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY] :
    data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG];
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
           !next_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");
    }
    Curl_multiuse_state(conn, conn->negnpn == CURL_HTTP_VERSION_2 ?
                        BUNDLE_MULTIPLEX : BUNDLE_NO_MULTIUSE);
  }
#endif

  connssl->connecting_state = ssl_connect_3;
  infof(data, "SSL connected\n");

  return CURLE_OK;
}

static CURLcode
mbed_connect_step3(struct connectdata *conn,
                   int sockindex)
{
  CURLcode retcode = CURLE_OK;
  struct ssl_connect_data *connssl = &conn->ssl[sockindex];
  struct ssl_backend_data *backend = connssl->backend;
  struct Curl_easy *data = conn->data;

  DEBUGASSERT(ssl_connect_3 == connssl->connecting_state);

  if(SSL_SET_OPTION(primary.sessionid)) {
    int ret;
    mbedtls_ssl_session *our_ssl_sessionid;
    void *old_ssl_sessionid = NULL;







|











|





<







695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719

720
721
722
723
724
725
726
           !next_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");
    }
    Curl_multiuse_state(data, conn->negnpn == CURL_HTTP_VERSION_2 ?
                        BUNDLE_MULTIPLEX : BUNDLE_NO_MULTIUSE);
  }
#endif

  connssl->connecting_state = ssl_connect_3;
  infof(data, "SSL connected\n");

  return CURLE_OK;
}

static CURLcode
mbed_connect_step3(struct Curl_easy *data, struct connectdata *conn,
                   int sockindex)
{
  CURLcode retcode = CURLE_OK;
  struct ssl_connect_data *connssl = &conn->ssl[sockindex];
  struct ssl_backend_data *backend = connssl->backend;


  DEBUGASSERT(ssl_connect_3 == connssl->connecting_state);

  if(SSL_SET_OPTION(primary.sessionid)) {
    int ret;
    mbedtls_ssl_session *our_ssl_sessionid;
    void *old_ssl_sessionid = NULL;
740
741
742
743
744
745
746
747
748
749
750
751

752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769

770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790

791
792
793
794


795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810

811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902

903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
        mbedtls_ssl_session_free(our_ssl_sessionid);
      free(our_ssl_sessionid);
      failf(data, "mbedtls_ssl_get_session returned -0x%x", -ret);
      return CURLE_SSL_CONNECT_ERROR;
    }

    /* If there's already a matching session in the cache, delete it */
    Curl_ssl_sessionid_lock(conn);
    if(!Curl_ssl_getsessionid(conn, &old_ssl_sessionid, NULL, sockindex))
      Curl_ssl_delsessionid(conn, old_ssl_sessionid);

    retcode = Curl_ssl_addsessionid(conn, our_ssl_sessionid, 0, sockindex);

    Curl_ssl_sessionid_unlock(conn);
    if(retcode) {
      mbedtls_ssl_session_free(our_ssl_sessionid);
      free(our_ssl_sessionid);
      failf(data, "failed to store ssl session");
      return retcode;
    }
  }

  connssl->connecting_state = ssl_connect_done;

  return CURLE_OK;
}

static ssize_t mbed_send(struct connectdata *conn, int sockindex,
                         const void *mem, size_t len,
                         CURLcode *curlcode)
{

  struct ssl_connect_data *connssl = &conn->ssl[sockindex];
  struct ssl_backend_data *backend = connssl->backend;
  int ret = -1;

  ret = mbedtls_ssl_write(&backend->ssl,
                          (unsigned char *)mem, len);

  if(ret < 0) {
    *curlcode = (ret == MBEDTLS_ERR_SSL_WANT_WRITE) ?
      CURLE_AGAIN : CURLE_SEND_ERROR;
    ret = -1;
  }

  return ret;
}

static void Curl_mbedtls_close_all(struct Curl_easy *data)
{
  (void)data;
}


static void Curl_mbedtls_close(struct connectdata *conn, int sockindex)
{
  struct ssl_connect_data *connssl = &conn->ssl[sockindex];
  struct ssl_backend_data *backend = connssl->backend;


  mbedtls_pk_free(&backend->pk);
  mbedtls_x509_crt_free(&backend->clicert);
  mbedtls_x509_crt_free(&backend->cacert);
  mbedtls_x509_crl_free(&backend->crl);
  mbedtls_ssl_config_free(&backend->config);
  mbedtls_ssl_free(&backend->ssl);
  mbedtls_ctr_drbg_free(&backend->ctr_drbg);
#ifndef THREADING_SUPPORT
  mbedtls_entropy_free(&backend->entropy);
#endif /* THREADING_SUPPORT */
}

static ssize_t mbed_recv(struct connectdata *conn, int num,
                         char *buf, size_t buffersize,
                         CURLcode *curlcode)
{

  struct ssl_connect_data *connssl = &conn->ssl[num];
  struct ssl_backend_data *backend = connssl->backend;
  int ret = -1;
  ssize_t len = -1;

  memset(buf, 0, buffersize);
  ret = mbedtls_ssl_read(&backend->ssl, (unsigned char *)buf,
                         buffersize);

  if(ret <= 0) {
    if(ret == MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY)
      return 0;

    *curlcode = (ret == MBEDTLS_ERR_SSL_WANT_READ) ?
      CURLE_AGAIN : CURLE_RECV_ERROR;
    return -1;
  }

  len = ret;

  return len;
}

static void Curl_mbedtls_session_free(void *ptr)
{
  mbedtls_ssl_session_free(ptr);
  free(ptr);
}

static size_t Curl_mbedtls_version(char *buffer, size_t size)
{
#ifdef MBEDTLS_VERSION_C
  /* if mbedtls_version_get_number() is available it is better */
  unsigned int version = mbedtls_version_get_number();
  return msnprintf(buffer, size, "mbedTLS/%u.%u.%u", version>>24,
                   (version>>16)&0xff, (version>>8)&0xff);
#else
  return msnprintf(buffer, size, "mbedTLS/%s", MBEDTLS_VERSION_STRING);
#endif
}

static CURLcode Curl_mbedtls_random(struct Curl_easy *data,
                                    unsigned char *entropy, size_t length)
{
#if defined(MBEDTLS_CTR_DRBG_C)
  int ret = -1;
  char errorbuf[128];
  mbedtls_entropy_context ctr_entropy;
  mbedtls_ctr_drbg_context ctr_drbg;
  mbedtls_entropy_init(&ctr_entropy);
  mbedtls_ctr_drbg_init(&ctr_drbg);
  errorbuf[0] = 0;

  ret = mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func,
                              &ctr_entropy, NULL, 0);

  if(ret) {
#ifdef MBEDTLS_ERROR_C
    mbedtls_strerror(ret, errorbuf, sizeof(errorbuf));
#endif /* MBEDTLS_ERROR_C */
    failf(data, "Failed - mbedTLS: ctr_drbg_seed returned (-0x%04X) %s\n",
          -ret, errorbuf);
  }
  else {
    ret = mbedtls_ctr_drbg_random(&ctr_drbg, entropy, length);

    if(ret) {
#ifdef MBEDTLS_ERROR_C
      mbedtls_strerror(ret, errorbuf, sizeof(errorbuf));
#endif /* MBEDTLS_ERROR_C */
      failf(data, "mbedTLS: ctr_drbg_init returned (-0x%04X) %s\n",
            -ret, errorbuf);
    }
  }

  mbedtls_ctr_drbg_free(&ctr_drbg);
  mbedtls_entropy_free(&ctr_entropy);

  return ret == 0 ? CURLE_OK : CURLE_FAILED_INIT;
#elif defined(MBEDTLS_HAVEGE_C)
  mbedtls_havege_state hs;
  mbedtls_havege_init(&hs);
  mbedtls_havege_random(&hs, entropy, length);
  mbedtls_havege_free(&hs);
  return CURLE_OK;
#else
  return CURLE_NOT_BUILT_IN;
#endif
}

static CURLcode
mbed_connect_common(struct connectdata *conn,

                    int sockindex,
                    bool nonblocking,
                    bool *done)
{
  CURLcode retcode;
  struct Curl_easy *data = conn->data;
  struct ssl_connect_data *connssl = &conn->ssl[sockindex];
  curl_socket_t sockfd = conn->sock[sockindex];
  timediff_t 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;
    }
    retcode = mbed_connect_step1(conn, sockindex);
    if(retcode)
      return retcode;
  }

  while(ssl_connect_2 == connssl->connecting_state ||
        ssl_connect_2_reading == connssl->connecting_state ||
        ssl_connect_2_writing == connssl->connecting_state) {







|
|
|

|
>
|













|



>




|
<










|




>
|



>
>












|



>





<

















|





|











|
|

















|









|




















|
>





<




















|







737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773

774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817

818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909

910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
        mbedtls_ssl_session_free(our_ssl_sessionid);
      free(our_ssl_sessionid);
      failf(data, "mbedtls_ssl_get_session returned -0x%x", -ret);
      return CURLE_SSL_CONNECT_ERROR;
    }

    /* If there's already a matching session in the cache, delete it */
    Curl_ssl_sessionid_lock(data);
    if(!Curl_ssl_getsessionid(data, conn, &old_ssl_sessionid, NULL, sockindex))
      Curl_ssl_delsessionid(data, old_ssl_sessionid);

    retcode = Curl_ssl_addsessionid(data, conn,
                                    our_ssl_sessionid, 0, sockindex);
    Curl_ssl_sessionid_unlock(data);
    if(retcode) {
      mbedtls_ssl_session_free(our_ssl_sessionid);
      free(our_ssl_sessionid);
      failf(data, "failed to store ssl session");
      return retcode;
    }
  }

  connssl->connecting_state = ssl_connect_done;

  return CURLE_OK;
}

static ssize_t mbed_send(struct Curl_easy *data, int sockindex,
                         const void *mem, size_t len,
                         CURLcode *curlcode)
{
  struct connectdata *conn = data->conn;
  struct ssl_connect_data *connssl = &conn->ssl[sockindex];
  struct ssl_backend_data *backend = connssl->backend;
  int ret = -1;

  ret = mbedtls_ssl_write(&backend->ssl, (unsigned char *)mem, len);


  if(ret < 0) {
    *curlcode = (ret == MBEDTLS_ERR_SSL_WANT_WRITE) ?
      CURLE_AGAIN : CURLE_SEND_ERROR;
    ret = -1;
  }

  return ret;
}

static void mbedtls_close_all(struct Curl_easy *data)
{
  (void)data;
}

static void mbedtls_close(struct Curl_easy *data,
                          struct connectdata *conn, int sockindex)
{
  struct ssl_connect_data *connssl = &conn->ssl[sockindex];
  struct ssl_backend_data *backend = connssl->backend;

  (void) data;
  mbedtls_pk_free(&backend->pk);
  mbedtls_x509_crt_free(&backend->clicert);
  mbedtls_x509_crt_free(&backend->cacert);
  mbedtls_x509_crl_free(&backend->crl);
  mbedtls_ssl_config_free(&backend->config);
  mbedtls_ssl_free(&backend->ssl);
  mbedtls_ctr_drbg_free(&backend->ctr_drbg);
#ifndef THREADING_SUPPORT
  mbedtls_entropy_free(&backend->entropy);
#endif /* THREADING_SUPPORT */
}

static ssize_t mbed_recv(struct Curl_easy *data, int num,
                         char *buf, size_t buffersize,
                         CURLcode *curlcode)
{
  struct connectdata *conn = data->conn;
  struct ssl_connect_data *connssl = &conn->ssl[num];
  struct ssl_backend_data *backend = connssl->backend;
  int ret = -1;
  ssize_t len = -1;


  ret = mbedtls_ssl_read(&backend->ssl, (unsigned char *)buf,
                         buffersize);

  if(ret <= 0) {
    if(ret == MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY)
      return 0;

    *curlcode = (ret == MBEDTLS_ERR_SSL_WANT_READ) ?
      CURLE_AGAIN : CURLE_RECV_ERROR;
    return -1;
  }

  len = ret;

  return len;
}

static void mbedtls_session_free(void *ptr)
{
  mbedtls_ssl_session_free(ptr);
  free(ptr);
}

static size_t mbedtls_version(char *buffer, size_t size)
{
#ifdef MBEDTLS_VERSION_C
  /* if mbedtls_version_get_number() is available it is better */
  unsigned int version = mbedtls_version_get_number();
  return msnprintf(buffer, size, "mbedTLS/%u.%u.%u", version>>24,
                   (version>>16)&0xff, (version>>8)&0xff);
#else
  return msnprintf(buffer, size, "mbedTLS/%s", MBEDTLS_VERSION_STRING);
#endif
}

static CURLcode mbedtls_random(struct Curl_easy *data,
                               unsigned char *entropy, size_t length)
{
#if defined(MBEDTLS_CTR_DRBG_C)
  int ret = -1;
  char errorbuf[128];
  mbedtls_entropy_context ctr_entropy;
  mbedtls_ctr_drbg_context ctr_drbg;
  mbedtls_entropy_init(&ctr_entropy);
  mbedtls_ctr_drbg_init(&ctr_drbg);
  errorbuf[0] = 0;

  ret = mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func,
                              &ctr_entropy, NULL, 0);

  if(ret) {
#ifdef MBEDTLS_ERROR_C
    mbedtls_strerror(ret, errorbuf, sizeof(errorbuf));
#endif /* MBEDTLS_ERROR_C */
    failf(data, "Failed - mbedTLS: ctr_drbg_seed returned (-0x%04X) %s",
          -ret, errorbuf);
  }
  else {
    ret = mbedtls_ctr_drbg_random(&ctr_drbg, entropy, length);

    if(ret) {
#ifdef MBEDTLS_ERROR_C
      mbedtls_strerror(ret, errorbuf, sizeof(errorbuf));
#endif /* MBEDTLS_ERROR_C */
      failf(data, "mbedTLS: ctr_drbg_init returned (-0x%04X) %s",
            -ret, errorbuf);
    }
  }

  mbedtls_ctr_drbg_free(&ctr_drbg);
  mbedtls_entropy_free(&ctr_entropy);

  return ret == 0 ? CURLE_OK : CURLE_FAILED_INIT;
#elif defined(MBEDTLS_HAVEGE_C)
  mbedtls_havege_state hs;
  mbedtls_havege_init(&hs);
  mbedtls_havege_random(&hs, entropy, length);
  mbedtls_havege_free(&hs);
  return CURLE_OK;
#else
  return CURLE_NOT_BUILT_IN;
#endif
}

static CURLcode
mbed_connect_common(struct Curl_easy *data,
                    struct connectdata *conn,
                    int sockindex,
                    bool nonblocking,
                    bool *done)
{
  CURLcode retcode;

  struct ssl_connect_data *connssl = &conn->ssl[sockindex];
  curl_socket_t sockfd = conn->sock[sockindex];
  timediff_t 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;
    }
    retcode = mbed_connect_step1(data, conn, sockindex);
    if(retcode)
      return retcode;
  }

  while(ssl_connect_2 == connssl->connecting_state ||
        ssl_connect_2_reading == connssl->connecting_state ||
        ssl_connect_2_writing == connssl->connecting_state) {
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013

1014
1015
1016
1017
1018
1019
1020

1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
    /* 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.
     */
    retcode = mbed_connect_step2(conn, sockindex);
    if(retcode || (nonblocking &&
                   (ssl_connect_2 == connssl->connecting_state ||
                    ssl_connect_2_reading == connssl->connecting_state ||
                    ssl_connect_2_writing == connssl->connecting_state)))
      return retcode;

  } /* repeat step2 until all transactions are done. */

  if(ssl_connect_3 == connssl->connecting_state) {
    retcode = mbed_connect_step3(conn, sockindex);
    if(retcode)
      return retcode;
  }

  if(ssl_connect_done == connssl->connecting_state) {
    connssl->state = ssl_connection_complete;
    conn->recv[sockindex] = mbed_recv;
    conn->send[sockindex] = mbed_send;
    *done = TRUE;
  }
  else
    *done = FALSE;

  /* Reset our connect state machine */
  connssl->connecting_state = ssl_connect_1;

  return CURLE_OK;
}


static CURLcode Curl_mbedtls_connect_nonblocking(struct connectdata *conn,
                                                 int sockindex, bool *done)
{
  return mbed_connect_common(conn, sockindex, TRUE, done);
}



static CURLcode Curl_mbedtls_connect(struct connectdata *conn, int sockindex)
{
  CURLcode retcode;
  bool done = FALSE;

  retcode = mbed_connect_common(conn, sockindex, FALSE, &done);
  if(retcode)
    return retcode;

  DEBUGASSERT(done);

  return CURLE_OK;
}

/*
 * return 0 error initializing SSL
 * return 1 SSL initialized successfully
 */
static int Curl_mbedtls_init(void)
{
  return Curl_mbedtlsthreadlock_thread_setup();
}

static void Curl_mbedtls_cleanup(void)
{
  (void)Curl_mbedtlsthreadlock_thread_cleanup();
}

static bool Curl_mbedtls_data_pending(const struct connectdata *conn,
                                      int sockindex)
{
  const struct ssl_connect_data *connssl = &conn->ssl[sockindex];
  struct ssl_backend_data *backend = connssl->backend;
  return mbedtls_ssl_get_bytes_avail(&backend->ssl) != 0;
}

static CURLcode Curl_mbedtls_sha256sum(const unsigned char *input,
                                    size_t inputlen,
                                    unsigned char *sha256sum,
                                    size_t sha256len UNUSED_PARAM)
{
  (void)sha256len;
#if MBEDTLS_VERSION_NUMBER < 0x02070000
  mbedtls_sha256(input, inputlen, sha256sum, 0);
#else
  /* returns 0 on success, otherwise failure */
  if(mbedtls_sha256_ret(input, inputlen, sha256sum, 0) != 0)
    return CURLE_BAD_FUNCTION_ARGUMENT;
#endif
  return CURLE_OK;
}

static void *Curl_mbedtls_get_internals(struct ssl_connect_data *connssl,
                                        CURLINFO info UNUSED_PARAM)
{
  struct ssl_backend_data *backend = connssl->backend;
  (void)info;
  return &backend->ssl;
}

const struct Curl_ssl Curl_ssl_mbedtls = {
  { CURLSSLBACKEND_MBEDTLS, "mbedtls" }, /* info */

  SSLSUPP_CA_PATH |
  SSLSUPP_PINNEDPUBKEY |
  SSLSUPP_SSL_CTX,

  sizeof(struct ssl_backend_data),

  Curl_mbedtls_init,                /* init */
  Curl_mbedtls_cleanup,             /* cleanup */
  Curl_mbedtls_version,             /* version */
  Curl_none_check_cxn,              /* check_cxn */
  Curl_none_shutdown,               /* shutdown */
  Curl_mbedtls_data_pending,        /* data_pending */
  Curl_mbedtls_random,              /* random */
  Curl_none_cert_status_request,    /* cert_status_request */
  Curl_mbedtls_connect,             /* connect */
  Curl_mbedtls_connect_nonblocking, /* connect_nonblocking */
  Curl_mbedtls_get_internals,       /* get_internals */
  Curl_mbedtls_close,               /* close_one */
  Curl_mbedtls_close_all,           /* close_all */
  Curl_mbedtls_session_free,        /* session_free */
  Curl_none_set_engine,             /* set_engine */
  Curl_none_set_engine_default,     /* set_engine_default */
  Curl_none_engines_list,           /* engines_list */
  Curl_none_false_start,            /* false_start */
  Curl_none_md5sum,                 /* md5sum */
  Curl_mbedtls_sha256sum            /* sha256sum */
};

#endif /* USE_MBEDTLS */







|









|



















>
|
|

|



>
|




|












|




|




|
|






|
|
|
|












|
|















|
|
|


|
|

|
|
|
|
|
|




<
|



978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110

1111
1112
1113
1114
    /* 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.
     */
    retcode = mbed_connect_step2(data, conn, sockindex);
    if(retcode || (nonblocking &&
                   (ssl_connect_2 == connssl->connecting_state ||
                    ssl_connect_2_reading == connssl->connecting_state ||
                    ssl_connect_2_writing == connssl->connecting_state)))
      return retcode;

  } /* repeat step2 until all transactions are done. */

  if(ssl_connect_3 == connssl->connecting_state) {
    retcode = mbed_connect_step3(data, conn, sockindex);
    if(retcode)
      return retcode;
  }

  if(ssl_connect_done == connssl->connecting_state) {
    connssl->state = ssl_connection_complete;
    conn->recv[sockindex] = mbed_recv;
    conn->send[sockindex] = mbed_send;
    *done = TRUE;
  }
  else
    *done = FALSE;

  /* Reset our connect state machine */
  connssl->connecting_state = ssl_connect_1;

  return CURLE_OK;
}

static CURLcode mbedtls_connect_nonblocking(struct Curl_easy *data,
                                            struct connectdata *conn,
                                            int sockindex, bool *done)
{
  return mbed_connect_common(data, conn, sockindex, TRUE, done);
}


static CURLcode mbedtls_connect(struct Curl_easy *data,
                                struct connectdata *conn, int sockindex)
{
  CURLcode retcode;
  bool done = FALSE;

  retcode = mbed_connect_common(data, conn, sockindex, FALSE, &done);
  if(retcode)
    return retcode;

  DEBUGASSERT(done);

  return CURLE_OK;
}

/*
 * return 0 error initializing SSL
 * return 1 SSL initialized successfully
 */
static int mbedtls_init(void)
{
  return Curl_mbedtlsthreadlock_thread_setup();
}

static void mbedtls_cleanup(void)
{
  (void)Curl_mbedtlsthreadlock_thread_cleanup();
}

static bool mbedtls_data_pending(const struct connectdata *conn,
                                 int sockindex)
{
  const struct ssl_connect_data *connssl = &conn->ssl[sockindex];
  struct ssl_backend_data *backend = connssl->backend;
  return mbedtls_ssl_get_bytes_avail(&backend->ssl) != 0;
}

static CURLcode mbedtls_sha256sum(const unsigned char *input,
                                  size_t inputlen,
                                  unsigned char *sha256sum,
                                  size_t sha256len UNUSED_PARAM)
{
  (void)sha256len;
#if MBEDTLS_VERSION_NUMBER < 0x02070000
  mbedtls_sha256(input, inputlen, sha256sum, 0);
#else
  /* returns 0 on success, otherwise failure */
  if(mbedtls_sha256_ret(input, inputlen, sha256sum, 0) != 0)
    return CURLE_BAD_FUNCTION_ARGUMENT;
#endif
  return CURLE_OK;
}

static void *mbedtls_get_internals(struct ssl_connect_data *connssl,
                                   CURLINFO info UNUSED_PARAM)
{
  struct ssl_backend_data *backend = connssl->backend;
  (void)info;
  return &backend->ssl;
}

const struct Curl_ssl Curl_ssl_mbedtls = {
  { CURLSSLBACKEND_MBEDTLS, "mbedtls" }, /* info */

  SSLSUPP_CA_PATH |
  SSLSUPP_PINNEDPUBKEY |
  SSLSUPP_SSL_CTX,

  sizeof(struct ssl_backend_data),

  mbedtls_init,                     /* init */
  mbedtls_cleanup,                  /* cleanup */
  mbedtls_version,                  /* version */
  Curl_none_check_cxn,              /* check_cxn */
  Curl_none_shutdown,               /* shutdown */
  mbedtls_data_pending,             /* data_pending */
  mbedtls_random,                   /* random */
  Curl_none_cert_status_request,    /* cert_status_request */
  mbedtls_connect,                  /* connect */
  mbedtls_connect_nonblocking,      /* connect_nonblocking */
  mbedtls_get_internals,            /* get_internals */
  mbedtls_close,                    /* close_one */
  mbedtls_close_all,                /* close_all */
  mbedtls_session_free,             /* session_free */
  Curl_none_set_engine,             /* set_engine */
  Curl_none_set_engine_default,     /* set_engine_default */
  Curl_none_engines_list,           /* engines_list */
  Curl_none_false_start,            /* false_start */

  mbedtls_sha256sum                 /* sha256sum */
};

#endif /* USE_MBEDTLS */
Changes to jni/curl/lib/vtls/mesalink.c.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 2017 - 2018, Yiming Jing, <jingyiming@baidu.com>
 * Copyright (C) 1998 - 2020, 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 https://curl.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








|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 2017 - 2018, Yiming Jing, <jingyiming@baidu.com>
 * Copyright (C) 1998 - 2021, 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 https://curl.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
85
86
87
88
89
90
91
92

93
94
95
96
97
98
99
100
101
102
}

/*
 * This function loads all the client/CA certificates and CRLs. Setup the TLS
 * layer and do all necessary magic.
 */
static CURLcode
mesalink_connect_step1(struct connectdata *conn, int sockindex)

{
  char *ciphers;
  struct Curl_easy *data = conn->data;
  struct ssl_connect_data *connssl = &conn->ssl[sockindex];
  struct in_addr addr4;
#ifdef ENABLE_IPV6
  struct in6_addr addr6;
#endif
  const char *const hostname =
    SSL_IS_PROXY() ? conn->http_proxy.host.name : conn->host.name;







|
>


<







85
86
87
88
89
90
91
92
93
94
95

96
97
98
99
100
101
102
}

/*
 * This function loads all the client/CA certificates and CRLs. Setup the TLS
 * layer and do all necessary magic.
 */
static CURLcode
mesalink_connect_step1(struct Curl_easy *data,
                       struct connectdata *conn, int sockindex)
{
  char *ciphers;

  struct ssl_connect_data *connssl = &conn->ssl[sockindex];
  struct in_addr addr4;
#ifdef ENABLE_IPV6
  struct in6_addr addr6;
#endif
  const char *const hostname =
    SSL_IS_PROXY() ? conn->http_proxy.host.name : conn->host.name;
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291

292
293
294
295
296
297
298
299
300
301
    }
  }

#ifdef MESALINK_HAVE_SESSION
  if(SSL_SET_OPTION(primary.sessionid)) {
    void *ssl_sessionid = NULL;

    Curl_ssl_sessionid_lock(conn);
    if(!Curl_ssl_getsessionid(conn, &ssl_sessionid, NULL, sockindex)) {
      /* we got a session id, use it! */
      if(!SSL_set_session(BACKEND->handle, ssl_sessionid)) {
        Curl_ssl_sessionid_unlock(conn);
        failf(
          data,
          "SSL: SSL_set_session failed: %s",
          ERR_error_string(SSL_get_error(BACKEND->handle, 0), error_buffer));
        return CURLE_SSL_CONNECT_ERROR;
      }
      /* Informational message */
      infof(data, "SSL re-using session ID\n");
    }
    Curl_ssl_sessionid_unlock(conn);
  }
#endif /* MESALINK_HAVE_SESSION */

  if(SSL_set_fd(BACKEND->handle, (int)sockfd) != SSL_SUCCESS) {
    failf(data, "SSL: SSL_set_fd failed");
    return CURLE_SSL_CONNECT_ERROR;
  }

  connssl->connecting_state = ssl_connect_2;
  return CURLE_OK;
}

static CURLcode
mesalink_connect_step2(struct connectdata *conn, int sockindex)

{
  int ret = -1;
  struct Curl_easy *data = conn->data;
  struct ssl_connect_data *connssl = &conn->ssl[sockindex];

  conn->recv[sockindex] = mesalink_recv;
  conn->send[sockindex] = mesalink_send;

  ret = SSL_connect(BACKEND->handle);
  if(ret != SSL_SUCCESS) {







|
|


|









|













|
>


<







256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294

295
296
297
298
299
300
301
    }
  }

#ifdef MESALINK_HAVE_SESSION
  if(SSL_SET_OPTION(primary.sessionid)) {
    void *ssl_sessionid = NULL;

    Curl_ssl_sessionid_lock(data);
    if(!Curl_ssl_getsessionid(data, conn, &ssl_sessionid, NULL, sockindex)) {
      /* we got a session id, use it! */
      if(!SSL_set_session(BACKEND->handle, ssl_sessionid)) {
        Curl_ssl_sessionid_unlock(data);
        failf(
          data,
          "SSL: SSL_set_session failed: %s",
          ERR_error_string(SSL_get_error(BACKEND->handle, 0), error_buffer));
        return CURLE_SSL_CONNECT_ERROR;
      }
      /* Informational message */
      infof(data, "SSL re-using session ID\n");
    }
    Curl_ssl_sessionid_unlock(data);
  }
#endif /* MESALINK_HAVE_SESSION */

  if(SSL_set_fd(BACKEND->handle, (int)sockfd) != SSL_SUCCESS) {
    failf(data, "SSL: SSL_set_fd failed");
    return CURLE_SSL_CONNECT_ERROR;
  }

  connssl->connecting_state = ssl_connect_2;
  return CURLE_OK;
}

static CURLcode
mesalink_connect_step2(struct Curl_easy *data,
                       struct connectdata *conn, int sockindex)
{
  int ret = -1;

  struct ssl_connect_data *connssl = &conn->ssl[sockindex];

  conn->recv[sockindex] = mesalink_recv;
  conn->send[sockindex] = mesalink_send;

  ret = SSL_connect(BACKEND->handle);
  if(ret != SSL_SUCCESS) {
344
345
346
347
348
349
350
351
352

353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383

384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412


413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428

429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474

475
476
477
478


479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
  if(SSL_SET_OPTION(primary.sessionid)) {
    bool incache;
    SSL_SESSION *our_ssl_sessionid;
    void *old_ssl_sessionid = NULL;

    our_ssl_sessionid = SSL_get_session(BACKEND->handle);

    Curl_ssl_sessionid_lock(conn);
    incache =

      !(Curl_ssl_getsessionid(conn, &old_ssl_sessionid, NULL, sockindex));
    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 */, sockindex);
      if(result) {
        Curl_ssl_sessionid_unlock(conn);
        failf(data, "failed to store ssl session");
        return result;
      }
    }
    Curl_ssl_sessionid_unlock(conn);
  }
#endif /* MESALINK_HAVE_SESSION */

  connssl->connecting_state = ssl_connect_done;

  return result;
}

static ssize_t
mesalink_send(struct connectdata *conn, int sockindex, const void *mem,
              size_t len, CURLcode *curlcode)
{

  struct ssl_connect_data *connssl = &conn->ssl[sockindex];
  char error_buffer[MESALINK_MAX_ERROR_SZ];
  int memlen = (len > (size_t)INT_MAX) ? INT_MAX : (int)len;
  int rc = SSL_write(BACKEND->handle, mem, memlen);

  if(rc < 0) {
    int err = SSL_get_error(BACKEND->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_n(err, error_buffer, sizeof(error_buffer)),
            SOCKERRNO);
      *curlcode = CURLE_SEND_ERROR;
      return -1;
    }
  }
  return rc;
}

static void
Curl_mesalink_close(struct connectdata *conn, int sockindex)
{
  struct ssl_connect_data *connssl = &conn->ssl[sockindex];



  if(BACKEND->handle) {
    (void)SSL_shutdown(BACKEND->handle);
    SSL_free(BACKEND->handle);
    BACKEND->handle = NULL;
  }
  if(BACKEND->ctx) {
    SSL_CTX_free(BACKEND->ctx);
    BACKEND->ctx = NULL;
  }
}

static ssize_t
mesalink_recv(struct connectdata *conn, int num, char *buf, size_t buffersize,
              CURLcode *curlcode)
{

  struct ssl_connect_data *connssl = &conn->ssl[num];
  char error_buffer[MESALINK_MAX_ERROR_SZ];
  int buffsize = (buffersize > (size_t)INT_MAX) ? INT_MAX : (int)buffersize;
  int nread = SSL_read(BACKEND->handle, buf, buffsize);

  if(nread <= 0) {
    int err = SSL_get_error(BACKEND->handle, nread);

    switch(err) {
    case SSL_ERROR_ZERO_RETURN: /* no more data */
    case IO_ERROR_CONNECTION_ABORTED:
      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_n(err, error_buffer, sizeof(error_buffer)),
            SOCKERRNO);
      *curlcode = CURLE_RECV_ERROR;
      return -1;
    }
  }
  return nread;
}

static size_t
Curl_mesalink_version(char *buffer, size_t size)
{
  return msnprintf(buffer, size, "MesaLink/%s", MESALINK_VERSION_STRING);
}

static int
Curl_mesalink_init(void)
{
  return (SSL_library_init() == SSL_SUCCESS);
}

/*
 * This function is called to shut down the SSL layer but keep the
 * socket open (CCC - Clear Command Channel)
 */
static int

Curl_mesalink_shutdown(struct connectdata *conn, int sockindex)
{
  int retval = 0;
  struct ssl_connect_data *connssl = &conn->ssl[sockindex];



  if(BACKEND->handle) {
    SSL_free(BACKEND->handle);
    BACKEND->handle = NULL;
  }
  return retval;
}

static CURLcode
mesalink_connect_common(struct connectdata *conn, int sockindex,
                        bool nonblocking, bool *done)
{
  CURLcode result;
  struct Curl_easy *data = conn->data;
  struct ssl_connect_data *connssl = &conn->ssl[sockindex];
  curl_socket_t sockfd = conn->sock[sockindex];
  timediff_t timeout_ms;
  int what;

  /* check if the connection has already been established */
  if(ssl_connection_complete == connssl->state) {







|

>
|



|






|

|




|









|


>














|











|


>
>













|


>


















|











|





|









>
|



>
>









|
|


<







344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499

500
501
502
503
504
505
506
  if(SSL_SET_OPTION(primary.sessionid)) {
    bool incache;
    SSL_SESSION *our_ssl_sessionid;
    void *old_ssl_sessionid = NULL;

    our_ssl_sessionid = SSL_get_session(BACKEND->handle);

    Curl_ssl_sessionid_lock(data);
    incache =
      !(Curl_ssl_getsessionid(data, conn,
                              &old_ssl_sessionid, NULL, sockindex));
    if(incache) {
      if(old_ssl_sessionid != our_ssl_sessionid) {
        infof(data, "old SSL session ID is stale, removing\n");
        Curl_ssl_delsessionid(data, old_ssl_sessionid);
        incache = FALSE;
      }
    }

    if(!incache) {
      result = Curl_ssl_addsessionid(
        data, conn, our_ssl_sessionid, 0 /* unknown size */, sockindex);
      if(result) {
        Curl_ssl_sessionid_unlock(data);
        failf(data, "failed to store ssl session");
        return result;
      }
    }
    Curl_ssl_sessionid_unlock(data);
  }
#endif /* MESALINK_HAVE_SESSION */

  connssl->connecting_state = ssl_connect_done;

  return result;
}

static ssize_t
mesalink_send(struct Curl_easy *data, int sockindex, const void *mem,
              size_t len, CURLcode *curlcode)
{
  struct connectdata *conn = data->conn;
  struct ssl_connect_data *connssl = &conn->ssl[sockindex];
  char error_buffer[MESALINK_MAX_ERROR_SZ];
  int memlen = (len > (size_t)INT_MAX) ? INT_MAX : (int)len;
  int rc = SSL_write(BACKEND->handle, mem, memlen);

  if(rc < 0) {
    int err = SSL_get_error(BACKEND->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(data,
            "SSL write: %s, errno %d",
            ERR_error_string_n(err, error_buffer, sizeof(error_buffer)),
            SOCKERRNO);
      *curlcode = CURLE_SEND_ERROR;
      return -1;
    }
  }
  return rc;
}

static void
mesalink_close(struct Curl_easy *data, struct connectdata *conn, int sockindex)
{
  struct ssl_connect_data *connssl = &conn->ssl[sockindex];

  (void) data;

  if(BACKEND->handle) {
    (void)SSL_shutdown(BACKEND->handle);
    SSL_free(BACKEND->handle);
    BACKEND->handle = NULL;
  }
  if(BACKEND->ctx) {
    SSL_CTX_free(BACKEND->ctx);
    BACKEND->ctx = NULL;
  }
}

static ssize_t
mesalink_recv(struct Curl_easy *data, int num, char *buf, size_t buffersize,
              CURLcode *curlcode)
{
  struct connectdata *conn = data->conn;
  struct ssl_connect_data *connssl = &conn->ssl[num];
  char error_buffer[MESALINK_MAX_ERROR_SZ];
  int buffsize = (buffersize > (size_t)INT_MAX) ? INT_MAX : (int)buffersize;
  int nread = SSL_read(BACKEND->handle, buf, buffsize);

  if(nread <= 0) {
    int err = SSL_get_error(BACKEND->handle, nread);

    switch(err) {
    case SSL_ERROR_ZERO_RETURN: /* no more data */
    case IO_ERROR_CONNECTION_ABORTED:
      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(data,
            "SSL read: %s, errno %d",
            ERR_error_string_n(err, error_buffer, sizeof(error_buffer)),
            SOCKERRNO);
      *curlcode = CURLE_RECV_ERROR;
      return -1;
    }
  }
  return nread;
}

static size_t
mesalink_version(char *buffer, size_t size)
{
  return msnprintf(buffer, size, "MesaLink/%s", MESALINK_VERSION_STRING);
}

static int
mesalink_init(void)
{
  return (SSL_library_init() == SSL_SUCCESS);
}

/*
 * This function is called to shut down the SSL layer but keep the
 * socket open (CCC - Clear Command Channel)
 */
static int
mesalink_shutdown(struct Curl_easy *data,
                  struct connectdata *conn, int sockindex)
{
  int retval = 0;
  struct ssl_connect_data *connssl = &conn->ssl[sockindex];

  (void) data;

  if(BACKEND->handle) {
    SSL_free(BACKEND->handle);
    BACKEND->handle = NULL;
  }
  return retval;
}

static CURLcode
mesalink_connect_common(struct Curl_easy *data, struct connectdata *conn,
                        int sockindex, bool nonblocking, bool *done)
{
  CURLcode result;

  struct ssl_connect_data *connssl = &conn->ssl[sockindex];
  curl_socket_t sockfd = conn->sock[sockindex];
  timediff_t timeout_ms;
  int what;

  /* check if the connection has already been established */
  if(ssl_connection_complete == connssl->state) {
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521

    if(timeout_ms < 0) {
      /* no need to continue if time already is up */
      failf(data, "SSL connection timeout");
      return CURLE_OPERATION_TIMEDOUT;
    }

    result = mesalink_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) {







|







514
515
516
517
518
519
520
521
522
523
524
525
526
527
528

    if(timeout_ms < 0) {
      /* no need to continue if time already is up */
      failf(data, "SSL connection timeout");
      return CURLE_OPERATION_TIMEDOUT;
    }

    result = mesalink_connect_step1(data, 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) {
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
    /* 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 = mesalink_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;
    }







|







571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
    /* 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 = mesalink_connect_step2(data, 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;
    }
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610

611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
  /* Reset our connect state machine */
  connssl->connecting_state = ssl_connect_1;

  return CURLE_OK;
}

static CURLcode
Curl_mesalink_connect_nonblocking(struct connectdata *conn, int sockindex,
                                  bool *done)
{
  return mesalink_connect_common(conn, sockindex, TRUE, done);
}

static CURLcode
Curl_mesalink_connect(struct connectdata *conn, int sockindex)

{
  CURLcode result;
  bool done = FALSE;

  result = mesalink_connect_common(conn, sockindex, FALSE, &done);
  if(result)
    return result;

  DEBUGASSERT(done);

  return CURLE_OK;
}

static void *
Curl_mesalink_get_internals(struct ssl_connect_data *connssl,
                            CURLINFO info UNUSED_PARAM)
{
  (void)info;
  return BACKEND->handle;
}

const struct Curl_ssl Curl_ssl_mesalink = {
  { CURLSSLBACKEND_MESALINK, "MesaLink" }, /* info */

  SSLSUPP_SSL_CTX,

  sizeof(struct ssl_backend_data),

  Curl_mesalink_init, /* init */
  Curl_none_cleanup, /* cleanup */
  Curl_mesalink_version, /* version */
  Curl_none_check_cxn, /* check_cxn */
  Curl_mesalink_shutdown, /* shutdown */
  Curl_none_data_pending, /* data_pending */
  Curl_none_random, /* random */
  Curl_none_cert_status_request, /* cert_status_request */
  Curl_mesalink_connect, /* connect */
  Curl_mesalink_connect_nonblocking, /* connect_nonblocking */
  Curl_mesalink_get_internals, /* get_internals */
  Curl_mesalink_close, /* close_one */
  Curl_none_close_all, /* close_all */
  Curl_none_session_free, /* session_free */
  Curl_none_set_engine, /* set_engine */
  Curl_none_set_engine_default, /* set_engine_default */
  Curl_none_engines_list, /* engines_list */
  Curl_none_false_start, /* false_start */
  Curl_none_md5sum, /* md5sum */
  NULL /* sha256sum */
};

#endif







|
|

|



|
>




|









|
|












|
|
|
|
|
|
|

|
|
|
|
|
|
|
|
|
|
<
|



603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664

665
666
667
668
  /* Reset our connect state machine */
  connssl->connecting_state = ssl_connect_1;

  return CURLE_OK;
}

static CURLcode
mesalink_connect_nonblocking(struct Curl_easy *data, struct connectdata *conn,
                             int sockindex, bool *done)
{
  return mesalink_connect_common(data, conn, sockindex, TRUE, done);
}

static CURLcode
mesalink_connect(struct Curl_easy *data, struct connectdata *conn,
                 int sockindex)
{
  CURLcode result;
  bool done = FALSE;

  result = mesalink_connect_common(data, conn, sockindex, FALSE, &done);
  if(result)
    return result;

  DEBUGASSERT(done);

  return CURLE_OK;
}

static void *
mesalink_get_internals(struct ssl_connect_data *connssl,
                       CURLINFO info UNUSED_PARAM)
{
  (void)info;
  return BACKEND->handle;
}

const struct Curl_ssl Curl_ssl_mesalink = {
  { CURLSSLBACKEND_MESALINK, "MesaLink" }, /* info */

  SSLSUPP_SSL_CTX,

  sizeof(struct ssl_backend_data),

  mesalink_init,                 /* init */
  Curl_none_cleanup,             /* cleanup */
  mesalink_version,              /* version */
  Curl_none_check_cxn,           /* check_cxn */
  mesalink_shutdown,             /* shutdown */
  Curl_none_data_pending,        /* data_pending */
  Curl_none_random,              /* random */
  Curl_none_cert_status_request, /* cert_status_request */
  mesalink_connect,              /* connect */
  mesalink_connect_nonblocking,  /* connect_nonblocking */
  mesalink_get_internals,        /* get_internals */
  mesalink_close,                /* close_one */
  Curl_none_close_all,           /* close_all */
  Curl_none_session_free,        /* session_free */
  Curl_none_set_engine,          /* set_engine */
  Curl_none_set_engine_default,  /* set_engine_default */
  Curl_none_engines_list,        /* engines_list */
  Curl_none_false_start,         /* false_start */

  NULL                           /* sha256sum */
};

#endif
Changes to jni/curl/lib/vtls/nss.c.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2020, 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 https://curl.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







|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2021, 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 https://curl.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
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
  wrap->ptr = ptr;
  Curl_llist_insert_next(list, list->tail, wrap, &wrap->node);
  return CURLE_OK;
}

/* 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 *connssl,
                                  CK_OBJECT_CLASS obj_class,
                                  const char *filename, bool cacert)
{
  PK11SlotInfo *slot;
  PK11GenericObject *obj;
  CK_BBOOL cktrue = CK_TRUE;







|







439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
  wrap->ptr = ptr;
  Curl_llist_insert_next(list, list->tail, wrap, &wrap->node);
  return CURLE_OK;
}

/* 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 nss_close(). */
static CURLcode nss_create_object(struct ssl_connect_data *connssl,
                                  CK_OBJECT_CLASS obj_class,
                                  const char *filename, bool cacert)
{
  PK11SlotInfo *slot;
  PK11GenericObject *obj;
  CK_BBOOL cktrue = CK_TRUE;
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
    backend->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)
{
  struct ptr_list_wrap *wrap = (struct ptr_list_wrap *) ptr;
  PK11GenericObject *obj = (PK11GenericObject *) wrap->ptr;
  (void) user;
  PK11_DestroyGenericObject(obj);
  free(wrap);







|







504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
    backend->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 nss_close() */
static void nss_destroy_object(void *user, void *ptr)
{
  struct ptr_list_wrap *wrap = (struct ptr_list_wrap *) ptr;
  PK11GenericObject *obj = (PK11GenericObject *) wrap->ptr;
  (void) user;
  PK11_DestroyGenericObject(obj);
  free(wrap);
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
  if(SECSuccess != CERT_CacheCRL(db, crl_der)) {
    /* unable to cache CRL */
    SECITEM_FreeItem(crl_der, PR_TRUE);
    PR_Unlock(nss_crllock);
    return CURLE_SSL_CRL_BADFILE;
  }

  /* store the CRL item so that we can free it in Curl_nss_cleanup() */
  if(insert_wrapped_ptr(&nss_crl_list, crl_der) != CURLE_OK) {
    if(SECSuccess == CERT_UncacheCRL(db, crl_der))
      SECITEM_FreeItem(crl_der, PR_TRUE);
    PR_Unlock(nss_crllock);
    return CURLE_OUT_OF_MEMORY;
  }








|







583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
  if(SECSuccess != CERT_CacheCRL(db, crl_der)) {
    /* unable to cache CRL */
    SECITEM_FreeItem(crl_der, PR_TRUE);
    PR_Unlock(nss_crllock);
    return CURLE_SSL_CRL_BADFILE;
  }

  /* store the CRL item so that we can free it in nss_cleanup() */
  if(insert_wrapped_ptr(&nss_crl_list, crl_der) != CURLE_OK) {
    if(SECSuccess == CERT_UncacheCRL(db, crl_der))
      SECITEM_FreeItem(crl_der, PR_TRUE);
    PR_Unlock(nss_crllock);
    return CURLE_OUT_OF_MEMORY;
  }

661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
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, *tmp;
  SECStatus status;
  CURLcode result;
  struct ssl_connect_data *ssl = conn->ssl;
  struct Curl_easy *data = conn->data;

  (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;







|
|





<







661
662
663
664
665
666
667
668
669
670
671
672
673
674

675
676
677
678
679
680
681
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 Curl_easy *data, struct connectdata *conn,
                             int sockindex, char *key_file)
{
  PK11SlotInfo *slot, *tmp;
  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;
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754

  status = PK11_Authenticate(slot, PR_TRUE, SSL_SET_OPTION(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 Curl_easy *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;
    }
  }







|




|


|







|
|

<






|










|


|


|







696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721

722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752

  status = PK11_Authenticate(slot, PR_TRUE, SSL_SET_OPTION(key_passwd));
  PK11_FreeSlot(slot);

  return (SECSuccess == status) ? CURLE_OK : CURLE_SSL_CERTPROBLEM;
}

static int display_error(struct Curl_easy *data, PRInt32 err,
                         const char *filename)
{
  switch(err) {
  case SEC_ERROR_BAD_PASSWORD:
    failf(data, "Unable to load client key: Incorrect password");
    return 1;
  case SEC_ERROR_UNKNOWN_CERT:
    failf(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 Curl_easy *data, struct connectdata *conn,
                           int sockindex, char *cert_file, char *key_file)
{

  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(data, 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(data, conn, sockindex, key_file);
    else
      /* In case the cert file also has the key */
      result = nss_load_key(data, conn, sockindex, cert_file);
    if(result) {
      const PRErrorCode err = PR_GetError();
      if(!display_error(data, 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;
    }
  }
767
768
769
770
771
772
773

774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815

816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
}

/* 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(SSL_CONN_CONFIG(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(!SSL_CONN_CONFIG(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->bits.tls_enable_npn && !conn->bits.tls_enable_alpn) {
    return;
  }

  if(SSL_GetNextProto(sock, &state, buf, &buflen, buflenmax) == SECSuccess) {

    switch(state) {
#if NSSVERNUM >= 0x031a00 /* 3.26.0 */
    /* used by NSS internally to implement 0-RTT */
    case SSL_NEXT_PROTO_EARLY_VALUE:
      /* fall through! */
#endif
    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;
    }
    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;
    }
    Curl_multiuse_state(conn, conn->negnpn == CURL_HTTP_VERSION_2 ?
                        BUNDLE_MULTIPLEX : BUNDLE_NO_MULTIUSE);
  }
}

#if NSSVERNUM >= 0x030f04 /* 3.15.4 */
static SECStatus CanFalseStartCallback(PRFileDesc *sock, void *client_data,
                                       PRBool *canFalseStart)
{
  struct connectdata *conn = client_data;
  struct Curl_easy *data = conn->data;

  SSLChannelInfo channelInfo;
  SSLCipherSuiteInfo cipherInfo;

  SECStatus rv;
  PRBool negotiatedExtension;








>
|







|




|









|






|











>
|



















|



|



|














|








<
|







765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867

868
869
870
871
872
873
874
875
}

/* 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 Curl_easy *data = (struct Curl_easy *)arg;
  struct connectdata *conn = data->conn;

#ifdef SSL_ENABLE_OCSP_STAPLING
  if(SSL_CONN_CONFIG(verifystatus)) {
    SECStatus cacheResult;

    const SECItemArray *csa = SSL_PeerStapledOCSPResponses(fd);
    if(!csa) {
      failf(data, "Invalid OCSP response");
      return SECFailure;
    }

    if(csa->len == 0) {
      failf(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(data, "Invalid OCSP response");
      return cacheResult;
    }
  }
#endif

  if(!SSL_CONN_CONFIG(verifypeer)) {
    infof(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 Curl_easy *data = (struct Curl_easy *)arg;
  struct connectdata *conn = data->conn;
  unsigned int buflenmax = 50;
  unsigned char buf[50];
  unsigned int buflen;
  SSLNextProtoState state;

  if(!conn->bits.tls_enable_npn && !conn->bits.tls_enable_alpn) {
    return;
  }

  if(SSL_GetNextProto(sock, &state, buf, &buflen, buflenmax) == SECSuccess) {

    switch(state) {
#if NSSVERNUM >= 0x031a00 /* 3.26.0 */
    /* used by NSS internally to implement 0-RTT */
    case SSL_NEXT_PROTO_EARLY_VALUE:
      /* fall through! */
#endif
    case SSL_NEXT_PROTO_NO_SUPPORT:
    case SSL_NEXT_PROTO_NO_OVERLAP:
      infof(data, "ALPN/NPN, server did not agree to a protocol\n");
      return;
#ifdef SSL_ENABLE_ALPN
    case SSL_NEXT_PROTO_SELECTED:
      infof(data, "ALPN, server accepted to use %.*s\n", buflen, buf);
      break;
#endif
    case SSL_NEXT_PROTO_NEGOTIATED:
      infof(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;
    }
    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;
    }
    Curl_multiuse_state(data, conn->negnpn == CURL_HTTP_VERSION_2 ?
                        BUNDLE_MULTIPLEX : BUNDLE_NO_MULTIUSE);
  }
}

#if NSSVERNUM >= 0x030f04 /* 3.15.4 */
static SECStatus CanFalseStartCallback(PRFileDesc *sock, void *client_data,
                                       PRBool *canFalseStart)
{

  struct Curl_easy *data = (struct Curl_easy *)client_data;

  SSLChannelInfo channelInfo;
  SSLCipherSuiteInfo cipherInfo;

  SECStatus rv;
  PRBool negotiatedExtension;

945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
  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);







|















|





|

|
|




















|


|







944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
  infof(data, "\tissuer: %s\n", issuer);

  PR_Free(subject);
  PR_Free(issuer);
  PR_Free(common_name);
}

static CURLcode display_conn_info(struct Curl_easy *data, 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(data, "SSL connection using %s\n", suite.cipherSuiteName);
    }
  }

  cert = SSL_PeerCertificate(sock);
  if(cert) {
    infof(data, "Server certificate:\n");

    if(!data->set.ssl.certinfo) {
      display_cert_info(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(data, i);
      if(!result) {
        for(i = 0; cert; cert = cert2) {
          result = Curl_extract_certinfo(data, i++, (char *)cert->derCert.data,
                                         (char *)cert->derCert.data +
                                                 cert->derCert.len);
          if(result)
            break;

          if(cert->isRoot) {
            CERT_DestroyCertificate(cert);
1017
1018
1019
1020
1021
1022
1023

1024
1025
1026
1027
1028
1029
1030
1031
1032
  }

  return result;
}

static SECStatus BadCertHandler(void *arg, PRFileDesc *sock)
{

  struct connectdata *conn = (struct connectdata *)arg;
  struct Curl_easy *data = conn->data;
  PRErrorCode err = PR_GetError();
  CERTCertificate *cert;

  /* remember the cert verification result */
  SSL_SET_OPTION_LVALUE(certverifyresult) = err;

  if(err == SSL_ERROR_BAD_CERT_DOMAIN && !SSL_CONN_CONFIG(verifyhost))







>
|
<







1016
1017
1018
1019
1020
1021
1022
1023
1024

1025
1026
1027
1028
1029
1030
1031
  }

  return result;
}

static SECStatus BadCertHandler(void *arg, PRFileDesc *sock)
{
  struct Curl_easy *data = (struct Curl_easy *)arg;
  struct connectdata *conn = data->conn;

  PRErrorCode err = PR_GetError();
  CERTCertificate *cert;

  /* remember the cert verification result */
  SSL_SET_OPTION_LVALUE(certverifyresult) = err;

  if(err == SSL_ERROR_BAD_CERT_DOMAIN && !SSL_CONN_CONFIG(verifyhost))
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
  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;

    err = PR_GetError();
    err_name = nss_error_to_name(err);







|







1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
  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;

    err = PR_GetError();
    err_name = nss_error_to_name(err);
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
  err = PR_GetError();
  err_name = nss_error_to_name(err);
  failf(data, "Unable to initialize NSS: %d (%s)", err, err_name);
  return CURLE_SSL_CACERT_BADFILE;
}

/* data might be NULL */
static CURLcode nss_init(struct Curl_easy *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() */
  Curl_llist_init(&nss_crl_list, nss_destroy_crl_item);

  /* 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))) {







|








|







1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
  err = PR_GetError();
  err_name = nss_error_to_name(err);
  failf(data, "Unable to initialize NSS: %d (%s)", err, err_name);
  return CURLE_SSL_CACERT_BADFILE;
}

/* data might be NULL */
static CURLcode nss_setup(struct Curl_easy *data)
{
  char *cert_dir;
  struct_stat st;
  CURLcode result;

  if(initialized)
    return CURLE_OK;

  /* list of all CRL items we need to destroy in nss_cleanup() */
  Curl_llist_init(&nss_crl_list, nss_destroy_crl_item);

  /* 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))) {
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433

/**
 * Global SSL init
 *
 * @retval 0 error initializing SSL
 * @retval 1 SSL initialized successfully
 */
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, 0);
    nss_initlock = PR_NewLock();
    nss_crllock = PR_NewLock();
    nss_findslot_lock = PR_NewLock();







|







1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432

/**
 * Global SSL init
 *
 * @retval 0 error initializing SSL
 * @retval 1 SSL initialized successfully
 */
static int 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, 0);
    nss_initlock = PR_NewLock();
    nss_crllock = PR_NewLock();
    nss_findslot_lock = PR_NewLock();
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
    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 */
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.







|






|







1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
    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_setup(data);
  PR_Unlock(nss_initlock);

  return result;
}

/* Global cleanup */
static void 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.
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
 * 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
 */
static int Curl_nss_check_cxn(struct connectdata *conn)
{
  struct ssl_connect_data *connssl = &conn->ssl[FIRSTSOCKET];
  struct ssl_backend_data *backend = connssl->backend;
  int rc;
  char buf;

  rc =
    PR_Recv(backend->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 */
}

static void nss_close(struct ssl_connect_data *connssl)
{
  /* before the cleanup, check whether we are using a client certificate */
  struct ssl_backend_data *backend = connssl->backend;
  const bool client_cert = (backend->client_nickname != NULL)
    || (backend->obj_clicert != NULL);

  free(backend->client_nickname);







|


















|







1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
 * 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
 */
static int nss_check_cxn(struct connectdata *conn)
{
  struct ssl_connect_data *connssl = &conn->ssl[FIRSTSOCKET];
  struct ssl_backend_data *backend = connssl->backend;
  int rc;
  char buf;

  rc =
    PR_Recv(backend->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 */
}

static void close_one(struct ssl_connect_data *connssl)
{
  /* before the cleanup, check whether we are using a client certificate */
  struct ssl_backend_data *backend = connssl->backend;
  const bool client_cert = (backend->client_nickname != NULL)
    || (backend->obj_clicert != NULL);

  free(backend->client_nickname);
1543
1544
1545
1546
1547
1548
1549

1550
1551
1552
1553
1554
1555
1556
1557

1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
    backend->handle = NULL;
  }
}

/*
 * This function is called when an SSL connection is closed.
 */

static void Curl_nss_close(struct connectdata *conn, int sockindex)
{
  struct ssl_connect_data *connssl = &conn->ssl[sockindex];
#ifndef CURL_DISABLE_PROXY
  struct ssl_connect_data *connssl_proxy = &conn->proxy_ssl[sockindex];
#endif
  struct ssl_backend_data *backend = connssl->backend;


  if(backend->handle
#ifndef CURL_DISABLE_PROXY
    || connssl_proxy->backend->handle
#endif
    ) {
    /* 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;
  }

#ifndef CURL_DISABLE_PROXY
  if(backend->handle)
    /* nss_close(connssl) will transitively close also
       connssl_proxy->backend->handle if both are used. Clear it to avoid
       a double close leading to crash. */
    connssl_proxy->backend->handle = NULL;

  nss_close(connssl_proxy);
#endif
  nss_close(connssl);
}

/* return true if NSS can provide error code (and possibly msg) for the
   error */
static bool is_nss_error(CURLcode err)
{
  switch(err) {







>
|







>


















|

|







1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
    backend->handle = NULL;
  }
}

/*
 * This function is called when an SSL connection is closed.
 */
static void nss_close(struct Curl_easy *data, struct connectdata *conn,
                      int sockindex)
{
  struct ssl_connect_data *connssl = &conn->ssl[sockindex];
#ifndef CURL_DISABLE_PROXY
  struct ssl_connect_data *connssl_proxy = &conn->proxy_ssl[sockindex];
#endif
  struct ssl_backend_data *backend = connssl->backend;

  (void)data;
  if(backend->handle
#ifndef CURL_DISABLE_PROXY
    || connssl_proxy->backend->handle
#endif
    ) {
    /* 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;
  }

#ifndef CURL_DISABLE_PROXY
  if(backend->handle)
    /* nss_close(connssl) will transitively close also
       connssl_proxy->backend->handle if both are used. Clear it to avoid
       a double close leading to crash. */
    connssl_proxy->backend->handle = NULL;

  close_one(connssl_proxy);
#endif
  close_one(connssl);
}

/* return true if NSS can provide error code (and possibly msg) for the
   error */
static bool is_nss_error(CURLcode err)
{
  switch(err) {
1607
1608
1609
1610
1611
1612
1613
1614

1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
    return false;
  }
}

static Curl_recv nss_recv;
static Curl_send nss_send;

static CURLcode nss_load_ca_certificates(struct connectdata *conn,

                                         int sockindex)
{
  struct Curl_easy *data = conn->data;
  const char *cafile = SSL_CONN_CONFIG(CAfile);
  const char *capath = SSL_CONN_CONFIG(CApath);
  bool use_trust_module;
  CURLcode result = CURLE_OK;

  /* treat empty string as unset */
  if(cafile && !cafile[0])







|
>


<







1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618

1619
1620
1621
1622
1623
1624
1625
    return false;
  }
}

static Curl_recv nss_recv;
static Curl_send nss_send;

static CURLcode nss_load_ca_certificates(struct Curl_easy *data,
                                         struct connectdata *conn,
                                         int sockindex)
{

  const char *cafile = SSL_CONN_CONFIG(CAfile);
  const char *capath = SSL_CONN_CONFIG(CApath);
  bool use_trust_module;
  CURLcode result = CURLE_OK;

  /* treat empty string as unset */
  if(cafile && !cafile[0])
1815
1816
1817
1818
1819
1820
1821
1822

1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836

  if(PR_SetSocketOption(backend->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 Curl_easy *data = conn->data;
  curl_socket_t sockfd = conn->sock[sockindex];
  struct ssl_connect_data *connssl = &conn->ssl[sockindex];
  struct ssl_backend_data *backend = connssl->backend;
  CURLcode result;
  bool second_layer = FALSE;
  SSLVersionRange sslver_supported;








|
>






<







1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830

1831
1832
1833
1834
1835
1836
1837

  if(PR_SetSocketOption(backend->handle, &sock_opt) != PR_SUCCESS)
    return nss_fail_connect(connssl, data, CURLE_SSL_CONNECT_ERROR);

  return CURLE_OK;
}

static CURLcode nss_setup_connect(struct Curl_easy *data,
                                  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;

  curl_socket_t sockfd = conn->sock[sockindex];
  struct ssl_connect_data *connssl = &conn->ssl[sockindex];
  struct ssl_backend_data *backend = connssl->backend;
  CURLcode result;
  bool second_layer = FALSE;
  SSLVersionRange sslver_supported;

1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
#else
    SSL_LIBRARY_VERSION_TLS_1_0
#endif
  };

  backend->data = data;

  /* list of all NSS objects we need to destroy in Curl_nss_close() */
  Curl_llist_init(&backend->obj_list, nss_destroy_object);

  PR_Lock(nss_initlock);
  result = nss_init(conn->data);
  if(result) {
    PR_Unlock(nss_initlock);
    goto error;
  }

  PK11_SetPasswordFunc(nss_get_password);








|



|







1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
#else
    SSL_LIBRARY_VERSION_TLS_1_0
#endif
  };

  backend->data = data;

  /* list of all NSS objects we need to destroy in nss_do_close() */
  Curl_llist_init(&backend->obj_list, nss_destroy_object);

  PR_Lock(nss_initlock);
  result = nss_setup(data);
  if(result) {
    PR_Unlock(nss_initlock);
    goto error;
  }

  PK11_SetPasswordFunc(nss_get_password);

1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
  }

  if(!SSL_CONN_CONFIG(verifypeer) && SSL_CONN_CONFIG(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;

  /* not checked yet */
  SSL_SET_OPTION_LVALUE(certverifyresult) = 0;

  if(SSL_BadCertHook(model, BadCertHandler, conn) != SECSuccess)
    goto error;

  if(SSL_HandshakeCallback(model, HandshakeCallback, conn) != SECSuccess)
    goto error;

  {
    const CURLcode rv = nss_load_ca_certificates(conn, sockindex);
    if((rv == CURLE_SSL_CACERT_BADFILE) && !SSL_CONN_CONFIG(verifypeer))
      /* not a fatal error because we are not going to verify the peer */
      infof(data, "warning: CA certificates failed to load\n");
    else if(rv) {
      result = rv;
      goto error;
    }







|





|


|



|







1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
  }

  if(!SSL_CONN_CONFIG(verifypeer) && SSL_CONN_CONFIG(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, data) != SECSuccess)
    goto error;

  /* not checked yet */
  SSL_SET_OPTION_LVALUE(certverifyresult) = 0;

  if(SSL_BadCertHook(model, BadCertHandler, data) != SECSuccess)
    goto error;

  if(SSL_HandshakeCallback(model, HandshakeCallback, data) != SECSuccess)
    goto error;

  {
    const CURLcode rv = nss_load_ca_certificates(data, conn, sockindex);
    if((rv == CURLE_SSL_CACERT_BADFILE) && !SSL_CONN_CONFIG(verifypeer))
      /* not a fatal error because we are not going to verify the peer */
      infof(data, "warning: CA certificates failed to load\n");
    else if(rv) {
      result = rv;
      goto error;
    }
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
  if(SSL_SET_OPTION(primary.clientcert)) {
    char *nickname = dup_nickname(data, SSL_SET_OPTION(primary.clientcert));
    if(nickname) {
      /* we are not going to use libnsspem.so to read the client cert */
      backend->obj_clicert = NULL;
    }
    else {
      CURLcode rv = cert_stuff(conn, sockindex,
                               SSL_SET_OPTION(primary.clientcert),
                               SSL_SET_OPTION(key));
      if(rv) {
        /* failf() is already done in cert_stuff() */
        result = rv;
        goto error;
      }







|







1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
  if(SSL_SET_OPTION(primary.clientcert)) {
    char *nickname = dup_nickname(data, SSL_SET_OPTION(primary.clientcert));
    if(nickname) {
      /* we are not going to use libnsspem.so to read the client cert */
      backend->obj_clicert = NULL;
    }
    else {
      CURLcode rv = cert_stuff(data, conn, sockindex,
                               SSL_SET_OPTION(primary.clientcert),
                               SSL_SET_OPTION(key));
      if(rv) {
        /* failf() is already done in cert_stuff() */
        result = rv;
        goto error;
      }
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
#if NSSVERNUM >= 0x030f04 /* 3.15.4 */
  if(data->set.ssl.falsestart) {
    if(SSL_OptionSet(backend->handle, SSL_ENABLE_FALSE_START, PR_TRUE)
        != SECSuccess)
      goto error;

    if(SSL_SetCanFalseStartCallback(backend->handle, CanFalseStartCallback,
        conn) != SECSuccess)
      goto error;
  }
#endif

#if defined(SSL_ENABLE_NPN) || defined(SSL_ENABLE_ALPN)
  if(conn->bits.tls_enable_npn || conn->bits.tls_enable_alpn) {
    int cur = 0;







|







2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
#if NSSVERNUM >= 0x030f04 /* 3.15.4 */
  if(data->set.ssl.falsestart) {
    if(SSL_OptionSet(backend->handle, SSL_ENABLE_FALSE_START, PR_TRUE)
        != SECSuccess)
      goto error;

    if(SSL_SetCanFalseStartCallback(backend->handle, CanFalseStartCallback,
        data) != SECSuccess)
      goto error;
  }
#endif

#if defined(SSL_ENABLE_NPN) || defined(SSL_ENABLE_ALPN)
  if(conn->bits.tls_enable_npn || conn->bits.tls_enable_alpn) {
    int cur = 0;
2121
2122
2123
2124
2125
2126
2127
2128

2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
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 ssl_backend_data *backend = connssl->backend;
  struct Curl_easy *data = conn->data;
  CURLcode result = CURLE_SSL_CONNECT_ERROR;
  PRUint32 timeout;

  /* check timeout situation */
  const timediff_t time_left = Curl_timeleft(data, NULL, TRUE);
  if(time_left < 0) {
    failf(data, "timed out before SSL handshake");







|
>



<







2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133

2134
2135
2136
2137
2138
2139
2140
error:
  if(model)
    PR_Close(model);

  return nss_fail_connect(connssl, data, result);
}

static CURLcode nss_do_connect(struct Curl_easy *data,
                               struct connectdata *conn, int sockindex)
{
  struct ssl_connect_data *connssl = &conn->ssl[sockindex];
  struct ssl_backend_data *backend = connssl->backend;

  CURLcode result = CURLE_SSL_CONNECT_ERROR;
  PRUint32 timeout;

  /* check timeout situation */
  const timediff_t time_left = Curl_timeleft(data, NULL, TRUE);
  if(time_left < 0) {
    failf(data, "timed out before SSL handshake");
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
    else if(SSL_SET_OPTION(certverifyresult) == SSL_ERROR_BAD_CERT_DOMAIN)
      result = CURLE_PEER_FAILED_VERIFICATION;
    else if(SSL_SET_OPTION(certverifyresult) != 0)
      result = CURLE_PEER_FAILED_VERIFICATION;
    goto error;
  }

  result = display_conn_info(conn, backend->handle);
  if(result)
    goto error;

  if(SSL_SET_OPTION(issuercert)) {
    SECStatus ret = SECFailure;
    char *nickname = dup_nickname(data, SSL_SET_OPTION(issuercert));
    if(nickname) {







|







2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
    else if(SSL_SET_OPTION(certverifyresult) == SSL_ERROR_BAD_CERT_DOMAIN)
      result = CURLE_PEER_FAILED_VERIFICATION;
    else if(SSL_SET_OPTION(certverifyresult) != 0)
      result = CURLE_PEER_FAILED_VERIFICATION;
    goto error;
  }

  result = display_conn_info(data, backend->handle);
  if(result)
    goto error;

  if(SSL_SET_OPTION(issuercert)) {
    SECStatus ret = SECFailure;
    char *nickname = dup_nickname(data, SSL_SET_OPTION(issuercert));
    if(nickname) {
2184
2185
2186
2187
2188
2189
2190
2191

2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226

  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 Curl_easy *data = conn->data;
  const bool blocking = (done == NULL);
  CURLcode result;

  if(connssl->state == ssl_connection_complete) {
    if(!blocking)
      *done = TRUE;
    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;

    connssl->connecting_state = ssl_connect_2;
  }

  /* enable/disable blocking mode before handshake */
  result = nss_set_blocking(connssl, data, blocking);
  if(result)
    return result;

  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;







|
>



<










|












|







2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196

2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227

  return CURLE_OK;

error:
  return nss_fail_connect(connssl, data, result);
}

static CURLcode nss_connect_common(struct Curl_easy *data,
                                   struct connectdata *conn, int sockindex,
                                   bool *done)
{
  struct ssl_connect_data *connssl = &conn->ssl[sockindex];

  const bool blocking = (done == NULL);
  CURLcode result;

  if(connssl->state == ssl_connection_complete) {
    if(!blocking)
      *done = TRUE;
    return CURLE_OK;
  }

  if(connssl->connecting_state == ssl_connect_1) {
    result = nss_setup_connect(data, conn, sockindex);
    if(result)
      /* we do not expect CURLE_AGAIN from nss_setup_connect() */
      return result;

    connssl->connecting_state = ssl_connect_2;
  }

  /* enable/disable blocking mode before handshake */
  result = nss_set_blocking(connssl, data, blocking);
  if(result)
    return result;

  result = nss_do_connect(data, 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;
2245
2246
2247
2248
2249
2250
2251

2252
2253
2254
2255
2256

2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268

2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306

2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
2370
2371
2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
2384
2385
2386
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
2450
2451
2452
2453
2454
2455
2456
2457
2458
2459
2460
2461
2462
2463
2464

  /* ssl_connect_done is never used outside, go back to the initial state */
  connssl->connecting_state = ssl_connect_1;

  return CURLE_OK;
}


static CURLcode Curl_nss_connect(struct connectdata *conn, int sockindex)
{
  return nss_connect_common(conn, sockindex, /* blocking */ NULL);
}


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)
{

  struct ssl_connect_data *connssl = &conn->ssl[sockindex];
  struct ssl_backend_data *backend = connssl->backend;
  ssize_t rc;

  /* The SelectClientCert() hook uses this for infof() and failf() but the
     handle stored in nss_setup_connect() could have already been freed. */
  backend->data = conn->data;

  rc = PR_Send(backend->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 sockindex,             /* socketindex */
                        char *buf,                 /* store read data here */
                        size_t buffersize,         /* max amount to read */
                        CURLcode *curlcode)
{

  struct ssl_connect_data *connssl = &conn->ssl[sockindex];
  struct ssl_backend_data *backend = connssl->backend;
  ssize_t nread;

  /* The SelectClientCert() hook uses this for infof() and failf() but the
     handle stored in nss_setup_connect() could have already been freed. */
  backend->data = conn->data;

  nread = PR_Recv(backend->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;
}

static size_t Curl_nss_version(char *buffer, size_t size)
{
  return msnprintf(buffer, size, "NSS/%s", NSS_VERSION);
}

/* data might be NULL */
static int Curl_nss_seed(struct Curl_easy *data)
{
  /* make sure that NSS is initialized */
  return !!Curl_nss_force_init(data);
}

/* data might be NULL */
static CURLcode Curl_nss_random(struct Curl_easy *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 CURLE_FAILED_INIT;

  return CURLE_OK;
}

static CURLcode 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;

  if(!MD5pw)
    return CURLE_NOT_BUILT_IN;

  PK11_DigestOp(MD5pw, tmp, curlx_uztoui(tmplen));
  PK11_DigestFinal(MD5pw, md5sum, &MD5out, curlx_uztoui(md5len));
  PK11_DestroyContext(MD5pw, PR_TRUE);

  return CURLE_OK;
}

static CURLcode Curl_nss_sha256sum(const unsigned char *tmp, /* input */
                               size_t tmplen,
                               unsigned char *sha256sum, /* output */
                               size_t sha256len)
{
  PK11Context *SHA256pw = PK11_CreateDigestContext(SEC_OID_SHA256);
  unsigned int SHA256out;

  if(!SHA256pw)
    return CURLE_NOT_BUILT_IN;

  PK11_DigestOp(SHA256pw, tmp, curlx_uztoui(tmplen));
  PK11_DigestFinal(SHA256pw, sha256sum, &SHA256out, curlx_uztoui(sha256len));
  PK11_DestroyContext(SHA256pw, PR_TRUE);

  return CURLE_OK;
}

static bool Curl_nss_cert_status_request(void)
{
#ifdef SSL_ENABLE_OCSP_STAPLING
  return TRUE;
#else
  return FALSE;
#endif
}

static bool Curl_nss_false_start(void)
{
#if NSSVERNUM >= 0x030f04 /* 3.15.4 */
  return TRUE;
#else
  return FALSE;
#endif
}

static void *Curl_nss_get_internals(struct ssl_connect_data *connssl,
                                    CURLINFO info UNUSED_PARAM)
{
  struct ssl_backend_data *backend = connssl->backend;
  (void)info;
  return backend->handle;
}

const struct Curl_ssl Curl_ssl_nss = {
  { CURLSSLBACKEND_NSS, "nss" }, /* info */

  SSLSUPP_CA_PATH |
  SSLSUPP_CERTINFO |
  SSLSUPP_PINNEDPUBKEY |
  SSLSUPP_HTTPS_PROXY,

  sizeof(struct ssl_backend_data),

  Curl_nss_init,                /* init */
  Curl_nss_cleanup,             /* cleanup */
  Curl_nss_version,             /* version */
  Curl_nss_check_cxn,           /* check_cxn */
  /* NSS has no shutdown function provided and thus always fail */
  Curl_none_shutdown,           /* shutdown */
  Curl_none_data_pending,       /* data_pending */
  Curl_nss_random,              /* random */
  Curl_nss_cert_status_request, /* cert_status_request */
  Curl_nss_connect,             /* connect */
  Curl_nss_connect_nonblocking, /* connect_nonblocking */
  Curl_nss_get_internals,       /* get_internals */
  Curl_nss_close,               /* close_one */
  Curl_none_close_all,          /* close_all */
  /* NSS has its own session ID cache */
  Curl_none_session_free,       /* session_free */
  Curl_none_set_engine,         /* set_engine */
  Curl_none_set_engine_default, /* set_engine_default */
  Curl_none_engines_list,       /* engines_list */
  Curl_nss_false_start,         /* false_start */
  Curl_nss_md5sum,              /* md5sum */
  Curl_nss_sha256sum            /* sha256sum */
};

#endif /* USE_NSS */







>
|

|


>
|
|

|


|





>






|









|


|












|

|
|


>






|












|


|












|

|










|
|
|










<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
|
|
|














|








|








|

















|
|
|
|



|
|
|
|
|
|






|
<
|



2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
2370
2371
2372


















2373
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
2384
2385
2386
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
2445
2446

2447
2448
2449
2450

  /* ssl_connect_done is never used outside, go back to the initial state */
  connssl->connecting_state = ssl_connect_1;

  return CURLE_OK;
}

static CURLcode nss_connect(struct Curl_easy *data, struct connectdata *conn,
                            int sockindex)
{
  return nss_connect_common(data, conn, sockindex, /* blocking */ NULL);
}

static CURLcode nss_connect_nonblocking(struct Curl_easy *data,
                                        struct connectdata *conn,
                                        int sockindex, bool *done)
{
  return nss_connect_common(data, conn, sockindex, done);
}

static ssize_t nss_send(struct Curl_easy *data,    /* transfer */
                        int sockindex,             /* socketindex */
                        const void *mem,           /* send this data */
                        size_t len,                /* amount to write */
                        CURLcode *curlcode)
{
  struct connectdata *conn = data->conn;
  struct ssl_connect_data *connssl = &conn->ssl[sockindex];
  struct ssl_backend_data *backend = connssl->backend;
  ssize_t rc;

  /* The SelectClientCert() hook uses this for infof() and failf() but the
     handle stored in nss_setup_connect() could have already been freed. */
  backend->data = data;

  rc = PR_Send(backend->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(data, "SSL write: error %d (%s)\n", err, err_name);

      /* print a human-readable message describing the error if available */
      nss_print_error_message(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 Curl_easy *data,    /* transfer */
                        int sockindex,             /* socketindex */
                        char *buf,             /* store read data here */
                        size_t buffersize,     /* max amount to read */
                        CURLcode *curlcode)
{
  struct connectdata *conn = data->conn;
  struct ssl_connect_data *connssl = &conn->ssl[sockindex];
  struct ssl_backend_data *backend = connssl->backend;
  ssize_t nread;

  /* The SelectClientCert() hook uses this for infof() and failf() but the
     handle stored in nss_setup_connect() could have already been freed. */
  backend->data = data;

  nread = PR_Recv(backend->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(data, "SSL read: errno %d (%s)\n", err, err_name);

      /* print a human-readable message describing the error if available */
      nss_print_error_message(data, err);

      *curlcode = (is_cc_error(err))
        ? CURLE_SSL_CERTPROBLEM
        : CURLE_RECV_ERROR;
    }

    return -1;
  }

  return nread;
}

static size_t nss_version(char *buffer, size_t size)
{
  return msnprintf(buffer, size, "NSS/%s", NSS_GetVersion());
}

/* data might be NULL */
static int Curl_nss_seed(struct Curl_easy *data)
{
  /* make sure that NSS is initialized */
  return !!Curl_nss_force_init(data);
}

/* data might be NULL */
static CURLcode nss_random(struct Curl_easy *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 CURLE_FAILED_INIT;

  return CURLE_OK;
}



















static CURLcode nss_sha256sum(const unsigned char *tmp, /* input */
                              size_t tmplen,
                              unsigned char *sha256sum, /* output */
                              size_t sha256len)
{
  PK11Context *SHA256pw = PK11_CreateDigestContext(SEC_OID_SHA256);
  unsigned int SHA256out;

  if(!SHA256pw)
    return CURLE_NOT_BUILT_IN;

  PK11_DigestOp(SHA256pw, tmp, curlx_uztoui(tmplen));
  PK11_DigestFinal(SHA256pw, sha256sum, &SHA256out, curlx_uztoui(sha256len));
  PK11_DestroyContext(SHA256pw, PR_TRUE);

  return CURLE_OK;
}

static bool nss_cert_status_request(void)
{
#ifdef SSL_ENABLE_OCSP_STAPLING
  return TRUE;
#else
  return FALSE;
#endif
}

static bool nss_false_start(void)
{
#if NSSVERNUM >= 0x030f04 /* 3.15.4 */
  return TRUE;
#else
  return FALSE;
#endif
}

static void *nss_get_internals(struct ssl_connect_data *connssl,
                                    CURLINFO info UNUSED_PARAM)
{
  struct ssl_backend_data *backend = connssl->backend;
  (void)info;
  return backend->handle;
}

const struct Curl_ssl Curl_ssl_nss = {
  { CURLSSLBACKEND_NSS, "nss" }, /* info */

  SSLSUPP_CA_PATH |
  SSLSUPP_CERTINFO |
  SSLSUPP_PINNEDPUBKEY |
  SSLSUPP_HTTPS_PROXY,

  sizeof(struct ssl_backend_data),

  nss_init,                     /* init */
  nss_cleanup,                  /* cleanup */
  nss_version,                  /* version */
  nss_check_cxn,                /* check_cxn */
  /* NSS has no shutdown function provided and thus always fail */
  Curl_none_shutdown,           /* shutdown */
  Curl_none_data_pending,       /* data_pending */
  nss_random,                   /* random */
  nss_cert_status_request,      /* cert_status_request */
  nss_connect,                  /* connect */
  nss_connect_nonblocking,      /* connect_nonblocking */
  nss_get_internals,            /* get_internals */
  nss_close,                    /* close_one */
  Curl_none_close_all,          /* close_all */
  /* NSS has its own session ID cache */
  Curl_none_session_free,       /* session_free */
  Curl_none_set_engine,         /* set_engine */
  Curl_none_set_engine_default, /* set_engine_default */
  Curl_none_engines_list,       /* engines_list */
  nss_false_start,              /* false_start */

  nss_sha256sum                 /* sha256sum */
};

#endif /* USE_NSS */
Changes to jni/curl/lib/vtls/openssl.c.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2020, 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 https://curl.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







|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2021, 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 https://curl.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
357
358
359
360
361
362
363












364
365
366
367
368
369
370
  if(size > 1 && !*buf) {
    strncpy(buf, (error ? "Unknown error" : "No error"), size);
    buf[size - 1] = '\0';
  }

  return buf;
}













/* Return an extra data index for the connection data.
 * This index can be used with SSL_get_ex_data() and SSL_set_ex_data().
 */
static int ossl_get_ssl_conn_index(void)
{
  static int ssl_ex_data_conn_index = -1;







>
>
>
>
>
>
>
>
>
>
>
>







357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
  if(size > 1 && !*buf) {
    strncpy(buf, (error ? "Unknown error" : "No error"), size);
    buf[size - 1] = '\0';
  }

  return buf;
}

/* Return an extra data index for the transfer data.
 * This index can be used with SSL_get_ex_data() and SSL_set_ex_data().
 */
static int ossl_get_ssl_data_index(void)
{
  static int ssl_ex_data_data_index = -1;
  if(ssl_ex_data_data_index < 0) {
    ssl_ex_data_data_index = SSL_get_ex_new_index(0, NULL, NULL, NULL, NULL);
  }
  return ssl_ex_data_data_index;
}

/* Return an extra data index for the connection data.
 * This index can be used with SSL_get_ex_data() and SSL_set_ex_data().
 */
static int ossl_get_ssl_conn_index(void)
{
  static int ssl_ex_data_conn_index = -1;
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
 * rand_enough() returns TRUE if we have seeded the random engine properly.
 */
static bool rand_enough(void)
{
  return (0 != RAND_status()) ? TRUE : FALSE;
}

static CURLcode Curl_ossl_seed(struct Curl_easy *data)
{
  /* we have the "SSL is seeded" boolean static to prevent multiple
     time-consuming seedings in vain */
  static bool ssl_seeded = FALSE;
  char fname[256];

  if(ssl_seeded)







|







418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
 * rand_enough() returns TRUE if we have seeded the random engine properly.
 */
static bool rand_enough(void)
{
  return (0 != RAND_status()) ? TRUE : FALSE;
}

static CURLcode ossl_seed(struct Curl_easy *data)
{
  /* we have the "SSL is seeded" boolean static to prevent multiple
     time-consuming seedings in vain */
  static bool ssl_seeded = FALSE;
  char fname[256];

  if(ssl_seeded)
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
static bool is_pkcs11_uri(const char *string)
{
  return (string && strncasecompare(string, "pkcs11:", 7));
}

#endif

static CURLcode Curl_ossl_set_engine(struct Curl_easy *data,
                                     const char *engine);

static int
SSL_CTX_use_certificate_bio(SSL_CTX *ctx, BIO *in, int type,
                            const char *key_passwd)
{
  int ret = 0;
  X509 *x = NULL;







|
<







580
581
582
583
584
585
586
587

588
589
590
591
592
593
594
static bool is_pkcs11_uri(const char *string)
{
  return (string && strncasecompare(string, "pkcs11:", 7));
}

#endif

static CURLcode ossl_set_engine(struct Curl_easy *data, const char *engine);


static int
SSL_CTX_use_certificate_bio(SSL_CTX *ctx, BIO *in, int type,
                            const char *key_passwd)
{
  int ret = 0;
  X509 *x = NULL;
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
  (void)in; /* unused */
  (void)key_passwd; /* unused */
  return 0;
#endif
}

static
int cert_stuff(struct connectdata *conn,
               SSL_CTX* ctx,
               char *cert_file,
               BIO *cert_bio,
               const char *cert_type,
               char *key_file,
               BIO* key_bio,
               const char *key_type,
               char *key_passwd)
{
  struct Curl_easy *data = conn->data;
  char error_buffer[256];
  bool check_privkey = TRUE;

  int file_type = do_file_type(cert_type);

  if(cert_file || cert_bio || (file_type == SSL_FILETYPE_ENGINE)) {
    SSL *ssl;







|









<







707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723

724
725
726
727
728
729
730
  (void)in; /* unused */
  (void)key_passwd; /* unused */
  return 0;
#endif
}

static
int cert_stuff(struct Curl_easy *data,
               SSL_CTX* ctx,
               char *cert_file,
               BIO *cert_bio,
               const char *cert_type,
               char *key_file,
               BIO* key_bio,
               const char *key_type,
               char *key_passwd)
{

  char error_buffer[256];
  bool check_privkey = TRUE;

  int file_type = do_file_type(cert_type);

  if(cert_file || cert_bio || (file_type == SSL_FILETYPE_ENGINE)) {
    SSL *ssl;
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
    case SSL_FILETYPE_ENGINE:
#if defined(USE_OPENSSL_ENGINE) && defined(ENGINE_CTRL_GET_CMD_FROM_NAME)
      {
        /* Implicitly use pkcs11 engine if none was provided and the
         * cert_file is a PKCS#11 URI */
        if(!data->state.engine) {
          if(is_pkcs11_uri(cert_file)) {
            if(Curl_ossl_set_engine(data, "pkcs11") != CURLE_OK) {
              return 0;
            }
          }
        }

        if(data->state.engine) {
          const char *cmd_name = "LOAD_CERT_CTRL";







|







779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
    case SSL_FILETYPE_ENGINE:
#if defined(USE_OPENSSL_ENGINE) && defined(ENGINE_CTRL_GET_CMD_FROM_NAME)
      {
        /* Implicitly use pkcs11 engine if none was provided and the
         * cert_file is a PKCS#11 URI */
        if(!data->state.engine) {
          if(is_pkcs11_uri(cert_file)) {
            if(ossl_set_engine(data, "pkcs11") != CURLE_OK) {
              return 0;
            }
          }
        }

        if(data->state.engine) {
          const char *cmd_name = "LOAD_CERT_CTRL";
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
      {                         /* XXXX still needs some work */
        EVP_PKEY *priv_key = NULL;

        /* Implicitly use pkcs11 engine if none was provided and the
         * key_file is a PKCS#11 URI */
        if(!data->state.engine) {
          if(is_pkcs11_uri(key_file)) {
            if(Curl_ossl_set_engine(data, "pkcs11") != CURLE_OK) {
              return 0;
            }
          }
        }

        if(data->state.engine) {
          UI_METHOD *ui_method =







|







978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
      {                         /* XXXX still needs some work */
        EVP_PKEY *priv_key = NULL;

        /* Implicitly use pkcs11 engine if none was provided and the
         * key_file is a PKCS#11 URI */
        if(!data->state.engine) {
          if(is_pkcs11_uri(key_file)) {
            if(ossl_set_engine(data, "pkcs11") != CURLE_OK) {
              return 0;
            }
          }
        }

        if(data->state.engine) {
          UI_METHOD *ui_method =
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123

/**
 * Global SSL init
 *
 * @retval 0 error initializing SSL
 * @retval 1 SSL initialized successfully
 */
static int Curl_ossl_init(void)
{
#if (OPENSSL_VERSION_NUMBER >= 0x10100000L) &&  \
  !defined(LIBRESSL_VERSION_NUMBER)
  const uint64_t flags =
#ifdef OPENSSL_INIT_ENGINE_ALL_BUILTIN
    /* not present in BoringSSL */
    OPENSSL_INIT_ENGINE_ALL_BUILTIN |







|







1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133

/**
 * Global SSL init
 *
 * @retval 0 error initializing SSL
 * @retval 1 SSL initialized successfully
 */
static int ossl_init(void)
{
#if (OPENSSL_VERSION_NUMBER >= 0x10100000L) &&  \
  !defined(LIBRESSL_VERSION_NUMBER)
  const uint64_t flags =
#ifdef OPENSSL_INIT_ENGINE_ALL_BUILTIN
    /* not present in BoringSSL */
    OPENSSL_INIT_ENGINE_ALL_BUILTIN |
1157
1158
1159
1160
1161
1162
1163

1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178

  OpenSSL_add_all_algorithms();
#endif

  Curl_tls_keylog_open();

  /* Initialize the extra data indexes */

  if(ossl_get_ssl_conn_index() < 0 || ossl_get_ssl_sockindex_index() < 0)
    return 0;

  return 1;
}

/* Global cleanup */
static void Curl_ossl_cleanup(void)
{
#if (OPENSSL_VERSION_NUMBER >= 0x10100000L) && \
    !defined(LIBRESSL_VERSION_NUMBER)
  /* OpenSSL 1.1 deprecates all these cleanup functions and
     turns them into no-ops in OpenSSL 1.0 compatibility mode */
#else
  /* Free ciphers and digests lists */







>
|






|







1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189

  OpenSSL_add_all_algorithms();
#endif

  Curl_tls_keylog_open();

  /* Initialize the extra data indexes */
  if(ossl_get_ssl_data_index() < 0 || ossl_get_ssl_conn_index() < 0 ||
     ossl_get_ssl_sockindex_index() < 0)
    return 0;

  return 1;
}

/* Global cleanup */
static void ossl_cleanup(void)
{
#if (OPENSSL_VERSION_NUMBER >= 0x10100000L) && \
    !defined(LIBRESSL_VERSION_NUMBER)
  /* OpenSSL 1.1 deprecates all these cleanup functions and
     turns them into no-ops in OpenSSL 1.0 compatibility mode */
#else
  /* Free ciphers and digests lists */
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
 * This function is used 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
 */
static int Curl_ossl_check_cxn(struct connectdata *conn)
{
  /* SSL_peek takes data out of the raw recv buffer without peeking so we use
     recv MSG_PEEK instead. Bug #795 */
#ifdef MSG_PEEK
  char buf;
  ssize_t nread;
  nread = recv((RECV_TYPE_ARG1)conn->sock[FIRSTSOCKET], (RECV_TYPE_ARG2)&buf,







|







1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
 * This function is used 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
 */
static int ossl_check_cxn(struct connectdata *conn)
{
  /* SSL_peek takes data out of the raw recv buffer without peeking so we use
     recv MSG_PEEK instead. Bug #795 */
#ifdef MSG_PEEK
  char buf;
  ssize_t nread;
  nread = recv((RECV_TYPE_ARG1)conn->sock[FIRSTSOCKET], (RECV_TYPE_ARG2)&buf,
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
  }
#endif
  return -1; /* connection status unknown */
}

/* Selects an OpenSSL crypto engine
 */
static CURLcode Curl_ossl_set_engine(struct Curl_easy *data,
                                     const char *engine)
{
#ifdef USE_OPENSSL_ENGINE
  ENGINE *e;

#if OPENSSL_VERSION_NUMBER >= 0x00909000L
  e = ENGINE_by_id(engine);
#else







|
<







1265
1266
1267
1268
1269
1270
1271
1272

1273
1274
1275
1276
1277
1278
1279
  }
#endif
  return -1; /* connection status unknown */
}

/* Selects an OpenSSL crypto engine
 */
static CURLcode ossl_set_engine(struct Curl_easy *data, const char *engine)

{
#ifdef USE_OPENSSL_ENGINE
  ENGINE *e;

#if OPENSSL_VERSION_NUMBER >= 0x00909000L
  e = ENGINE_by_id(engine);
#else
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
    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, ossl_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
 */
static CURLcode Curl_ossl_set_engine_default(struct Curl_easy *data)
{
#ifdef USE_OPENSSL_ENGINE
  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));
    }







|














|







1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
    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': %s",
          engine, ossl_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
 */
static CURLcode ossl_set_engine_default(struct Curl_easy *data)
{
#ifdef USE_OPENSSL_ENGINE
  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));
    }
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367

1368
1369

1370
1371
1372
1373
1374
1375
1376
1377
1378
1379

1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
  (void) data;
#endif
  return CURLE_OK;
}

/* Return list of OpenSSL crypto engine names.
 */
static struct curl_slist *Curl_ossl_engines_list(struct Curl_easy *data)
{
  struct curl_slist *list = NULL;
#ifdef USE_OPENSSL_ENGINE
  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;
}

static void ossl_close(struct ssl_connect_data *connssl)
{
  struct ssl_backend_data *backend = connssl->backend;
  if(backend->handle) {
    (void)SSL_shutdown(backend->handle);
    SSL_set_connect_state(backend->handle);

    SSL_free(backend->handle);
    backend->handle = NULL;
  }
  if(backend->ctx) {
    SSL_CTX_free(backend->ctx);
    backend->ctx = NULL;
  }
}

/*
 * This function is called when an SSL connection is closed.
 */

static void Curl_ossl_close(struct connectdata *conn, int sockindex)
{

  ossl_close(&conn->ssl[sockindex]);
#ifndef CURL_DISABLE_PROXY
  ossl_close(&conn->proxy_ssl[sockindex]);
#endif
}

/*
 * This function is called to shut down the SSL layer but keep the
 * socket open (CCC - Clear Command Channel)
 */

static int Curl_ossl_shutdown(struct connectdata *conn, int sockindex)
{
  int retval = 0;
  struct ssl_connect_data *connssl = &conn->ssl[sockindex];
  struct Curl_easy *data = conn->data;
  char buf[256]; /* We will use this for the OpenSSL error buffer, so it has
                    to be at least 256 bytes long. */
  unsigned long sslerror;
  ssize_t nread;
  int buffsize;
  int err;
  bool done = FALSE;







|



















|


















>
|

>
|

|







>
|



<







1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396

1397
1398
1399
1400
1401
1402
1403
  (void) data;
#endif
  return CURLE_OK;
}

/* Return list of OpenSSL crypto engine names.
 */
static struct curl_slist *ossl_engines_list(struct Curl_easy *data)
{
  struct curl_slist *list = NULL;
#ifdef USE_OPENSSL_ENGINE
  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;
}

static void ossl_closeone(struct ssl_connect_data *connssl)
{
  struct ssl_backend_data *backend = connssl->backend;
  if(backend->handle) {
    (void)SSL_shutdown(backend->handle);
    SSL_set_connect_state(backend->handle);

    SSL_free(backend->handle);
    backend->handle = NULL;
  }
  if(backend->ctx) {
    SSL_CTX_free(backend->ctx);
    backend->ctx = NULL;
  }
}

/*
 * This function is called when an SSL connection is closed.
 */
static void ossl_close(struct Curl_easy *data, struct connectdata *conn,
                       int sockindex)
{
  (void) data;
  ossl_closeone(&conn->ssl[sockindex]);
#ifndef CURL_DISABLE_PROXY
  ossl_closeone(&conn->proxy_ssl[sockindex]);
#endif
}

/*
 * This function is called to shut down the SSL layer but keep the
 * socket open (CCC - Clear Command Channel)
 */
static int ossl_shutdown(struct Curl_easy *data,
                         struct connectdata *conn, int sockindex)
{
  int retval = 0;
  struct ssl_connect_data *connssl = &conn->ssl[sockindex];

  char buf[256]; /* We will use this for the OpenSSL error buffer, so it has
                    to be at least 256 bytes long. */
  unsigned long sslerror;
  ssize_t nread;
  int buffsize;
  int err;
  bool done = FALSE;
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
          /* SSL wants a write. Really odd. Let's bail out. */
          infof(data, "SSL_ERROR_WANT_WRITE\n");
          done = TRUE;
          break;
        default:
          /* openssl/ssl.h says "look at error stack/return value/errno" */
          sslerror = ERR_get_error();
          failf(conn->data, OSSL_PACKAGE " SSL_read on shutdown: %s, errno %d",
                (sslerror ?
                 ossl_strerror(sslerror, buf, sizeof(buf)) :
                 SSL_ERROR_to_str(err)),
                SOCKERRNO);
          done = TRUE;
          break;
        }







|







1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
          /* SSL wants a write. Really odd. Let's bail out. */
          infof(data, "SSL_ERROR_WANT_WRITE\n");
          done = TRUE;
          break;
        default:
          /* openssl/ssl.h says "look at error stack/return value/errno" */
          sslerror = ERR_get_error();
          failf(data, OSSL_PACKAGE " SSL_read on shutdown: %s, errno %d",
                (sslerror ?
                 ossl_strerror(sslerror, buf, sizeof(buf)) :
                 SSL_ERROR_to_str(err)),
                SOCKERRNO);
          done = TRUE;
          break;
        }
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498

    SSL_free(backend->handle);
    backend->handle = NULL;
  }
  return retval;
}

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!
 */
static void Curl_ossl_close_all(struct Curl_easy *data)
{
#ifdef USE_OPENSSL_ENGINE
  if(data->state.engine) {
    ENGINE_finish(data->state.engine);
    ENGINE_free(data->state.engine);
    data->state.engine = NULL;
  }







|









|







1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510

    SSL_free(backend->handle);
    backend->handle = NULL;
  }
  return retval;
}

static void 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!
 */
static void ossl_close_all(struct Curl_easy *data)
{
#ifdef USE_OPENSSL_ENGINE
  if(data->state.engine) {
    ENGINE_finish(data->state.engine);
    ENGINE_free(data->state.engine);
    data->state.engine = NULL;
  }
1578
1579
1580
1581
1582
1583
1584
1585

1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
   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)

{
  bool matched = FALSE;
  int target = GEN_DNS; /* target type, GEN_DNS or GEN_IPADD */
  size_t addrlen = 0;
  struct Curl_easy *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;







|
>




<







1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602

1603
1604
1605
1606
1607
1608
1609
   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 Curl_easy *data, struct connectdata *conn,
                           X509 *server_cert)
{
  bool matched = FALSE;
  int target = GEN_DNS; /* target type, GEN_DNS or GEN_IPADD */
  size_t addrlen = 0;

  STACK_OF(GENERAL_NAME) *altnames;
#ifdef ENABLE_IPV6
  struct in6_addr addr;
#else
  struct in_addr addr;
#endif
  CURLcode result = CURLE_OK;
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
  }

  return result;
}

#if (OPENSSL_VERSION_NUMBER >= 0x0090808fL) && !defined(OPENSSL_NO_TLSEXT) && \
    !defined(OPENSSL_NO_OCSP)
static CURLcode verifystatus(struct connectdata *conn,
                             struct ssl_connect_data *connssl)
{
  int i, ocsp_status;
  unsigned char *status;
  const unsigned char *p;
  CURLcode result = CURLE_OK;
  struct Curl_easy *data = conn->data;
  OCSP_RESPONSE *rsp = NULL;
  OCSP_BASICRESP *br = NULL;
  X509_STORE     *st = NULL;
  STACK_OF(X509) *ch = NULL;
  struct ssl_backend_data *backend = connssl->backend;
  X509 *cert;
  OCSP_CERTID *id = NULL;







|






<







1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803

1804
1805
1806
1807
1808
1809
1810
  }

  return result;
}

#if (OPENSSL_VERSION_NUMBER >= 0x0090808fL) && !defined(OPENSSL_NO_TLSEXT) && \
    !defined(OPENSSL_NO_OCSP)
static CURLcode verifystatus(struct Curl_easy *data,
                             struct ssl_connect_data *connssl)
{
  int i, ocsp_status;
  unsigned char *status;
  const unsigned char *p;
  CURLcode result = CURLE_OK;

  OCSP_RESPONSE *rsp = NULL;
  OCSP_BASICRESP *br = NULL;
  X509_STORE     *st = NULL;
  STACK_OF(X509) *ch = NULL;
  struct ssl_backend_data *backend = connssl->backend;
  X509 *cert;
  OCSP_CERTID *id = NULL;
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
    result = CURLE_SSL_INVALIDCERTSTATUS;
    goto end;
  }

  /* Compute the certificate's ID */
  cert = SSL_get_peer_certificate(backend->handle);
  if(!cert) {
    failf(data, "Error getting peer certficate");
    result = CURLE_SSL_INVALIDCERTSTATUS;
    goto end;
  }

  for(i = 0; i < sk_X509_num(ch); i++) {
    X509 *issuer = sk_X509_value(ch, i);
    if(X509_check_issued(issuer, cert) == X509_V_OK) {







|







1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
    result = CURLE_SSL_INVALIDCERTSTATUS;
    goto end;
  }

  /* Compute the certificate's ID */
  cert = SSL_get_peer_certificate(backend->handle);
  if(!cert) {
    failf(data, "Error getting peer certificate");
    result = CURLE_SSL_INVALIDCERTSTATUS;
    goto end;
  }

  for(i = 0; i < sk_X509_num(ch); i++) {
    X509 *issuer = sk_X509_value(ch, i);
    if(X509_check_issued(issuer, cert) == X509_V_OK) {
2202
2203
2204
2205
2206
2207
2208

2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238

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 &&
     !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;
    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 */







>
|
<



|


|








|




|







2213
2214
2215
2216
2217
2218
2219
2220
2221

2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249

static int
select_next_proto_cb(SSL *ssl,
                     unsigned char **out, unsigned char *outlen,
                     const unsigned char *in, unsigned int inlen,
                     void *arg)
{
  struct Curl_easy *data = (struct Curl_easy *)arg;
  struct connectdata *conn = data->conn;

  (void)ssl;

#ifdef USE_NGHTTP2
  if(data->set.httpversion >= CURL_HTTP_VERSION_2 &&
     !select_next_protocol(out, outlen, in, inlen, NGHTTP2_PROTO_VERSION_ID,
                           NGHTTP2_PROTO_VERSION_ID_LEN)) {
    infof(data, "NPN, negotiated HTTP2 (%s)\n",
          NGHTTP2_PROTO_VERSION_ID);
    conn->negnpn = CURL_HTTP_VERSION_2;
    return SSL_TLSEXT_ERR_OK;
  }
#endif

  if(!select_next_protocol(out, outlen, in, inlen, ALPN_HTTP_1_1,
                           ALPN_HTTP_1_1_LENGTH)) {
    infof(data, "NPN, negotiated HTTP1.1\n");
    conn->negnpn = CURL_HTTP_VERSION_1_1;
    return SSL_TLSEXT_ERR_OK;
  }

  infof(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 */
2355
2356
2357
2358
2359
2360
2361

2362
2363
2364
2365
2366
2367
2368
2369
2370


2371
2372
2373
2374
2375
2376
2377
#else
typedef long ctx_option_t;
#endif

#if (OPENSSL_VERSION_NUMBER < 0x10100000L) /* 1.1.0 */
static CURLcode
set_ssl_version_min_max_legacy(ctx_option_t *ctx_options,

                              struct connectdata *conn, int sockindex)
{
#if (OPENSSL_VERSION_NUMBER < 0x1000100FL) || !defined(TLS1_3_VERSION)
  /* convoluted #if condition just to avoid compiler warnings on unused
     variable */
  struct Curl_easy *data = conn->data;
#endif
  long ssl_version = SSL_CONN_CONFIG(version);
  long ssl_version_max = SSL_CONN_CONFIG(version_max);



  switch(ssl_version) {
    case CURL_SSLVERSION_TLSv1_3:
#ifdef TLS1_3_VERSION
    {
      struct ssl_connect_data *connssl = &conn->ssl[sockindex];
      SSL_CTX_set_max_proto_version(backend->ctx, TLS1_3_VERSION);







>
|

<
<
<
<
<


>
>







2366
2367
2368
2369
2370
2371
2372
2373
2374
2375





2376
2377
2378
2379
2380
2381
2382
2383
2384
2385
2386
#else
typedef long ctx_option_t;
#endif

#if (OPENSSL_VERSION_NUMBER < 0x10100000L) /* 1.1.0 */
static CURLcode
set_ssl_version_min_max_legacy(ctx_option_t *ctx_options,
                               struct Curl_easy *data,
                               struct connectdata *conn, int sockindex)
{





  long ssl_version = SSL_CONN_CONFIG(version);
  long ssl_version_max = SSL_CONN_CONFIG(version_max);

  (void) data; /* In case it's unused. */

  switch(ssl_version) {
    case CURL_SSLVERSION_TLSv1_3:
#ifdef TLS1_3_VERSION
    {
      struct ssl_connect_data *connssl = &conn->ssl[sockindex];
      SSL_CTX_set_max_proto_version(backend->ctx, TLS1_3_VERSION);
2439
2440
2441
2442
2443
2444
2445

2446
2447
2448
2449
2450
2451
2452
2453
2454
2455
2456
2457
2458
2459
2460
2461
2462
2463
2464
2465
2466
2467
2468
2469
2470
2471
2472
2473
2474
2475
2476
2477
2478
2479
2480
2481
2482
2483
2484
2485
2486
2487
2488
2489
2490
2491
2492

2493
2494
2495
2496
2497
2498
2499
2500
2501
2502
2503
static int ossl_new_session_cb(SSL *ssl, SSL_SESSION *ssl_sessionid)
{
  int res = 0;
  struct connectdata *conn;
  struct Curl_easy *data;
  int sockindex;
  curl_socket_t *sockindex_ptr;

  int connectdata_idx = ossl_get_ssl_conn_index();
  int sockindex_idx = ossl_get_ssl_sockindex_index();

  if(connectdata_idx < 0 || sockindex_idx < 0)
    return 0;

  conn = (struct connectdata*) SSL_get_ex_data(ssl, connectdata_idx);
  if(!conn)
    return 0;

  data = conn->data;

  /* The sockindex has been stored as a pointer to an array element */
  sockindex_ptr = (curl_socket_t*) SSL_get_ex_data(ssl, sockindex_idx);
  sockindex = (int)(sockindex_ptr - conn->sock);

  if(SSL_SET_OPTION(primary.sessionid)) {
    bool incache;
    void *old_ssl_sessionid = NULL;

    Curl_ssl_sessionid_lock(conn);
    incache = !(Curl_ssl_getsessionid(conn, &old_ssl_sessionid, NULL,
                                      sockindex));
    if(incache) {
      if(old_ssl_sessionid != ssl_sessionid) {
        infof(data, "old SSL session ID is stale, removing\n");
        Curl_ssl_delsessionid(conn, old_ssl_sessionid);
        incache = FALSE;
      }
    }

    if(!incache) {
      if(!Curl_ssl_addsessionid(conn, ssl_sessionid,
                                      0 /* unknown size */, sockindex)) {
        /* the session has been put into the session cache */
        res = 1;
      }
      else
        failf(data, "failed to store ssl session");
    }
    Curl_ssl_sessionid_unlock(conn);
  }

  return res;
}

static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex)

{
  CURLcode result = CURLE_OK;
  char *ciphers;
  struct Curl_easy *data = conn->data;
  SSL_METHOD_QUAL SSL_METHOD *req_method = NULL;
  X509_LOOKUP *lookup = NULL;
  curl_socket_t sockfd = conn->sock[sockindex];
  struct ssl_connect_data *connssl = &conn->ssl[sockindex];
  ctx_option_t ctx_options = 0;

#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME







>



|






|









|
|




|





|







|





|
>



<







2448
2449
2450
2451
2452
2453
2454
2455
2456
2457
2458
2459
2460
2461
2462
2463
2464
2465
2466
2467
2468
2469
2470
2471
2472
2473
2474
2475
2476
2477
2478
2479
2480
2481
2482
2483
2484
2485
2486
2487
2488
2489
2490
2491
2492
2493
2494
2495
2496
2497
2498
2499
2500
2501
2502
2503
2504
2505
2506

2507
2508
2509
2510
2511
2512
2513
static int ossl_new_session_cb(SSL *ssl, SSL_SESSION *ssl_sessionid)
{
  int res = 0;
  struct connectdata *conn;
  struct Curl_easy *data;
  int sockindex;
  curl_socket_t *sockindex_ptr;
  int data_idx = ossl_get_ssl_data_index();
  int connectdata_idx = ossl_get_ssl_conn_index();
  int sockindex_idx = ossl_get_ssl_sockindex_index();

  if(data_idx < 0 || connectdata_idx < 0 || sockindex_idx < 0)
    return 0;

  conn = (struct connectdata*) SSL_get_ex_data(ssl, connectdata_idx);
  if(!conn)
    return 0;

  data = (struct Curl_easy *) SSL_get_ex_data(ssl, data_idx);

  /* The sockindex has been stored as a pointer to an array element */
  sockindex_ptr = (curl_socket_t*) SSL_get_ex_data(ssl, sockindex_idx);
  sockindex = (int)(sockindex_ptr - conn->sock);

  if(SSL_SET_OPTION(primary.sessionid)) {
    bool incache;
    void *old_ssl_sessionid = NULL;

    Curl_ssl_sessionid_lock(data);
    incache = !(Curl_ssl_getsessionid(data, conn, &old_ssl_sessionid, NULL,
                                      sockindex));
    if(incache) {
      if(old_ssl_sessionid != ssl_sessionid) {
        infof(data, "old SSL session ID is stale, removing\n");
        Curl_ssl_delsessionid(data, old_ssl_sessionid);
        incache = FALSE;
      }
    }

    if(!incache) {
      if(!Curl_ssl_addsessionid(data, conn, ssl_sessionid,
                                      0 /* unknown size */, sockindex)) {
        /* the session has been put into the session cache */
        res = 1;
      }
      else
        failf(data, "failed to store ssl session");
    }
    Curl_ssl_sessionid_unlock(data);
  }

  return res;
}

static CURLcode ossl_connect_step1(struct Curl_easy *data,
                                   struct connectdata *conn, int sockindex)
{
  CURLcode result = CURLE_OK;
  char *ciphers;

  SSL_METHOD_QUAL SSL_METHOD *req_method = NULL;
  X509_LOOKUP *lookup = NULL;
  curl_socket_t sockfd = conn->sock[sockindex];
  struct ssl_connect_data *connssl = &conn->ssl[sockindex];
  ctx_option_t ctx_options = 0;

#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
  char error_buffer[256];
  struct ssl_backend_data *backend = connssl->backend;
  bool imported_native_ca = false;

  DEBUGASSERT(ssl_connect_1 == connssl->connecting_state);

  /* Make funny stuff to get random input */
  result = Curl_ossl_seed(data);
  if(result)
    return result;

  SSL_SET_OPTION_LVALUE(certverifyresult) = !X509_V_OK;

  /* check to see if we've been told to use an explicit SSL/TLS version */








|







2534
2535
2536
2537
2538
2539
2540
2541
2542
2543
2544
2545
2546
2547
2548
  char error_buffer[256];
  struct ssl_backend_data *backend = connssl->backend;
  bool imported_native_ca = false;

  DEBUGASSERT(ssl_connect_1 == connssl->connecting_state);

  /* Make funny stuff to get random input */
  result = ossl_seed(data);
  if(result)
    return result;

  SSL_SET_OPTION_LVALUE(certverifyresult) = !X509_V_OK;

  /* check to see if we've been told to use an explicit SSL/TLS version */

2710
2711
2712
2713
2714
2715
2716
2717

2718
2719
2720
2721
2722
2723
2724
2725
2726
2727
2728
2729
2730
2731
2732
2733
2734
2735
2736
2737
2738
2739
        allowed */
      ctx_options |= SSL_OP_NO_SSLv2;
      ctx_options |= SSL_OP_NO_SSLv3;

#if (OPENSSL_VERSION_NUMBER >= 0x10100000L) /* 1.1.0 */
      result = set_ssl_version_min_max(backend->ctx, conn);
#else
      result = set_ssl_version_min_max_legacy(&ctx_options, conn, sockindex);

#endif
      if(result != CURLE_OK)
        return result;
      break;

    default:
      failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION");
      return CURLE_SSL_CONNECT_ERROR;
  }

  SSL_CTX_set_options(backend->ctx, ctx_options);

#ifdef HAS_NPN
  if(conn->bits.tls_enable_npn)
    SSL_CTX_set_next_proto_select_cb(backend->ctx, select_next_proto_cb, conn);
#endif

#ifdef HAS_ALPN
  if(conn->bits.tls_enable_alpn) {
    int cur = 0;
    unsigned char protocols[128];








|
>














|







2720
2721
2722
2723
2724
2725
2726
2727
2728
2729
2730
2731
2732
2733
2734
2735
2736
2737
2738
2739
2740
2741
2742
2743
2744
2745
2746
2747
2748
2749
2750
        allowed */
      ctx_options |= SSL_OP_NO_SSLv2;
      ctx_options |= SSL_OP_NO_SSLv3;

#if (OPENSSL_VERSION_NUMBER >= 0x10100000L) /* 1.1.0 */
      result = set_ssl_version_min_max(backend->ctx, conn);
#else
      result = set_ssl_version_min_max_legacy(&ctx_options, data, conn,
                                              sockindex);
#endif
      if(result != CURLE_OK)
        return result;
      break;

    default:
      failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION");
      return CURLE_SSL_CONNECT_ERROR;
  }

  SSL_CTX_set_options(backend->ctx, ctx_options);

#ifdef HAS_NPN
  if(conn->bits.tls_enable_npn)
    SSL_CTX_set_next_proto_select_cb(backend->ctx, select_next_proto_cb, data);
#endif

#ifdef HAS_ALPN
  if(conn->bits.tls_enable_alpn) {
    int cur = 0;
    unsigned char protocols[128];

2778
2779
2780
2781
2782
2783
2784
2785
2786
2787
2788
2789
2790
2791
2792
    if(!result && SSL_SET_OPTION(key_blob)) {
      ssl_key_bio = BIO_new_mem_buf(SSL_SET_OPTION(key_blob)->data,
                                    (int)SSL_SET_OPTION(key_blob)->len);
      if(!ssl_key_bio)
        result = CURLE_OUT_OF_MEMORY;
    }
    if(!result &&
       !cert_stuff(conn, backend->ctx,
                   ssl_cert, ssl_cert_bio, ssl_cert_type,
                   SSL_SET_OPTION(key), ssl_key_bio,
                   SSL_SET_OPTION(key_type), SSL_SET_OPTION(key_passwd)))
      result = CURLE_SSL_CERTPROBLEM;
    if(ssl_cert_bio)
      BIO_free(ssl_cert_bio);
    if(ssl_key_bio)







|







2789
2790
2791
2792
2793
2794
2795
2796
2797
2798
2799
2800
2801
2802
2803
    if(!result && SSL_SET_OPTION(key_blob)) {
      ssl_key_bio = BIO_new_mem_buf(SSL_SET_OPTION(key_blob)->data,
                                    (int)SSL_SET_OPTION(key_blob)->len);
      if(!ssl_key_bio)
        result = CURLE_OUT_OF_MEMORY;
    }
    if(!result &&
       !cert_stuff(data, backend->ctx,
                   ssl_cert, ssl_cert_bio, ssl_cert_type,
                   SSL_SET_OPTION(key), ssl_key_bio,
                   SSL_SET_OPTION(key_type), SSL_SET_OPTION(key_passwd)))
      result = CURLE_SSL_CERTPROBLEM;
    if(ssl_cert_bio)
      BIO_free(ssl_cert_bio);
    if(ssl_key_bio)
3174
3175
3176
3177
3178
3179
3180
3181










3182
3183
3184

3185
3186
3187
3188
3189

3190
3191
3192
3193
3194
3195

3196
3197
3198
3199
3200
3201
3202
3203
3204
3205
3206
3207
3208
3209
3210
3211
3212
3213
3214
3215
3216
3217
3218
3219
3220

  backend->server_cert = 0x0;
#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
  if((0 == Curl_inet_pton(AF_INET, hostname, &addr)) &&
#ifdef ENABLE_IPV6
     (0 == Curl_inet_pton(AF_INET6, hostname, &addr)) &&
#endif
     sni &&










     !SSL_set_tlsext_host_name(backend->handle, hostname))
    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(SSL_SET_OPTION(primary.sessionid)) {
    void *ssl_sessionid = NULL;

    int connectdata_idx = ossl_get_ssl_conn_index();
    int sockindex_idx = ossl_get_ssl_sockindex_index();

    if(connectdata_idx >= 0 && sockindex_idx >= 0) {
      /* Store the data needed for the "new session" callback.
       * The sockindex is stored as a pointer to an array element. */

      SSL_set_ex_data(backend->handle, connectdata_idx, conn);
      SSL_set_ex_data(backend->handle, sockindex_idx, conn->sock + sockindex);
    }

    Curl_ssl_sessionid_lock(conn);
    if(!Curl_ssl_getsessionid(conn, &ssl_sessionid, NULL, sockindex)) {
      /* we got a session id, use it! */
      if(!SSL_set_session(backend->handle, ssl_sessionid)) {
        Curl_ssl_sessionid_unlock(conn);
        failf(data, "SSL: SSL_set_session failed: %s",
              ossl_strerror(ERR_get_error(), error_buffer,
                            sizeof(error_buffer)));
        return CURLE_SSL_CONNECT_ERROR;
      }
      /* Informational message */
      infof(data, "SSL re-using session ID\n");
    }
    Curl_ssl_sessionid_unlock(conn);
  }

#ifndef CURL_DISABLE_PROXY
  if(conn->proxy_ssl[sockindex].use) {
    BIO *const bio = BIO_new(BIO_f_ssl());
    SSL *handle = conn->proxy_ssl[sockindex].backend->handle;
    DEBUGASSERT(ssl_connection_complete == conn->proxy_ssl[sockindex].state);







|
>
>
>
>
>
>
>
>
>
>
|
|
|
>





>



|


>




|
|


|








|







3185
3186
3187
3188
3189
3190
3191
3192
3193
3194
3195
3196
3197
3198
3199
3200
3201
3202
3203
3204
3205
3206
3207
3208
3209
3210
3211
3212
3213
3214
3215
3216
3217
3218
3219
3220
3221
3222
3223
3224
3225
3226
3227
3228
3229
3230
3231
3232
3233
3234
3235
3236
3237
3238
3239
3240
3241
3242
3243
3244

  backend->server_cert = 0x0;
#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
  if((0 == Curl_inet_pton(AF_INET, hostname, &addr)) &&
#ifdef ENABLE_IPV6
     (0 == Curl_inet_pton(AF_INET6, hostname, &addr)) &&
#endif
     sni) {
    size_t nlen = strlen(hostname);
    if((long)nlen >= data->set.buffer_size)
      /* this is seriously messed up */
      return CURLE_SSL_CONNECT_ERROR;

    /* RFC 6066 section 3 says the SNI field is case insensitive, but browsers
       send the data lowercase and subsequently there are now numerous servers
       out there that don't work unless the name is lowercased */
    Curl_strntolower(data->state.buffer, hostname, nlen);
    data->state.buffer[nlen] = 0;
    if(!SSL_set_tlsext_host_name(backend->handle, data->state.buffer))
      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(SSL_SET_OPTION(primary.sessionid)) {
    void *ssl_sessionid = NULL;
    int data_idx = ossl_get_ssl_data_index();
    int connectdata_idx = ossl_get_ssl_conn_index();
    int sockindex_idx = ossl_get_ssl_sockindex_index();

    if(data_idx >= 0 && connectdata_idx >= 0 && sockindex_idx >= 0) {
      /* Store the data needed for the "new session" callback.
       * The sockindex is stored as a pointer to an array element. */
      SSL_set_ex_data(backend->handle, data_idx, data);
      SSL_set_ex_data(backend->handle, connectdata_idx, conn);
      SSL_set_ex_data(backend->handle, sockindex_idx, conn->sock + sockindex);
    }

    Curl_ssl_sessionid_lock(data);
    if(!Curl_ssl_getsessionid(data, conn, &ssl_sessionid, NULL, sockindex)) {
      /* we got a session id, use it! */
      if(!SSL_set_session(backend->handle, ssl_sessionid)) {
        Curl_ssl_sessionid_unlock(data);
        failf(data, "SSL: SSL_set_session failed: %s",
              ossl_strerror(ERR_get_error(), error_buffer,
                            sizeof(error_buffer)));
        return CURLE_SSL_CONNECT_ERROR;
      }
      /* Informational message */
      infof(data, "SSL re-using session ID\n");
    }
    Curl_ssl_sessionid_unlock(data);
  }

#ifndef CURL_DISABLE_PROXY
  if(conn->proxy_ssl[sockindex].use) {
    BIO *const bio = BIO_new(BIO_f_ssl());
    SSL *handle = conn->proxy_ssl[sockindex].backend->handle;
    DEBUGASSERT(ssl_connection_complete == conn->proxy_ssl[sockindex].state);
3233
3234
3235
3236
3237
3238
3239
3240

3241
3242
3243
3244
3245
3246
3247
3248
3249
  }

  connssl->connecting_state = ssl_connect_2;

  return CURLE_OK;
}

static CURLcode ossl_connect_step2(struct connectdata *conn, int sockindex)

{
  struct Curl_easy *data = conn->data;
  int err;
  struct ssl_connect_data *connssl = &conn->ssl[sockindex];
  struct ssl_backend_data *backend = connssl->backend;
  DEBUGASSERT(ssl_connect_2 == connssl->connecting_state
              || ssl_connect_2_reading == connssl->connecting_state
              || ssl_connect_2_writing == connssl->connecting_state);








|
>

<







3257
3258
3259
3260
3261
3262
3263
3264
3265
3266

3267
3268
3269
3270
3271
3272
3273
  }

  connssl->connecting_state = ssl_connect_2;

  return CURLE_OK;
}

static CURLcode ossl_connect_step2(struct Curl_easy *data,
                                   struct connectdata *conn, int sockindex)
{

  int err;
  struct ssl_connect_data *connssl = &conn->ssl[sockindex];
  struct ssl_backend_data *backend = connssl->backend;
  DEBUGASSERT(ssl_connect_2 == connssl->connecting_state
              || ssl_connect_2_reading == connssl->connecting_state
              || ssl_connect_2_writing == connssl->connecting_state);

3381
3382
3383
3384
3385
3386
3387
3388
3389
3390
3391
3392
3393
3394
3395
           !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");

      Curl_multiuse_state(conn, conn->negnpn == CURL_HTTP_VERSION_2 ?
                          BUNDLE_MULTIPLEX : BUNDLE_NO_MULTIUSE);
    }
#endif

    return CURLE_OK;
  }
}







|







3405
3406
3407
3408
3409
3410
3411
3412
3413
3414
3415
3416
3417
3418
3419
           !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");

      Curl_multiuse_state(data, conn->negnpn == CURL_HTTP_VERSION_2 ?
                          BUNDLE_MULTIPLEX : BUNDLE_NO_MULTIUSE);
    }
#endif

    return CURLE_OK;
  }
}
3487
3488
3489
3490
3491
3492
3493
3494
3495
3496
3497
3498
3499
3500
3501
3502
3503
3504
3505
3506
3507

#ifdef OPENSSL_IS_BORINGSSL
typedef size_t numcert_t;
#else
typedef int numcert_t;
#endif

static CURLcode get_cert_chain(struct connectdata *conn,
                               struct ssl_connect_data *connssl)
{
  CURLcode result;
  STACK_OF(X509) *sk;
  int i;
  struct Curl_easy *data = conn->data;
  numcert_t numcerts;
  BIO *mem;
  struct ssl_backend_data *backend = connssl->backend;

  sk = SSL_get_peer_cert_chain(backend->handle);
  if(!sk) {
    return CURLE_OUT_OF_MEMORY;







|





<







3511
3512
3513
3514
3515
3516
3517
3518
3519
3520
3521
3522
3523

3524
3525
3526
3527
3528
3529
3530

#ifdef OPENSSL_IS_BORINGSSL
typedef size_t numcert_t;
#else
typedef int numcert_t;
#endif

static CURLcode get_cert_chain(struct Curl_easy *data,
                               struct ssl_connect_data *connssl)
{
  CURLcode result;
  STACK_OF(X509) *sk;
  int i;

  numcert_t numcerts;
  BIO *mem;
  struct ssl_backend_data *backend = connssl->backend;

  sk = SSL_get_peer_cert_chain(backend->handle);
  if(!sk) {
    return CURLE_OUT_OF_MEMORY;
3768
3769
3770
3771
3772
3773
3774
3775

3776
3777
3778
3779
3780
3781
3782
3783
3784
3785
3786
3787
3788
3789
3790
3791
3792
3793
3794
3795
3796
3797
3798
3799
3800
 * 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;
  struct Curl_easy *data = conn->data;
  X509 *issuer;
  BIO *fp = NULL;
  char error_buffer[256]="";
  char buffer[2048];
  const char *ptr;
  BIO *mem = BIO_new(BIO_s_mem());
  struct ssl_backend_data *backend = connssl->backend;

  if(data->set.ssl.certinfo)
    /* we've been asked to gather certificate info! */
    (void)get_cert_chain(conn, connssl);

  backend->server_cert = SSL_get_peer_certificate(backend->handle);
  if(!backend->server_cert) {
    BIO_free(mem);
    if(!strict)
      return CURLE_OK;








|
>






<










|







3791
3792
3793
3794
3795
3796
3797
3798
3799
3800
3801
3802
3803
3804
3805

3806
3807
3808
3809
3810
3811
3812
3813
3814
3815
3816
3817
3818
3819
3820
3821
3822
3823
 * 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 Curl_easy *data,
                           struct connectdata *conn,
                           struct ssl_connect_data *connssl,
                           bool strict)
{
  CURLcode result = CURLE_OK;
  int rc;
  long lerr;

  X509 *issuer;
  BIO *fp = NULL;
  char error_buffer[256]="";
  char buffer[2048];
  const char *ptr;
  BIO *mem = BIO_new(BIO_s_mem());
  struct ssl_backend_data *backend = connssl->backend;

  if(data->set.ssl.certinfo)
    /* we've been asked to gather certificate info! */
    (void)get_cert_chain(data, connssl);

  backend->server_cert = SSL_get_peer_certificate(backend->handle);
  if(!backend->server_cert) {
    BIO_free(mem);
    if(!strict)
      return CURLE_OK;

3822
3823
3824
3825
3826
3827
3828
3829
3830
3831
3832
3833
3834
3835
3836
    (void)BIO_reset(mem);
  }
#endif

  BIO_free(mem);

  if(SSL_CONN_CONFIG(verifyhost)) {
    result = verifyhost(conn, backend->server_cert);
    if(result) {
      X509_free(backend->server_cert);
      backend->server_cert = NULL;
      return result;
    }
  }








|







3845
3846
3847
3848
3849
3850
3851
3852
3853
3854
3855
3856
3857
3858
3859
    (void)BIO_reset(mem);
  }
#endif

  BIO_free(mem);

  if(SSL_CONN_CONFIG(verifyhost)) {
    result = verifyhost(data, conn, backend->server_cert);
    if(result) {
      X509_free(backend->server_cert);
      backend->server_cert = NULL;
      return result;
    }
  }

3924
3925
3926
3927
3928
3929
3930
3931
3932
3933
3934
3935
3936
3937
3938
    else
      infof(data, " SSL certificate verify ok.\n");
  }

#if (OPENSSL_VERSION_NUMBER >= 0x0090808fL) && !defined(OPENSSL_NO_TLSEXT) && \
    !defined(OPENSSL_NO_OCSP)
  if(SSL_CONN_CONFIG(verifystatus)) {
    result = verifystatus(conn, connssl);
    if(result) {
      X509_free(backend->server_cert);
      backend->server_cert = NULL;
      return result;
    }
  }
#endif







|







3947
3948
3949
3950
3951
3952
3953
3954
3955
3956
3957
3958
3959
3960
3961
    else
      infof(data, " SSL certificate verify ok.\n");
  }

#if (OPENSSL_VERSION_NUMBER >= 0x0090808fL) && !defined(OPENSSL_NO_TLSEXT) && \
    !defined(OPENSSL_NO_OCSP)
  if(SSL_CONN_CONFIG(verifystatus)) {
    result = verifystatus(data, connssl);
    if(result) {
      X509_free(backend->server_cert);
      backend->server_cert = NULL;
      return result;
    }
  }
#endif
3952
3953
3954
3955
3956
3957
3958
3959

3960
3961
3962
3963
3964
3965
3966
3967
3968
3969
3970
3971
3972
3973
3974
3975
3976
3977
3978
3979
3980
3981
3982
3983
3984
3985

3986
3987
3988
3989
3990
3991
3992
3993
3994
3995
3996
3997
3998
3999
4000
4001
4002
4003
4004
4005
4006
4007
4008
4009
4010
4011
4012
4013
4014
4015
4016
4017
4018
4019
  X509_free(backend->server_cert);
  backend->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;
  struct ssl_connect_data *connssl = &conn->ssl[sockindex];

  DEBUGASSERT(ssl_connect_3 == connssl->connecting_state);

  /*
   * 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, (SSL_CONN_CONFIG(verifypeer) ||
                                      SSL_CONN_CONFIG(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 Curl_easy *data = conn->data;
  struct ssl_connect_data *connssl = &conn->ssl[sockindex];
  curl_socket_t sockfd = conn->sock[sockindex];
  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 */
    const timediff_t 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) {







|
>













|
|










|
>





<




















|







3975
3976
3977
3978
3979
3980
3981
3982
3983
3984
3985
3986
3987
3988
3989
3990
3991
3992
3993
3994
3995
3996
3997
3998
3999
4000
4001
4002
4003
4004
4005
4006
4007
4008
4009
4010
4011
4012
4013
4014
4015

4016
4017
4018
4019
4020
4021
4022
4023
4024
4025
4026
4027
4028
4029
4030
4031
4032
4033
4034
4035
4036
4037
4038
4039
4040
4041
4042
4043
  X509_free(backend->server_cert);
  backend->server_cert = NULL;
  connssl->connecting_state = ssl_connect_done;

  return result;
}

static CURLcode ossl_connect_step3(struct Curl_easy *data,
                                   struct connectdata *conn, int sockindex)
{
  CURLcode result = CURLE_OK;
  struct ssl_connect_data *connssl = &conn->ssl[sockindex];

  DEBUGASSERT(ssl_connect_3 == connssl->connecting_state);

  /*
   * 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(data, conn, connssl, (SSL_CONN_CONFIG(verifypeer) ||
                                            SSL_CONN_CONFIG(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 Curl_easy *data,
                                    struct connectdata *conn,
                                    int sockindex,
                                    bool nonblocking,
                                    bool *done)
{
  CURLcode result;

  struct ssl_connect_data *connssl = &conn->ssl[sockindex];
  curl_socket_t sockfd = conn->sock[sockindex];
  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 */
    const timediff_t 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(data, 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) {
4057
4058
4059
4060
4061
4062
4063
4064
4065
4066
4067
4068
4069
4070
4071
4072
4073
4074
4075
4076
4077
4078
4079
4080
4081
4082
4083
4084
4085
4086
4087
4088
4089
4090
4091
4092
4093

4094
4095
4096
4097
4098
4099
4100

4101
4102
4103
4104
4105
4106
4107
4108
4109
4110
4111
4112
4113
4114
4115
4116
4117
4118
4119
4120
4121
4122
4123
4124
4125
4126
4127
4128
4129
4130
4131
4132
4133
4134
4135
4136
4137
4138
4139
4140
4141
4142
4143
4144
4145

4146
4147
4148
4149
4150
4151
4152

    /* 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;
}


static CURLcode Curl_ossl_connect_nonblocking(struct connectdata *conn,
                                              int sockindex,
                                              bool *done)
{
  return ossl_connect_common(conn, sockindex, TRUE, done);
}


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;
}

static bool Curl_ossl_data_pending(const struct connectdata *conn,
                                   int connindex)
{
  const struct ssl_connect_data *connssl = &conn->ssl[connindex];
  if(connssl->backend->handle && SSL_pending(connssl->backend->handle))
    return TRUE;
#ifndef CURL_DISABLE_PROXY
  {
    const struct ssl_connect_data *proxyssl = &conn->proxy_ssl[connindex];
    if(proxyssl->backend->handle && SSL_pending(proxyssl->backend->handle))
      return TRUE;
  }
#endif
  return FALSE;
}

static size_t Curl_ossl_version(char *buffer, size_t size);

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[256];
  unsigned long sslerror;
  int memlen;
  int rc;

  struct ssl_connect_data *connssl = &conn->ssl[sockindex];
  struct ssl_backend_data *backend = connssl->backend;

  ERR_clear_error();

  memlen = (len > (size_t)INT_MAX) ? INT_MAX : (int)len;
  rc = SSL_write(backend->handle, mem, memlen);







|









|



















>
|
|
|

|


>
|




|








|
|














|

|












>







4081
4082
4083
4084
4085
4086
4087
4088
4089
4090
4091
4092
4093
4094
4095
4096
4097
4098
4099
4100
4101
4102
4103
4104
4105
4106
4107
4108
4109
4110
4111
4112
4113
4114
4115
4116
4117
4118
4119
4120
4121
4122
4123
4124
4125
4126
4127
4128
4129
4130
4131
4132
4133
4134
4135
4136
4137
4138
4139
4140
4141
4142
4143
4144
4145
4146
4147
4148
4149
4150
4151
4152
4153
4154
4155
4156
4157
4158
4159
4160
4161
4162
4163
4164
4165
4166
4167
4168
4169
4170
4171
4172
4173
4174
4175
4176
4177
4178
4179

    /* 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(data, 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(data, 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;
}

static CURLcode ossl_connect_nonblocking(struct Curl_easy *data,
                                         struct connectdata *conn,
                                         int sockindex,
                                         bool *done)
{
  return ossl_connect_common(data, conn, sockindex, TRUE, done);
}

static CURLcode ossl_connect(struct Curl_easy *data, struct connectdata *conn,
                             int sockindex)
{
  CURLcode result;
  bool done = FALSE;

  result = ossl_connect_common(data, conn, sockindex, FALSE, &done);
  if(result)
    return result;

  DEBUGASSERT(done);

  return CURLE_OK;
}

static bool ossl_data_pending(const struct connectdata *conn,
                              int connindex)
{
  const struct ssl_connect_data *connssl = &conn->ssl[connindex];
  if(connssl->backend->handle && SSL_pending(connssl->backend->handle))
    return TRUE;
#ifndef CURL_DISABLE_PROXY
  {
    const struct ssl_connect_data *proxyssl = &conn->proxy_ssl[connindex];
    if(proxyssl->backend->handle && SSL_pending(proxyssl->backend->handle))
      return TRUE;
  }
#endif
  return FALSE;
}

static size_t ossl_version(char *buffer, size_t size);

static ssize_t ossl_send(struct Curl_easy *data,
                         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[256];
  unsigned long sslerror;
  int memlen;
  int rc;
  struct connectdata *conn = data->conn;
  struct ssl_connect_data *connssl = &conn->ssl[sockindex];
  struct ssl_backend_data *backend = connssl->backend;

  ERR_clear_error();

  memlen = (len > (size_t)INT_MAX) ? INT_MAX : (int)len;
  rc = SSL_write(backend->handle, mem, memlen);
4170
4171
4172
4173
4174
4175
4176
4177
4178
4179
4180
4181
4182
4183
4184
4185
4186
4187
4188
4189
4190
4191
4192
4193
4194
4195
4196
4197
4198
4199
4200
4201
4202
4203
4204
4205
4206
4207
4208
4209
4210
4211
4212
4213
4214
4215
4216
4217
4218
4219
4220
4221
4222
4223

4224
4225
4226
4227
4228
4229
4230
          ossl_strerror(sslerror, error_buffer, sizeof(error_buffer));
        else if(sockerr)
          Curl_strerror(sockerr, error_buffer, sizeof(error_buffer));
        else {
          strncpy(error_buffer, SSL_ERROR_to_str(err), sizeof(error_buffer));
          error_buffer[sizeof(error_buffer) - 1] = '\0';
        }
        failf(conn->data, OSSL_PACKAGE " SSL_write: %s, errno %d",
              error_buffer, sockerr);
        *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();
      if(ERR_GET_LIB(sslerror) == ERR_LIB_SSL &&
         ERR_GET_REASON(sslerror) == SSL_R_BIO_NOT_SET &&
         conn->ssl[sockindex].state == ssl_connection_complete
#ifndef CURL_DISABLE_PROXY
         && conn->proxy_ssl[sockindex].state == ssl_connection_complete
#endif
        ) {
        char ver[120];
        Curl_ossl_version(ver, 120);
        failf(conn->data, "Error: %s does not support double SSL tunneling.",
              ver);
      }
      else
        failf(conn->data, "SSL_write() error: %s",
              ossl_strerror(sslerror, error_buffer, sizeof(error_buffer)));
      *curlcode = CURLE_SEND_ERROR;
      return -1;
    }
    /* a true error */
    failf(conn->data, OSSL_PACKAGE " SSL_write: %s, errno %d",
          SSL_ERROR_to_str(err), SOCKERRNO);
    *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[256];
  unsigned long sslerror;
  ssize_t nread;
  int buffsize;

  struct ssl_connect_data *connssl = &conn->ssl[num];
  struct ssl_backend_data *backend = connssl->backend;

  ERR_clear_error();

  buffsize = (buffersize > (size_t)INT_MAX) ? INT_MAX : (int)buffersize;
  nread = (ssize_t)SSL_read(backend->handle, buf, buffsize);







|
















|
|
<


|





|








|









>







4197
4198
4199
4200
4201
4202
4203
4204
4205
4206
4207
4208
4209
4210
4211
4212
4213
4214
4215
4216
4217
4218
4219
4220
4221
4222

4223
4224
4225
4226
4227
4228
4229
4230
4231
4232
4233
4234
4235
4236
4237
4238
4239
4240
4241
4242
4243
4244
4245
4246
4247
4248
4249
4250
4251
4252
4253
4254
4255
4256
4257
          ossl_strerror(sslerror, error_buffer, sizeof(error_buffer));
        else if(sockerr)
          Curl_strerror(sockerr, error_buffer, sizeof(error_buffer));
        else {
          strncpy(error_buffer, SSL_ERROR_to_str(err), sizeof(error_buffer));
          error_buffer[sizeof(error_buffer) - 1] = '\0';
        }
        failf(data, OSSL_PACKAGE " SSL_write: %s, errno %d",
              error_buffer, sockerr);
        *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();
      if(ERR_GET_LIB(sslerror) == ERR_LIB_SSL &&
         ERR_GET_REASON(sslerror) == SSL_R_BIO_NOT_SET &&
         conn->ssl[sockindex].state == ssl_connection_complete
#ifndef CURL_DISABLE_PROXY
         && conn->proxy_ssl[sockindex].state == ssl_connection_complete
#endif
        ) {
        char ver[120];
        ossl_version(ver, 120);
        failf(data, "Error: %s does not support double SSL tunneling.", ver);

      }
      else
        failf(data, "SSL_write() error: %s",
              ossl_strerror(sslerror, error_buffer, sizeof(error_buffer)));
      *curlcode = CURLE_SEND_ERROR;
      return -1;
    }
    /* a true error */
    failf(data, OSSL_PACKAGE " SSL_write: %s, errno %d",
          SSL_ERROR_to_str(err), SOCKERRNO);
    *curlcode = CURLE_SEND_ERROR;
    return -1;
  }
  *curlcode = CURLE_OK;
  return (ssize_t)rc; /* number of bytes */
}

static ssize_t ossl_recv(struct Curl_easy *data,   /* transfer */
                         int num,                  /* socketindex */
                         char *buf,                /* store read data here */
                         size_t buffersize,        /* max amount to read */
                         CURLcode *curlcode)
{
  char error_buffer[256];
  unsigned long sslerror;
  ssize_t nread;
  int buffsize;
  struct connectdata *conn = data->conn;
  struct ssl_connect_data *connssl = &conn->ssl[num];
  struct ssl_backend_data *backend = connssl->backend;

  ERR_clear_error();

  buffsize = (buffersize > (size_t)INT_MAX) ? INT_MAX : (int)buffersize;
  nread = (ssize_t)SSL_read(backend->handle, buf, buffsize);
4260
4261
4262
4263
4264
4265
4266
4267
4268
4269
4270
4271
4272
4273
4274
          ossl_strerror(sslerror, error_buffer, sizeof(error_buffer));
        else if(sockerr && err == SSL_ERROR_SYSCALL)
          Curl_strerror(sockerr, error_buffer, sizeof(error_buffer));
        else {
          strncpy(error_buffer, SSL_ERROR_to_str(err), sizeof(error_buffer));
          error_buffer[sizeof(error_buffer) - 1] = '\0';
        }
        failf(conn->data, OSSL_PACKAGE " SSL_read: %s, errno %d",
              error_buffer, sockerr);
        *curlcode = CURLE_RECV_ERROR;
        return -1;
      }
      /* For debug builds be a little stricter and error on any
         SSL_ERROR_SYSCALL. For example a server may have closed the connection
         abruptly without a close_notify alert. For compatibility with older







|







4287
4288
4289
4290
4291
4292
4293
4294
4295
4296
4297
4298
4299
4300
4301
          ossl_strerror(sslerror, error_buffer, sizeof(error_buffer));
        else if(sockerr && err == SSL_ERROR_SYSCALL)
          Curl_strerror(sockerr, error_buffer, sizeof(error_buffer));
        else {
          strncpy(error_buffer, SSL_ERROR_to_str(err), sizeof(error_buffer));
          error_buffer[sizeof(error_buffer) - 1] = '\0';
        }
        failf(data, OSSL_PACKAGE " SSL_read: %s, errno %d",
              error_buffer, sockerr);
        *curlcode = CURLE_RECV_ERROR;
        return -1;
      }
      /* For debug builds be a little stricter and error on any
         SSL_ERROR_SYSCALL. For example a server may have closed the connection
         abruptly without a close_notify alert. For compatibility with older
4282
4283
4284
4285
4286
4287
4288
4289
4290
4291
4292
4293
4294
4295
4296
4297
4298
4299
4300
4301
4302
4303
4304
4305
4306
4307
4308
        int sockerr = SOCKERRNO;
        if(sockerr)
          Curl_strerror(sockerr, error_buffer, sizeof(error_buffer));
        else {
          msnprintf(error_buffer, sizeof(error_buffer),
                    "Connection closed abruptly");
        }
        failf(conn->data, OSSL_PACKAGE " SSL_read: %s, errno %d"
              " (Fatal because this is a curl debug build)",
              error_buffer, sockerr);
        *curlcode = CURLE_RECV_ERROR;
        return -1;
      }
#endif
    }
  }
  return nread;
}

static size_t Curl_ossl_version(char *buffer, size_t size)
{
#ifdef LIBRESSL_VERSION_NUMBER
#if LIBRESSL_VERSION_NUMBER < 0x2070100fL
  return msnprintf(buffer, size, "%s/%lx.%lx.%lx",
                   OSSL_PACKAGE,
                   (LIBRESSL_VERSION_NUMBER>>28)&0xf,
                   (LIBRESSL_VERSION_NUMBER>>20)&0xff,







|











|







4309
4310
4311
4312
4313
4314
4315
4316
4317
4318
4319
4320
4321
4322
4323
4324
4325
4326
4327
4328
4329
4330
4331
4332
4333
4334
4335
        int sockerr = SOCKERRNO;
        if(sockerr)
          Curl_strerror(sockerr, error_buffer, sizeof(error_buffer));
        else {
          msnprintf(error_buffer, sizeof(error_buffer),
                    "Connection closed abruptly");
        }
        failf(data, OSSL_PACKAGE " SSL_read: %s, errno %d"
              " (Fatal because this is a curl debug build)",
              error_buffer, sockerr);
        *curlcode = CURLE_RECV_ERROR;
        return -1;
      }
#endif
    }
  }
  return nread;
}

static size_t ossl_version(char *buffer, size_t size)
{
#ifdef LIBRESSL_VERSION_NUMBER
#if LIBRESSL_VERSION_NUMBER < 0x2070100fL
  return msnprintf(buffer, size, "%s/%lx.%lx.%lx",
                   OSSL_PACKAGE,
                   (LIBRESSL_VERSION_NUMBER>>28)&0xf,
                   (LIBRESSL_VERSION_NUMBER>>20)&0xff,
4365
4366
4367
4368
4369
4370
4371
4372
4373
4374
4375
4376
4377
4378
4379
4380
4381
4382
4383
4384
4385
4386
4387
4388
4389
4390
4391
4392
4393
4394
4395
4396
4397
4398
4399
4400
4401
4402
4403
4404
4405
4406
4407
4408
4409
4410
4411
4412
4413
4414
4415
4416
4417
4418
4419
4420
4421
4422
4423
4424
4425
4426
4427
4428
4429
4430
4431
4432
4433
4434
4435
4436
4437
4438
4439
4440
4441
4442
4443
4444
4445
4446
4447
                   (ssleay_value>>20)&0xff,
                   (ssleay_value>>12)&0xff,
                   sub);
#endif /* OPENSSL_IS_BORINGSSL */
}

/* can be called with data == NULL */
static CURLcode Curl_ossl_random(struct Curl_easy *data,
                                 unsigned char *entropy, size_t length)
{
  int rc;
  if(data) {
    if(Curl_ossl_seed(data)) /* Initiate the seed if not already done */
      return CURLE_FAILED_INIT; /* couldn't seed for some reason */
  }
  else {
    if(!rand_enough())
      return CURLE_FAILED_INIT;
  }
  /* RAND_bytes() returns 1 on success, 0 otherwise.  */
  rc = RAND_bytes(entropy, curlx_uztosi(length));
  return (rc == 1 ? CURLE_OK : CURLE_FAILED_INIT);
}

static CURLcode Curl_ossl_md5sum(unsigned char *tmp, /* input */
                                 size_t tmplen,
                                 unsigned char *md5sum /* output */,
                                 size_t unused)
{
  EVP_MD_CTX *mdctx;
  unsigned int len = 0;
  (void) unused;

  mdctx = EVP_MD_CTX_create();
  if(!mdctx)
    return CURLE_OUT_OF_MEMORY;
  EVP_DigestInit(mdctx, EVP_md5());
  EVP_DigestUpdate(mdctx, tmp, tmplen);
  EVP_DigestFinal_ex(mdctx, md5sum, &len);
  EVP_MD_CTX_destroy(mdctx);
  return CURLE_OK;
}

#if (OPENSSL_VERSION_NUMBER >= 0x0090800fL) && !defined(OPENSSL_NO_SHA256)
static CURLcode Curl_ossl_sha256sum(const unsigned char *tmp, /* input */
                                size_t tmplen,
                                unsigned char *sha256sum /* output */,
                                size_t unused)
{
  EVP_MD_CTX *mdctx;
  unsigned int len = 0;
  (void) unused;

  mdctx = EVP_MD_CTX_create();
  if(!mdctx)
    return CURLE_OUT_OF_MEMORY;
  EVP_DigestInit(mdctx, EVP_sha256());
  EVP_DigestUpdate(mdctx, tmp, tmplen);
  EVP_DigestFinal_ex(mdctx, sha256sum, &len);
  EVP_MD_CTX_destroy(mdctx);
  return CURLE_OK;
}
#endif

static bool Curl_ossl_cert_status_request(void)
{
#if (OPENSSL_VERSION_NUMBER >= 0x0090808fL) && !defined(OPENSSL_NO_TLSEXT) && \
    !defined(OPENSSL_NO_OCSP)
  return TRUE;
#else
  return FALSE;
#endif
}

static void *Curl_ossl_get_internals(struct ssl_connect_data *connssl,
                                     CURLINFO info)
{
  /* Legacy: CURLINFO_TLS_SESSION must return an SSL_CTX pointer. */
  struct ssl_backend_data *backend = connssl->backend;
  return info == CURLINFO_TLS_SESSION ?
         (void *)backend->ctx : (void *)backend->handle;
}








|
|



|











<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<

|
|
|
|
















|









|
|







4392
4393
4394
4395
4396
4397
4398
4399
4400
4401
4402
4403
4404
4405
4406
4407
4408
4409
4410
4411
4412
4413
4414
4415



















4416
4417
4418
4419
4420
4421
4422
4423
4424
4425
4426
4427
4428
4429
4430
4431
4432
4433
4434
4435
4436
4437
4438
4439
4440
4441
4442
4443
4444
4445
4446
4447
4448
4449
4450
4451
4452
4453
4454
4455
                   (ssleay_value>>20)&0xff,
                   (ssleay_value>>12)&0xff,
                   sub);
#endif /* OPENSSL_IS_BORINGSSL */
}

/* can be called with data == NULL */
static CURLcode ossl_random(struct Curl_easy *data,
                            unsigned char *entropy, size_t length)
{
  int rc;
  if(data) {
    if(ossl_seed(data)) /* Initiate the seed if not already done */
      return CURLE_FAILED_INIT; /* couldn't seed for some reason */
  }
  else {
    if(!rand_enough())
      return CURLE_FAILED_INIT;
  }
  /* RAND_bytes() returns 1 on success, 0 otherwise.  */
  rc = RAND_bytes(entropy, curlx_uztosi(length));
  return (rc == 1 ? CURLE_OK : CURLE_FAILED_INIT);
}




















#if (OPENSSL_VERSION_NUMBER >= 0x0090800fL) && !defined(OPENSSL_NO_SHA256)
static CURLcode ossl_sha256sum(const unsigned char *tmp, /* input */
                               size_t tmplen,
                               unsigned char *sha256sum /* output */,
                               size_t unused)
{
  EVP_MD_CTX *mdctx;
  unsigned int len = 0;
  (void) unused;

  mdctx = EVP_MD_CTX_create();
  if(!mdctx)
    return CURLE_OUT_OF_MEMORY;
  EVP_DigestInit(mdctx, EVP_sha256());
  EVP_DigestUpdate(mdctx, tmp, tmplen);
  EVP_DigestFinal_ex(mdctx, sha256sum, &len);
  EVP_MD_CTX_destroy(mdctx);
  return CURLE_OK;
}
#endif

static bool ossl_cert_status_request(void)
{
#if (OPENSSL_VERSION_NUMBER >= 0x0090808fL) && !defined(OPENSSL_NO_TLSEXT) && \
    !defined(OPENSSL_NO_OCSP)
  return TRUE;
#else
  return FALSE;
#endif
}

static void *ossl_get_internals(struct ssl_connect_data *connssl,
                                CURLINFO info)
{
  /* Legacy: CURLINFO_TLS_SESSION must return an SSL_CTX pointer. */
  struct ssl_backend_data *backend = connssl->backend;
  return info == CURLINFO_TLS_SESSION ?
         (void *)backend->ctx : (void *)backend->handle;
}

4455
4456
4457
4458
4459
4460
4461
4462
4463
4464
4465
4466
4467
4468
4469
4470
4471
4472
4473
4474
4475
4476
4477
4478
4479
4480
4481
4482
4483
4484
4485
4486
4487
4488
#ifdef HAVE_SSL_CTX_SET_CIPHERSUITES
  SSLSUPP_TLS13_CIPHERSUITES |
#endif
  SSLSUPP_HTTPS_PROXY,

  sizeof(struct ssl_backend_data),

  Curl_ossl_init,                /* init */
  Curl_ossl_cleanup,             /* cleanup */
  Curl_ossl_version,             /* version */
  Curl_ossl_check_cxn,           /* check_cxn */
  Curl_ossl_shutdown,            /* shutdown */
  Curl_ossl_data_pending,        /* data_pending */
  Curl_ossl_random,              /* random */
  Curl_ossl_cert_status_request, /* cert_status_request */
  Curl_ossl_connect,             /* connect */
  Curl_ossl_connect_nonblocking, /* connect_nonblocking */
  Curl_ossl_get_internals,       /* get_internals */
  Curl_ossl_close,               /* close_one */
  Curl_ossl_close_all,           /* close_all */
  Curl_ossl_session_free,        /* session_free */
  Curl_ossl_set_engine,          /* set_engine */
  Curl_ossl_set_engine_default,  /* set_engine_default */
  Curl_ossl_engines_list,        /* engines_list */
  Curl_none_false_start,         /* false_start */
  Curl_ossl_md5sum,              /* md5sum */
#if (OPENSSL_VERSION_NUMBER >= 0x0090800fL) && !defined(OPENSSL_NO_SHA256)
  Curl_ossl_sha256sum            /* sha256sum */
#else
  NULL                           /* sha256sum */
#endif
};

#endif /* USE_OPENSSL */







|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<

|

|




4463
4464
4465
4466
4467
4468
4469
4470
4471
4472
4473
4474
4475
4476
4477
4478
4479
4480
4481
4482
4483
4484
4485
4486
4487

4488
4489
4490
4491
4492
4493
4494
4495
#ifdef HAVE_SSL_CTX_SET_CIPHERSUITES
  SSLSUPP_TLS13_CIPHERSUITES |
#endif
  SSLSUPP_HTTPS_PROXY,

  sizeof(struct ssl_backend_data),

  ossl_init,                /* init */
  ossl_cleanup,             /* cleanup */
  ossl_version,             /* version */
  ossl_check_cxn,           /* check_cxn */
  ossl_shutdown,            /* shutdown */
  ossl_data_pending,        /* data_pending */
  ossl_random,              /* random */
  ossl_cert_status_request, /* cert_status_request */
  ossl_connect,             /* connect */
  ossl_connect_nonblocking, /* connect_nonblocking */
  ossl_get_internals,       /* get_internals */
  ossl_close,               /* close_one */
  ossl_close_all,           /* close_all */
  ossl_session_free,        /* session_free */
  ossl_set_engine,          /* set_engine */
  ossl_set_engine_default,  /* set_engine_default */
  ossl_engines_list,        /* engines_list */
  Curl_none_false_start,    /* false_start */

#if (OPENSSL_VERSION_NUMBER >= 0x0090800fL) && !defined(OPENSSL_NO_SHA256)
  ossl_sha256sum            /* sha256sum */
#else
  NULL                      /* sha256sum */
#endif
};

#endif /* USE_OPENSSL */
Changes to jni/curl/lib/vtls/schannel.c.
1
2
3
4
5
6
7

8
9
10
11
12
13
14
15
16
17
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *

 * Copyright (C) 2012 - 2016, Marc Hoersken, <info@marc-hoersken.de>
 * Copyright (C) 2012, Mark Salisbury, <mark.salisbury@hp.com>
 * Copyright (C) 2012 - 2020, 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 https://curl.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







>


<







1
2
3
4
5
6
7
8
9
10

11
12
13
14
15
16
17
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 2012 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
 * Copyright (C) 2012 - 2016, Marc Hoersken, <info@marc-hoersken.de>
 * Copyright (C) 2012, Mark Salisbury, <mark.salisbury@hp.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 https://curl.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
138
139
140
141
142
143
144
145

146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165

166
167
168
169
170
171
172
173
174
#endif

#define BACKEND connssl->backend

static Curl_recv schannel_recv;
static Curl_send schannel_send;

static CURLcode pkp_pin_peer_pubkey(struct connectdata *conn, int sockindex,

                                    const char *pinnedpubkey);

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
set_ssl_version_min_max(SCHANNEL_CRED *schannel_cred, struct connectdata *conn)

{
  struct Curl_easy *data = conn->data;
  long ssl_version = SSL_CONN_CONFIG(version);
  long ssl_version_max = SSL_CONN_CONFIG(version_max);
  long i = ssl_version;

  switch(ssl_version_max) {
  case CURL_SSLVERSION_MAX_NONE:
  case CURL_SSLVERSION_MAX_DEFAULT:







|
>



















|
>

<







138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168

169
170
171
172
173
174
175
#endif

#define BACKEND connssl->backend

static Curl_recv schannel_recv;
static Curl_send schannel_send;

static CURLcode pkp_pin_peer_pubkey(struct Curl_easy *data,
                                    struct connectdata *conn, int sockindex,
                                    const char *pinnedpubkey);

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
set_ssl_version_min_max(SCHANNEL_CRED *schannel_cred, struct Curl_easy *data,
                        struct connectdata *conn)
{

  long ssl_version = SSL_CONN_CONFIG(version);
  long ssl_version_max = SSL_CONN_CONFIG(version_max);
  long i = ssl_version;

  switch(ssl_version_max) {
  case CURL_SSLVERSION_MAX_NONE:
  case CURL_SSLVERSION_MAX_DEFAULT:
401
402
403
404
405
406
407
408

409
410
411
412
413
414
415
416
417
418
    return CURLE_OUT_OF_MEMORY;

  return CURLE_OK;
}
#endif

static CURLcode
schannel_connect_step1(struct connectdata *conn, int sockindex)

{
  ssize_t written = -1;
  struct Curl_easy *data = conn->data;
  struct ssl_connect_data *connssl = &conn->ssl[sockindex];
  SecBuffer outbuf;
  SecBufferDesc outbuf_desc;
  SecBuffer inbuf;
  SecBufferDesc inbuf_desc;
#ifdef HAS_ALPN
  unsigned char alpn_buffer[128];







|
>


<







402
403
404
405
406
407
408
409
410
411
412

413
414
415
416
417
418
419
    return CURLE_OUT_OF_MEMORY;

  return CURLE_OK;
}
#endif

static CURLcode
schannel_connect_step1(struct Curl_easy *data, struct connectdata *conn,
                       int sockindex)
{
  ssize_t written = -1;

  struct ssl_connect_data *connssl = &conn->ssl[sockindex];
  SecBuffer outbuf;
  SecBufferDesc outbuf_desc;
  SecBuffer inbuf;
  SecBufferDesc inbuf_desc;
#ifdef HAS_ALPN
  unsigned char alpn_buffer[128];
489
490
491
492
493
494
495
496
497

498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
#endif
#endif

  BACKEND->cred = NULL;

  /* check for an existing re-usable credential handle */
  if(SSL_SET_OPTION(primary.sessionid)) {
    Curl_ssl_sessionid_lock(conn);
    if(!Curl_ssl_getsessionid(conn, (void **)&old_cred, NULL, sockindex)) {

      BACKEND->cred = old_cred;
      DEBUGF(infof(data, "schannel: re-using existing credential handle\n"));

      /* increment the reference counter of the credential/session handle */
      BACKEND->cred->refcount++;
      DEBUGF(infof(data,
                   "schannel: incremented credential handle refcount = %d\n",
                   BACKEND->cred->refcount));
    }
    Curl_ssl_sessionid_unlock(conn);
  }

  if(!BACKEND->cred) {
    /* setup Schannel API options */
    memset(&schannel_cred, 0, sizeof(schannel_cred));
    schannel_cred.dwVersion = SCHANNEL_CRED_VERSION;








|
|
>









|







490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
#endif
#endif

  BACKEND->cred = NULL;

  /* check for an existing re-usable credential handle */
  if(SSL_SET_OPTION(primary.sessionid)) {
    Curl_ssl_sessionid_lock(data);
    if(!Curl_ssl_getsessionid(data, conn,
                              (void **)&old_cred, NULL, sockindex)) {
      BACKEND->cred = old_cred;
      DEBUGF(infof(data, "schannel: re-using existing credential handle\n"));

      /* increment the reference counter of the credential/session handle */
      BACKEND->cred->refcount++;
      DEBUGF(infof(data,
                   "schannel: incremented credential handle refcount = %d\n",
                   BACKEND->cred->refcount));
    }
    Curl_ssl_sessionid_unlock(data);
  }

  if(!BACKEND->cred) {
    /* setup Schannel API options */
    memset(&schannel_cred, 0, sizeof(schannel_cred));
    schannel_cred.dwVersion = SCHANNEL_CRED_VERSION;

559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
    case CURL_SSLVERSION_DEFAULT:
    case CURL_SSLVERSION_TLSv1:
    case CURL_SSLVERSION_TLSv1_0:
    case CURL_SSLVERSION_TLSv1_1:
    case CURL_SSLVERSION_TLSv1_2:
    case CURL_SSLVERSION_TLSv1_3:
    {
      result = set_ssl_version_min_max(&schannel_cred, conn);
      if(result != CURLE_OK)
        return result;
      break;
    }
    case CURL_SSLVERSION_SSLv3:
      schannel_cred.grbitEnabledProtocols = SP_PROT_SSL3_CLIENT;
      break;







|







561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
    case CURL_SSLVERSION_DEFAULT:
    case CURL_SSLVERSION_TLSv1:
    case CURL_SSLVERSION_TLSv1_0:
    case CURL_SSLVERSION_TLSv1_1:
    case CURL_SSLVERSION_TLSv1_2:
    case CURL_SSLVERSION_TLSv1_3:
    {
      result = set_ssl_version_min_max(&schannel_cred, data, conn);
      if(result != CURLE_OK)
        return result;
      break;
    }
    case CURL_SSLVERSION_SSLv3:
      schannel_cred.grbitEnabledProtocols = SP_PROT_SSL3_CLIENT;
      break;
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
    }
  }

  DEBUGF(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;
  }







|







954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
    }
  }

  DEBUGF(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(data, 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;
  }
976
977
978
979
980
981
982
983

984
985
986
987
988
989
990
991
992
993
994
  /* 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 Curl_easy *data = conn->data;
  struct ssl_connect_data *connssl = &conn->ssl[sockindex];
  unsigned char *reallocated_buffer;
  SecBuffer outbuf[3];
  SecBufferDesc outbuf_desc;
  SecBuffer inbuf[2];
  SecBufferDesc inbuf_desc;
  SECURITY_STATUS sspi_status = SEC_E_OK;







|
>



<







978
979
980
981
982
983
984
985
986
987
988
989

990
991
992
993
994
995
996
  /* continue to second handshake step */
  connssl->connecting_state = ssl_connect_2;

  return CURLE_OK;
}

static CURLcode
schannel_connect_step2(struct Curl_easy *data, struct connectdata *conn,
                       int sockindex)
{
  int i;
  ssize_t nread = -1, written = -1;

  struct ssl_connect_data *connssl = &conn->ssl[sockindex];
  unsigned char *reallocated_buffer;
  SecBuffer outbuf[3];
  SecBufferDesc outbuf_desc;
  SecBuffer inbuf[2];
  SecBufferDesc inbuf_desc;
  SECURITY_STATUS sspi_status = SEC_E_OK;
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
      for(i = 0; i < 3; i++) {
        /* search for handshake tokens that need to be send */
        if(outbuf[i].BufferType == SECBUFFER_TOKEN && outbuf[i].cbBuffer > 0) {
          DEBUGF(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;







|







1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
      for(i = 0; i < 3; i++) {
        /* search for handshake tokens that need to be send */
        if(outbuf[i].BufferType == SECBUFFER_TOKEN && outbuf[i].cbBuffer > 0) {
          DEBUGF(infof(data, "schannel: sending next handshake data: "
                       "sending %lu bytes...\n", outbuf[i].cbBuffer));

          /* send handshake token to server */
          result = Curl_write_plain(data, 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;
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
    DEBUGF(infof(data, "schannel: SSL/TLS handshake complete\n"));
  }

  pubkey_ptr = SSL_IS_PROXY() ?
    data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY] :
    data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG];
  if(pubkey_ptr) {
    result = pkp_pin_peer_pubkey(conn, sockindex, pubkey_ptr);
    if(result) {
      failf(data, "SSL: public key does not match pinned public key!");
      return result;
    }
  }

#ifdef HAS_MANUAL_VERIFY_API
  if(conn->ssl_config.verifypeer && BACKEND->use_manual_cred_validation) {
    return Curl_verify_certificate(conn, sockindex);
  }
#endif

  return CURLE_OK;
}

static bool







|








|







1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
    DEBUGF(infof(data, "schannel: SSL/TLS handshake complete\n"));
  }

  pubkey_ptr = SSL_IS_PROXY() ?
    data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY] :
    data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG];
  if(pubkey_ptr) {
    result = pkp_pin_peer_pubkey(data, conn, sockindex, pubkey_ptr);
    if(result) {
      failf(data, "SSL: public key does not match pinned public key!");
      return result;
    }
  }

#ifdef HAS_MANUAL_VERIFY_API
  if(conn->ssl_config.verifypeer && BACKEND->use_manual_cred_validation) {
    return Curl_verify_certificate(data, conn, sockindex);
  }
#endif

  return CURLE_OK;
}

static bool
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323

1324
1325
1326
1327
1328
1329
1330

1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
  if(valid_cert_encoding(ccert_context))
    (*(int *)certs_count)++;
  return true;
}

struct Adder_args
{
  struct connectdata *conn;
  CURLcode result;
  int idx;
  int certs_count;
};

static bool
add_cert_to_certinfo(const CERT_CONTEXT *ccert_context, void *raw_arg)
{
  struct Adder_args *args = (struct Adder_args*)raw_arg;
  args->result = CURLE_OK;
  if(valid_cert_encoding(ccert_context)) {
    const char *beg = (const char *) ccert_context->pbCertEncoded;
    const char *end = beg + ccert_context->cbCertEncoded;
    int insert_index = (args->certs_count - 1) - args->idx;
    args->result = Curl_extract_certinfo(args->conn, insert_index, beg, end);

    args->idx++;
  }
  return args->result == CURLE_OK;
}

static CURLcode
schannel_connect_step3(struct connectdata *conn, int sockindex)

{
  CURLcode result = CURLE_OK;
  struct Curl_easy *data = conn->data;
  struct ssl_connect_data *connssl = &conn->ssl[sockindex];
  SECURITY_STATUS sspi_status = SEC_E_OK;
  CERT_CONTEXT *ccert_context = NULL;
#ifdef DEBUGBUILD
  const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name :
    conn->host.name;
#endif







|














|
>






|
>


<







1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336

1337
1338
1339
1340
1341
1342
1343
  if(valid_cert_encoding(ccert_context))
    (*(int *)certs_count)++;
  return true;
}

struct Adder_args
{
  struct Curl_easy *data;
  CURLcode result;
  int idx;
  int certs_count;
};

static bool
add_cert_to_certinfo(const CERT_CONTEXT *ccert_context, void *raw_arg)
{
  struct Adder_args *args = (struct Adder_args*)raw_arg;
  args->result = CURLE_OK;
  if(valid_cert_encoding(ccert_context)) {
    const char *beg = (const char *) ccert_context->pbCertEncoded;
    const char *end = beg + ccert_context->cbCertEncoded;
    int insert_index = (args->certs_count - 1) - args->idx;
    args->result = Curl_extract_certinfo(args->data, insert_index,
                                         beg, end);
    args->idx++;
  }
  return args->result == CURLE_OK;
}

static CURLcode
schannel_connect_step3(struct Curl_easy *data, struct connectdata *conn,
                       int sockindex)
{
  CURLcode result = CURLE_OK;

  struct ssl_connect_data *connssl = &conn->ssl[sockindex];
  SECURITY_STATUS sspi_status = SEC_E_OK;
  CERT_CONTEXT *ccert_context = NULL;
#ifdef DEBUGBUILD
  const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name :
    conn->host.name;
#endif
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
           !memcmp(ALPN_HTTP_1_1, alpn_result.ProtocolId,
                   ALPN_HTTP_1_1_LENGTH)) {
          conn->negnpn = CURL_HTTP_VERSION_1_1;
        }
    }
    else
      infof(data, "ALPN, server did not agree to a protocol\n");
    Curl_multiuse_state(conn, conn->negnpn == CURL_HTTP_VERSION_2 ?
                        BUNDLE_MULTIPLEX : BUNDLE_NO_MULTIUSE);
  }
#endif

  /* save the current session data for possible re-use */
  if(SSL_SET_OPTION(primary.sessionid)) {
    bool incache;
    struct Curl_schannel_cred *old_cred = NULL;

    Curl_ssl_sessionid_lock(conn);
    incache = !(Curl_ssl_getsessionid(conn, (void **)&old_cred, NULL,
                                      sockindex));
    if(incache) {
      if(old_cred != BACKEND->cred) {
        DEBUGF(infof(data,
                     "schannel: old credential handle is stale, removing\n"));
        /* we're not taking old_cred ownership here, no refcount++ is needed */
        Curl_ssl_delsessionid(conn, (void *)old_cred);
        incache = FALSE;
      }
    }
    if(!incache) {
      result = Curl_ssl_addsessionid(conn, (void *)BACKEND->cred,
                                     sizeof(struct Curl_schannel_cred),
                                     sockindex);
      if(result) {
        Curl_ssl_sessionid_unlock(conn);
        failf(data, "schannel: failed to store credential handle");
        return result;
      }
      else {
        /* this cred session is now also referenced by sessionid cache */
        BACKEND->cred->refcount++;
        DEBUGF(infof(data,
                     "schannel: stored credential handle in session cache\n"));
      }
    }
    Curl_ssl_sessionid_unlock(conn);
  }

  if(data->set.ssl.certinfo) {
    int certs_count = 0;
    sspi_status =
      s_pSecFn->QueryContextAttributes(&BACKEND->ctxt->ctxt_handle,
                                       SECPKG_ATTR_REMOTE_CERT_CONTEXT,
                                       &ccert_context);

    if((sspi_status != SEC_E_OK) || (ccert_context == NULL)) {
      failf(data, "schannel: failed to retrieve remote cert context");
      return CURLE_PEER_FAILED_VERIFICATION;
    }

    traverse_cert_store(ccert_context, cert_counter_callback, &certs_count);

    result = Curl_ssl_init_certinfo(data, certs_count);
    if(!result) {
      struct Adder_args args;
      args.conn = conn;
      args.idx = 0;
      args.certs_count = certs_count;
      traverse_cert_store(ccert_context, add_cert_to_certinfo, &args);
      result = args.result;
    }
    CertFreeCertificateContext(ccert_context);
    if(result)
      return result;
  }

  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 Curl_easy *data = conn->data;
  struct ssl_connect_data *connssl = &conn->ssl[sockindex];
  curl_socket_t sockfd = conn->sock[sockindex];
  timediff_t timeout_ms;
  int what;

  /* check if the connection has already been established */
  if(ssl_connection_complete == connssl->state) {







|









|
|






|




|



|










|



















|
















|
|


<







1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484

1485
1486
1487
1488
1489
1490
1491
           !memcmp(ALPN_HTTP_1_1, alpn_result.ProtocolId,
                   ALPN_HTTP_1_1_LENGTH)) {
          conn->negnpn = CURL_HTTP_VERSION_1_1;
        }
    }
    else
      infof(data, "ALPN, server did not agree to a protocol\n");
    Curl_multiuse_state(data, conn->negnpn == CURL_HTTP_VERSION_2 ?
                        BUNDLE_MULTIPLEX : BUNDLE_NO_MULTIUSE);
  }
#endif

  /* save the current session data for possible re-use */
  if(SSL_SET_OPTION(primary.sessionid)) {
    bool incache;
    struct Curl_schannel_cred *old_cred = NULL;

    Curl_ssl_sessionid_lock(data);
    incache = !(Curl_ssl_getsessionid(data, conn, (void **)&old_cred, NULL,
                                      sockindex));
    if(incache) {
      if(old_cred != BACKEND->cred) {
        DEBUGF(infof(data,
                     "schannel: old credential handle is stale, removing\n"));
        /* we're not taking old_cred ownership here, no refcount++ is needed */
        Curl_ssl_delsessionid(data, (void *)old_cred);
        incache = FALSE;
      }
    }
    if(!incache) {
      result = Curl_ssl_addsessionid(data, conn, (void *)BACKEND->cred,
                                     sizeof(struct Curl_schannel_cred),
                                     sockindex);
      if(result) {
        Curl_ssl_sessionid_unlock(data);
        failf(data, "schannel: failed to store credential handle");
        return result;
      }
      else {
        /* this cred session is now also referenced by sessionid cache */
        BACKEND->cred->refcount++;
        DEBUGF(infof(data,
                     "schannel: stored credential handle in session cache\n"));
      }
    }
    Curl_ssl_sessionid_unlock(data);
  }

  if(data->set.ssl.certinfo) {
    int certs_count = 0;
    sspi_status =
      s_pSecFn->QueryContextAttributes(&BACKEND->ctxt->ctxt_handle,
                                       SECPKG_ATTR_REMOTE_CERT_CONTEXT,
                                       &ccert_context);

    if((sspi_status != SEC_E_OK) || (ccert_context == NULL)) {
      failf(data, "schannel: failed to retrieve remote cert context");
      return CURLE_PEER_FAILED_VERIFICATION;
    }

    traverse_cert_store(ccert_context, cert_counter_callback, &certs_count);

    result = Curl_ssl_init_certinfo(data, certs_count);
    if(!result) {
      struct Adder_args args;
      args.data = data;
      args.idx = 0;
      args.certs_count = certs_count;
      traverse_cert_store(ccert_context, add_cert_to_certinfo, &args);
      result = args.result;
    }
    CertFreeCertificateContext(ccert_context);
    if(result)
      return result;
  }

  connssl->connecting_state = ssl_connect_done;

  return CURLE_OK;
}

static CURLcode
schannel_connect_common(struct Curl_easy *data, struct connectdata *conn,
                        int sockindex, bool nonblocking, bool *done)
{
  CURLcode result;

  struct ssl_connect_data *connssl = &conn->ssl[sockindex];
  curl_socket_t sockfd = conn->sock[sockindex];
  timediff_t timeout_ms;
  int what;

  /* check if the connection has already been established */
  if(ssl_connection_complete == connssl->state) {
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511

    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) {







|







1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513

    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(data, 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) {
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
    /* 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;







|









|







1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
    /* 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(data, 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(data, conn, sockindex);
    if(result)
      return result;
  }

  if(ssl_connect_done == connssl->connecting_state) {
    connssl->state = ssl_connection_complete;
    conn->recv[sockindex] = schannel_recv;
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605

1606
1607
1608
1609
1610
1611
1612
  /* 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 */







|




|
>







1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
  /* reset our connection state machine */
  connssl->connecting_state = ssl_connect_1;

  return CURLE_OK;
}

static ssize_t
schannel_send(struct Curl_easy *data, int sockindex,
              const void *buf, size_t len, CURLcode *err)
{
  ssize_t written = -1;
  size_t data_len = 0;
  unsigned char *ptr = NULL;
  struct connectdata *conn = data->conn;
  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 */
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
  if(len > BACKEND->stream_sizes.cbMaximumMessage) {
    len = BACKEND->stream_sizes.cbMaximumMessage;
  }

  /* calculate the complete message length and allocate a buffer for it */
  data_len = BACKEND->stream_sizes.cbHeader + len +
    BACKEND->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, BACKEND->stream_sizes.cbHeader);
  InitSecBuffer(&outbuf[1], SECBUFFER_DATA,
                data + BACKEND->stream_sizes.cbHeader, curlx_uztoul(len));
  InitSecBuffer(&outbuf[2], SECBUFFER_STREAM_TRAILER,
                data + BACKEND->stream_sizes.cbHeader + len,
                BACKEND->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);








|
|






|

|

|







1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
  if(len > BACKEND->stream_sizes.cbMaximumMessage) {
    len = BACKEND->stream_sizes.cbMaximumMessage;
  }

  /* calculate the complete message length and allocate a buffer for it */
  data_len = BACKEND->stream_sizes.cbHeader + len +
    BACKEND->stream_sizes.cbTrailer;
  ptr = (unsigned char *) malloc(data_len);
  if(!ptr) {
    *err = CURLE_OUT_OF_MEMORY;
    return -1;
  }

  /* setup output buffers (header, data, trailer, empty) */
  InitSecBuffer(&outbuf[0], SECBUFFER_STREAM_HEADER,
                ptr, BACKEND->stream_sizes.cbHeader);
  InitSecBuffer(&outbuf[1], SECBUFFER_DATA,
                ptr + BACKEND->stream_sizes.cbHeader, curlx_uztoul(len));
  InitSecBuffer(&outbuf[2], SECBUFFER_STREAM_TRAILER,
                ptr + BACKEND->stream_sizes.cbHeader + len,
                BACKEND->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);

1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
      seems the answer is NO.
    */

    /* send entire message or fail */
    while(len > (size_t)written) {
      ssize_t this_write = 0;
      int what;
      timediff_t timeout_ms = Curl_timeleft(conn->data, NULL, FALSE);
      if(timeout_ms < 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;
      }
      else if(!timeout_ms)
        timeout_ms = TIMEDIFF_T_MAX;
      what = SOCKET_WRITABLE(conn->sock[sockindex], timeout_ms);
      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 = -1;
  struct Curl_easy *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;







|


|










|





|







|



















|










|




|







1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
      seems the answer is NO.
    */

    /* send entire message or fail */
    while(len > (size_t)written) {
      ssize_t this_write = 0;
      int what;
      timediff_t timeout_ms = Curl_timeleft(data, NULL, FALSE);
      if(timeout_ms < 0) {
        /* we already got the timeout */
        failf(data, "schannel: timed out sending data "
              "(bytes sent: %zd)", written);
        *err = CURLE_OPERATION_TIMEDOUT;
        written = -1;
        break;
      }
      else if(!timeout_ms)
        timeout_ms = TIMEDIFF_T_MAX;
      what = SOCKET_WRITABLE(conn->sock[sockindex], timeout_ms);
      if(what < 0) {
        /* fatal error */
        failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO);
        *err = CURLE_SEND_ERROR;
        written = -1;
        break;
      }
      else if(0 == what) {
        failf(data, "schannel: timed out sending data "
              "(bytes sent: %zd)", written);
        *err = CURLE_OPERATION_TIMEDOUT;
        written = -1;
        break;
      }
      /* socket is writable */

      result = Curl_write_plain(data, conn->sock[sockindex], ptr + 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(ptr);

  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 Curl_easy *data, int sockindex,
              char *buf, size_t len, CURLcode *err)
{
  size_t size = 0;
  ssize_t nread = -1;
  struct connectdata *conn = data->conn;
  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;
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
    goto cleanup;
  }
  else if(BACKEND->recv_sspi_close_notify) {
    /* once a server has indicated shutdown there is no more encrypted data */
    infof(data, "schannel: server indicated shutdown in a prior call\n");
    goto cleanup;
  }
  else if(!len) {
    /* It's debatable what to return when !len. Regardless we can't return
       immediately because there may be data to decrypt (in the case we want to
       decrypt all encrypted cached data) so handle !len later in cleanup.
    */
    ; /* do nothing */
  }
  else if(!BACKEND->recv_connection_closed) {
    /* increase enc buffer in order to fit the requested amount of data */
    size = BACKEND->encdata_length - BACKEND->encdata_offset;
    if(size < CURL_SCHANNEL_BUFFER_FREE_SIZE ||
       BACKEND->encdata_length < min_encdata_length) {
      reallocated_length = BACKEND->encdata_offset +
        CURL_SCHANNEL_BUFFER_FREE_SIZE;
      if(reallocated_length < min_encdata_length) {







|
|
|
|
|
<
<
|







1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793


1794
1795
1796
1797
1798
1799
1800
1801
    goto cleanup;
  }
  else if(BACKEND->recv_sspi_close_notify) {
    /* once a server has indicated shutdown there is no more encrypted data */
    infof(data, "schannel: server indicated shutdown in a prior call\n");
    goto cleanup;
  }

  /* It's debatable what to return when !len. Regardless we can't return
     immediately because there may be data to decrypt (in the case we want to
     decrypt all encrypted cached data) so handle !len later in cleanup.
  */


  else if(len && !BACKEND->recv_connection_closed) {
    /* increase enc buffer in order to fit the requested amount of data */
    size = BACKEND->encdata_length - BACKEND->encdata_offset;
    if(size < CURL_SCHANNEL_BUFFER_FREE_SIZE ||
       BACKEND->encdata_length < min_encdata_length) {
      reallocated_length = BACKEND->encdata_offset +
        CURL_SCHANNEL_BUFFER_FREE_SIZE;
      if(reallocated_length < min_encdata_length) {
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
                "encrypted data available\n");
          goto cleanup;
        }
        /* begin renegotiation */
        infof(data, "schannel: renegotiating SSL/TLS connection\n");
        connssl->state = ssl_connection_negotiating;
        connssl->connecting_state = ssl_connect_2_writing;
        *err = schannel_connect_common(conn, sockindex, FALSE, &done);
        if(*err) {
          infof(data, "schannel: renegotiation failed\n");
          goto cleanup;
        }
        /* now retry receiving data */
        sspi_status = SEC_E_OK;
        infof(data, "schannel: SSL/TLS connection renegotiated\n");







|







1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
                "encrypted data available\n");
          goto cleanup;
        }
        /* begin renegotiation */
        infof(data, "schannel: renegotiating SSL/TLS connection\n");
        connssl->state = ssl_connection_negotiating;
        connssl->connecting_state = ssl_connect_2_writing;
        *err = schannel_connect_common(data, conn, sockindex, FALSE, &done);
        if(*err) {
          infof(data, "schannel: renegotiation failed\n");
          goto cleanup;
        }
        /* now retry receiving data */
        sspi_status = SEC_E_OK;
        infof(data, "schannel: SSL/TLS connection renegotiated\n");
2060
2061
2062
2063
2064
2065
2066

2067
2068
2069
2070
2071
2072

2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098

2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117

2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
  */
  if(!len)
    *err = CURLE_OK;

  return *err ? -1 : 0;
}


static CURLcode Curl_schannel_connect_nonblocking(struct connectdata *conn,
                                                  int sockindex, bool *done)
{
  return schannel_connect_common(conn, sockindex, TRUE, done);
}


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;
}

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 (BACKEND->decdata_offset > 0 ||
            (BACKEND->encdata_offset > 0 && !BACKEND->encdata_is_incomplete));
  else
    return FALSE;
}


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);
}

static void Curl_schannel_session_free(void *ptr)
{
  /* this is expected to be called under sessionid lock */
  struct Curl_schannel_cred *cred = ptr;

  cred->refcount--;
  if(cred->refcount == 0) {
    s_pSecFn->FreeCredentialsHandle(&cred->cred_handle);
    Curl_safefree(cred);
  }
}


static int Curl_schannel_shutdown(struct connectdata *conn, int sockindex)
{
  /* See https://msdn.microsoft.com/en-us/library/windows/desktop/aa380138.aspx
   * Shutting Down an Schannel Connection
   */
  struct Curl_easy *data = conn->data;
  struct ssl_connect_data *connssl = &conn->ssl[sockindex];
#ifndef CURL_DISABLE_PROXY
  char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name :
    conn->host.name;
#else
  char * const hostname = conn->host.name;
#endif







>
|
|

|


>
|




|








|
|










>
|



|


|











>
|




<







2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127

2128
2129
2130
2131
2132
2133
2134
  */
  if(!len)
    *err = CURLE_OK;

  return *err ? -1 : 0;
}

static CURLcode schannel_connect_nonblocking(struct Curl_easy *data,
                                             struct connectdata *conn,
                                             int sockindex, bool *done)
{
  return schannel_connect_common(data, conn, sockindex, TRUE, done);
}

static CURLcode schannel_connect(struct Curl_easy *data,
                                 struct connectdata *conn, int sockindex)
{
  CURLcode result;
  bool done = FALSE;

  result = schannel_connect_common(data, conn, sockindex, FALSE, &done);
  if(result)
    return result;

  DEBUGASSERT(done);

  return CURLE_OK;
}

static bool 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 (BACKEND->decdata_offset > 0 ||
            (BACKEND->encdata_offset > 0 && !BACKEND->encdata_is_incomplete));
  else
    return FALSE;
}

static void schannel_close(struct Curl_easy *data, 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(data, conn, sockindex);
}

static void schannel_session_free(void *ptr)
{
  /* this is expected to be called under sessionid lock */
  struct Curl_schannel_cred *cred = ptr;

  cred->refcount--;
  if(cred->refcount == 0) {
    s_pSecFn->FreeCredentialsHandle(&cred->cred_handle);
    Curl_safefree(cred);
  }
}

static int schannel_shutdown(struct Curl_easy *data, struct connectdata *conn,
                             int sockindex)
{
  /* See https://msdn.microsoft.com/en-us/library/windows/desktop/aa380138.aspx
   * Shutting Down an Schannel Connection
   */

  struct ssl_connect_data *connssl = &conn->ssl[sockindex];
#ifndef CURL_DISABLE_PROXY
  char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name :
    conn->host.name;
#else
  char * const hostname = conn->host.name;
#endif
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
      &BACKEND->ctxt->time_stamp);

    curlx_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(BACKEND->ctxt) {
    DEBUGF(infof(data, "schannel: clear security context handle\n"));
    s_pSecFn->DeleteSecurityContext(&BACKEND->ctxt->ctxt_handle);
    Curl_safefree(BACKEND->ctxt);
  }

  /* free SSPI Schannel API credential handle */
  if(BACKEND->cred) {
    /*
     * When this function is called from Curl_schannel_close() the connection
     * might not have an associated transfer so the check for conn->data is
     * necessary.
     */
    Curl_ssl_sessionid_lock(conn);
    Curl_schannel_session_free(BACKEND->cred);
    Curl_ssl_sessionid_unlock(conn);
    BACKEND->cred = NULL;
  }

  /* free internal buffer for received encrypted data */
  if(BACKEND->encdata_buffer != NULL) {
    Curl_safefree(BACKEND->encdata_buffer);
    BACKEND->encdata_length = 0;







|



















<
<
<
<
<
|
|
|







2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209





2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
      &BACKEND->ctxt->time_stamp);

    curlx_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(data, 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(BACKEND->ctxt) {
    DEBUGF(infof(data, "schannel: clear security context handle\n"));
    s_pSecFn->DeleteSecurityContext(&BACKEND->ctxt->ctxt_handle);
    Curl_safefree(BACKEND->ctxt);
  }

  /* free SSPI Schannel API credential handle */
  if(BACKEND->cred) {





    Curl_ssl_sessionid_lock(data);
    schannel_session_free(BACKEND->cred);
    Curl_ssl_sessionid_unlock(data);
    BACKEND->cred = NULL;
  }

  /* free internal buffer for received encrypted data */
  if(BACKEND->encdata_buffer != NULL) {
    Curl_safefree(BACKEND->encdata_buffer);
    BACKEND->encdata_length = 0;
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272

2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
    BACKEND->decdata_length = 0;
    BACKEND->decdata_offset = 0;
  }

  return CURLE_OK;
}

static int Curl_schannel_init(void)
{
  return (Curl_sspi_global_init() == CURLE_OK ? 1 : 0);
}

static void Curl_schannel_cleanup(void)
{
  Curl_sspi_global_cleanup();
}

static size_t Curl_schannel_version(char *buffer, size_t size)
{
  size = msnprintf(buffer, size, "Schannel");

  return size;
}

static CURLcode Curl_schannel_random(struct Curl_easy *data UNUSED_PARAM,
                                     unsigned char *entropy, size_t length)
{
  HCRYPTPROV hCryptProv = 0;

  (void)data;

  if(!CryptAcquireContext(&hCryptProv, NULL, NULL, PROV_RSA_FULL,
                          CRYPT_VERIFYCONTEXT | CRYPT_SILENT))
    return CURLE_FAILED_INIT;

  if(!CryptGenRandom(hCryptProv, (DWORD)length, entropy)) {
    CryptReleaseContext(hCryptProv, 0UL);
    return CURLE_FAILED_INIT;
  }

  CryptReleaseContext(hCryptProv, 0UL);
  return CURLE_OK;
}

static CURLcode pkp_pin_peer_pubkey(struct connectdata *conn, int sockindex,

                                    const char *pinnedpubkey)
{
  struct Curl_easy *data = conn->data;
  struct ssl_connect_data *connssl = &conn->ssl[sockindex];
  CERT_CONTEXT *pCertContextServer = NULL;

  /* Result is returned to caller */
  CURLcode result = CURLE_SSL_PINNEDPUBKEYNOTMATCH;

  /* if a path wasn't specified, don't pin */







|




|




|






|
|


















|
>


<







2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274

2275
2276
2277
2278
2279
2280
2281
    BACKEND->decdata_length = 0;
    BACKEND->decdata_offset = 0;
  }

  return CURLE_OK;
}

static int schannel_init(void)
{
  return (Curl_sspi_global_init() == CURLE_OK ? 1 : 0);
}

static void schannel_cleanup(void)
{
  Curl_sspi_global_cleanup();
}

static size_t schannel_version(char *buffer, size_t size)
{
  size = msnprintf(buffer, size, "Schannel");

  return size;
}

static CURLcode schannel_random(struct Curl_easy *data UNUSED_PARAM,
                                unsigned char *entropy, size_t length)
{
  HCRYPTPROV hCryptProv = 0;

  (void)data;

  if(!CryptAcquireContext(&hCryptProv, NULL, NULL, PROV_RSA_FULL,
                          CRYPT_VERIFYCONTEXT | CRYPT_SILENT))
    return CURLE_FAILED_INIT;

  if(!CryptGenRandom(hCryptProv, (DWORD)length, entropy)) {
    CryptReleaseContext(hCryptProv, 0UL);
    return CURLE_FAILED_INIT;
  }

  CryptReleaseContext(hCryptProv, 0UL);
  return CURLE_OK;
}

static CURLcode pkp_pin_peer_pubkey(struct Curl_easy *data,
                                    struct connectdata *conn, int sockindex,
                                    const char *pinnedpubkey)
{

  struct ssl_connect_data *connssl = &conn->ssl[sockindex];
  CERT_CONTEXT *pCertContextServer = NULL;

  /* Result is returned to caller */
  CURLcode result = CURLE_SSL_PINNEDPUBKEYNOTMATCH;

  /* if a path wasn't specified, don't pin */
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349

  if(pCertContextServer)
    CertFreeCertificateContext(pCertContextServer);

  return result;
}

static void Curl_schannel_checksum(const unsigned char *input,
                                   size_t inputlen,
                                   unsigned char *checksum,
                                   size_t checksumlen,
                                   DWORD provType,
                                   const unsigned int algId)
{
  HCRYPTPROV hProv = 0;
  HCRYPTHASH hHash = 0;
  DWORD cbHashSize = 0;
  DWORD dwHashSizeLen = (DWORD)sizeof(cbHashSize);
  DWORD dwChecksumLen = (DWORD)checksumlen;








|
|
|
|
|
|







2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348

  if(pCertContextServer)
    CertFreeCertificateContext(pCertContextServer);

  return result;
}

static void schannel_checksum(const unsigned char *input,
                              size_t inputlen,
                              unsigned char *checksum,
                              size_t checksumlen,
                              DWORD provType,
                              const unsigned int algId)
{
  HCRYPTPROV hProv = 0;
  HCRYPTHASH hHash = 0;
  DWORD cbHashSize = 0;
  DWORD dwHashSizeLen = (DWORD)sizeof(cbHashSize);
  DWORD dwChecksumLen = (DWORD)checksumlen;

2380
2381
2382
2383
2384
2385
2386
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
  if(hHash)
    CryptDestroyHash(hHash);

  if(hProv)
    CryptReleaseContext(hProv, 0);
}

static CURLcode Curl_schannel_md5sum(unsigned char *input,
                                     size_t inputlen,
                                     unsigned char *md5sum,
                                     size_t md5len)
{
  Curl_schannel_checksum(input, inputlen, md5sum, md5len,
                         PROV_RSA_FULL, CALG_MD5);
  return CURLE_OK;
}

static CURLcode Curl_schannel_sha256sum(const unsigned char *input,
                                        size_t inputlen,
                                        unsigned char *sha256sum,
                                        size_t sha256len)
{
  Curl_schannel_checksum(input, inputlen, sha256sum, sha256len,
                         PROV_RSA_AES, CALG_SHA_256);
  return CURLE_OK;
}

static void *Curl_schannel_get_internals(struct ssl_connect_data *connssl,
                                         CURLINFO info UNUSED_PARAM)
{
  (void)info;
  return &BACKEND->ctxt->ctxt_handle;
}

const struct Curl_ssl Curl_ssl_schannel = {
  { CURLSSLBACKEND_SCHANNEL, "schannel" }, /* info */

  SSLSUPP_CERTINFO |
  SSLSUPP_PINNEDPUBKEY,

  sizeof(struct ssl_backend_data),

  Curl_schannel_init,                /* init */
  Curl_schannel_cleanup,             /* cleanup */
  Curl_schannel_version,             /* version */
  Curl_none_check_cxn,               /* check_cxn */
  Curl_schannel_shutdown,            /* shutdown */
  Curl_schannel_data_pending,        /* data_pending */
  Curl_schannel_random,              /* random */
  Curl_none_cert_status_request,     /* cert_status_request */
  Curl_schannel_connect,             /* connect */
  Curl_schannel_connect_nonblocking, /* connect_nonblocking */
  Curl_schannel_get_internals,       /* get_internals */
  Curl_schannel_close,               /* close_one */
  Curl_none_close_all,               /* close_all */
  Curl_schannel_session_free,        /* session_free */
  Curl_none_set_engine,              /* set_engine */
  Curl_none_set_engine_default,      /* set_engine_default */
  Curl_none_engines_list,            /* engines_list */
  Curl_none_false_start,             /* false_start */
  Curl_schannel_md5sum,              /* md5sum */
  Curl_schannel_sha256sum            /* sha256sum */
};

#endif /* USE_SCHANNEL */







<
<
<
<
<
<
<
<
<
<
|
|
|
|

|
|



|
|













|
|
|

|
|
|

|
|
|
|

|




<
|



2379
2380
2381
2382
2383
2384
2385










2386
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428

2429
2430
2431
2432
  if(hHash)
    CryptDestroyHash(hHash);

  if(hProv)
    CryptReleaseContext(hProv, 0);
}











static CURLcode schannel_sha256sum(const unsigned char *input,
                                   size_t inputlen,
                                   unsigned char *sha256sum,
                                   size_t sha256len)
{
  schannel_checksum(input, inputlen, sha256sum, sha256len,
                    PROV_RSA_AES, CALG_SHA_256);
  return CURLE_OK;
}

static void *schannel_get_internals(struct ssl_connect_data *connssl,
                                    CURLINFO info UNUSED_PARAM)
{
  (void)info;
  return &BACKEND->ctxt->ctxt_handle;
}

const struct Curl_ssl Curl_ssl_schannel = {
  { CURLSSLBACKEND_SCHANNEL, "schannel" }, /* info */

  SSLSUPP_CERTINFO |
  SSLSUPP_PINNEDPUBKEY,

  sizeof(struct ssl_backend_data),

  schannel_init,                     /* init */
  schannel_cleanup,                  /* cleanup */
  schannel_version,                  /* version */
  Curl_none_check_cxn,               /* check_cxn */
  schannel_shutdown,                 /* shutdown */
  schannel_data_pending,             /* data_pending */
  schannel_random,                   /* random */
  Curl_none_cert_status_request,     /* cert_status_request */
  schannel_connect,                  /* connect */
  schannel_connect_nonblocking,      /* connect_nonblocking */
  schannel_get_internals,            /* get_internals */
  schannel_close,                    /* close_one */
  Curl_none_close_all,               /* close_all */
  schannel_session_free,             /* session_free */
  Curl_none_set_engine,              /* set_engine */
  Curl_none_set_engine_default,      /* set_engine_default */
  Curl_none_engines_list,            /* engines_list */
  Curl_none_false_start,             /* false_start */

  schannel_sha256sum                 /* sha256sum */
};

#endif /* USE_SCHANNEL */
Changes to jni/curl/lib/vtls/schannel.h.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#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 - 2020, 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 https://curl.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










|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#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 - 2021, 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 https://curl.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
49
50
51
52
53
54
55
56

57
58
59
60
61
62
63
# undef X509_NAME
# undef X509_CERT_PAIR
# undef X509_EXTENSIONS
#endif

extern const struct Curl_ssl Curl_ssl_schannel;

CURLcode Curl_verify_certificate(struct connectdata *conn, int sockindex);


/* structs to expose only in schannel.c and schannel_verify.c */
#ifdef EXPOSE_SCHANNEL_INTERNAL_STRUCTS

#ifdef __MINGW32__
#include <_mingw.h>
#ifdef __MINGW64_VERSION_MAJOR







|
>







49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
# undef X509_NAME
# undef X509_CERT_PAIR
# undef X509_EXTENSIONS
#endif

extern const struct Curl_ssl Curl_ssl_schannel;

CURLcode Curl_verify_certificate(struct Curl_easy *data,
                                 struct connectdata *conn, int sockindex);

/* structs to expose only in schannel.c and schannel_verify.c */
#ifdef EXPOSE_SCHANNEL_INTERNAL_STRUCTS

#ifdef __MINGW32__
#include <_mingw.h>
#ifdef __MINGW64_VERSION_MAJOR
Changes to jni/curl/lib/vtls/schannel_verify.c.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 2012 - 2016, Marc Hoersken, <info@marc-hoersken.de>
 * Copyright (C) 2012, Mark Salisbury, <mark.salisbury@hp.com>
 * Copyright (C) 2012 - 2020, 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 https://curl.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









|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 2012 - 2016, Marc Hoersken, <info@marc-hoersken.de>
 * Copyright (C) 2012, Mark Salisbury, <mark.salisbury@hp.com>
 * Copyright (C) 2012 - 2021, 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 https://curl.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
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
static int is_cr_or_lf(char c)
{
  return c == '\r' || c == '\n';
}

static CURLcode add_certs_to_store(HCERTSTORE trust_store,
                                   const char *ca_file,
                                   struct connectdata *conn)
{
  CURLcode result;
  struct Curl_easy *data = conn->data;
  HANDLE ca_file_handle = INVALID_HANDLE_VALUE;
  LARGE_INTEGER file_size;
  char *ca_file_buffer = NULL;
  char *current_ca_file_ptr = NULL;
  TCHAR *ca_file_tstr = NULL;
  size_t ca_file_bufsize = 0;
  DWORD total_bytes_read = 0;







|


<







75
76
77
78
79
80
81
82
83
84

85
86
87
88
89
90
91
static int is_cr_or_lf(char c)
{
  return c == '\r' || c == '\n';
}

static CURLcode add_certs_to_store(HCERTSTORE trust_store,
                                   const char *ca_file,
                                   struct Curl_easy *data)
{
  CURLcode result;

  HANDLE ca_file_handle = INVALID_HANDLE_VALUE;
  LARGE_INTEGER file_size;
  char *ca_file_buffer = NULL;
  char *current_ca_file_ptr = NULL;
  TCHAR *ca_file_tstr = NULL;
  size_t ca_file_bufsize = 0;
  DWORD total_bytes_read = 0;
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
    char *cert_hostname;

    /* Comparing the cert name and the connection hostname encoded as UTF-8
     * is acceptable since both values are assumed to use ASCII
     * (or some equivalent) encoding
     */
    cert_hostname = curlx_convert_tchar_to_UTF8(
        &cert_hostname_buff[cert_hostname_buff_index]);
    if(!cert_hostname) {
      result = CURLE_OUT_OF_MEMORY;
    }
    else {
      int match_result;

      match_result = Curl_cert_hostcheck(cert_hostname, conn_hostname);







|







472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
    char *cert_hostname;

    /* Comparing the cert name and the connection hostname encoded as UTF-8
     * is acceptable since both values are assumed to use ASCII
     * (or some equivalent) encoding
     */
    cert_hostname = curlx_convert_tchar_to_UTF8(
      &cert_hostname_buff[cert_hostname_buff_index]);
    if(!cert_hostname) {
      result = CURLE_OUT_OF_MEMORY;
    }
    else {
      int match_result;

      match_result = Curl_cert_hostcheck(cert_hostname, conn_hostname);
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530

531
532
533
534
535
536
537
538
539
540
        size_t cert_hostname_len;

        infof(data,
              "schannel: connection hostname (%s) did not match "
              "against certificate name (%s)\n",
              conn_hostname, cert_hostname);

        cert_hostname_len = _tcslen(
            &cert_hostname_buff[cert_hostname_buff_index]);

        /* Move on to next cert name */
        cert_hostname_buff_index += cert_hostname_len + 1;

        result = CURLE_PEER_FAILED_VERIFICATION;
      }
      curlx_unicodefree(cert_hostname);
    }
  }

  if(result == CURLE_PEER_FAILED_VERIFICATION) {
    failf(data,
          "schannel: CertGetNameString() failed to match "
          "connection hostname (%s) against server certificate names",
          conn_hostname);
  }
  else if(result != CURLE_OK)
    failf(data, "schannel: server certificate name verification failed");

cleanup:
  curlx_unicodefree(cert_hostname_buff);

  return result;
}

CURLcode Curl_verify_certificate(struct connectdata *conn, int sockindex)

{
  SECURITY_STATUS sspi_status;
  struct Curl_easy *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;
  HCERTCHAINENGINE cert_chain_engine = NULL;
  HCERTSTORE trust_store = NULL;
#ifndef CURL_DISABLE_PROXY







|
|




















|




|
>


<







495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532

533
534
535
536
537
538
539
        size_t cert_hostname_len;

        infof(data,
              "schannel: connection hostname (%s) did not match "
              "against certificate name (%s)\n",
              conn_hostname, cert_hostname);

        cert_hostname_len =
          _tcslen(&cert_hostname_buff[cert_hostname_buff_index]);

        /* Move on to next cert name */
        cert_hostname_buff_index += cert_hostname_len + 1;

        result = CURLE_PEER_FAILED_VERIFICATION;
      }
      curlx_unicodefree(cert_hostname);
    }
  }

  if(result == CURLE_PEER_FAILED_VERIFICATION) {
    failf(data,
          "schannel: CertGetNameString() failed to match "
          "connection hostname (%s) against server certificate names",
          conn_hostname);
  }
  else if(result != CURLE_OK)
    failf(data, "schannel: server certificate name verification failed");

cleanup:
  Curl_safefree(cert_hostname_buff);

  return result;
}

CURLcode Curl_verify_certificate(struct Curl_easy *data,
                                 struct connectdata *conn, int sockindex)
{
  SECURITY_STATUS sspi_status;

  struct ssl_connect_data *connssl = &conn->ssl[sockindex];
  CURLcode result = CURLE_OK;
  CERT_CONTEXT *pCertContextServer = NULL;
  const CERT_CHAIN_CONTEXT *pChainContext = NULL;
  HCERTCHAINENGINE cert_chain_engine = NULL;
  HCERTSTORE trust_store = NULL;
#ifndef CURL_DISABLE_PROXY
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
        char buffer[STRERROR_LEN];
        failf(data, "schannel: failed to create certificate store: %s",
              Curl_winapi_strerror(GetLastError(), buffer, sizeof(buffer)));
        result = CURLE_SSL_CACERT_BADFILE;
      }
      else {
        result = add_certs_to_store(trust_store, SSL_CONN_CONFIG(CAfile),
                                    conn);
      }
    }

    if(result == CURLE_OK) {
      struct cert_chain_engine_config_win7 engine_config;
      BOOL create_engine_result;








|







579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
        char buffer[STRERROR_LEN];
        failf(data, "schannel: failed to create certificate store: %s",
              Curl_winapi_strerror(GetLastError(), buffer, sizeof(buffer)));
        result = CURLE_SSL_CACERT_BADFILE;
      }
      else {
        result = add_certs_to_store(trust_store, SSL_CONN_CONFIG(CAfile),
                                    data);
      }
    }

    if(result == CURLE_OK) {
      struct cert_chain_engine_config_win7 engine_config;
      BOOL create_engine_result;

671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
        result = CURLE_PEER_FAILED_VERIFICATION;
      }
    }
  }

  if(result == CURLE_OK) {
    if(SSL_CONN_CONFIG(verifyhost)) {
      result = verify_host(conn->data, pCertContextServer, conn_hostname);
    }
  }

  if(cert_chain_engine) {
    CertFreeCertificateChainEngine(cert_chain_engine);
  }








|







670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
        result = CURLE_PEER_FAILED_VERIFICATION;
      }
    }
  }

  if(result == CURLE_OK) {
    if(SSL_CONN_CONFIG(verifyhost)) {
      result = verify_host(data, pCertContextServer, conn_hostname);
    }
  }

  if(cert_chain_engine) {
    CertFreeCertificateChainEngine(cert_chain_engine);
  }

Changes to jni/curl/lib/vtls/sectransp.c.
1
2
3
4
5
6
7

8
9
10
11
12
13
14
15
16
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *

 * Copyright (C) 2012 - 2017, Nick Zitzmann, <nickzman@gmail.com>.
 * Copyright (C) 2012 - 2020, 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 https://curl.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







>

<







1
2
3
4
5
6
7
8
9

10
11
12
13
14
15
16
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 2012 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
 * Copyright (C) 2012 - 2017, Nick Zitzmann, <nickzman@gmail.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 https://curl.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
1287
1288
1289
1290
1291
1292
1293
1294

1295
1296
1297
1298
1299
1300
1301
1302
1303
      break;
  }
  return CURLE_SSL_CONNECT_ERROR;
}
#endif

static CURLcode
set_ssl_version_min_max(struct connectdata *conn, int sockindex)

{
  struct Curl_easy *data = conn->data;
  struct ssl_connect_data *connssl = &conn->ssl[sockindex];
  struct ssl_backend_data *backend = connssl->backend;
  long ssl_version = SSL_CONN_CONFIG(version);
  long ssl_version_max = SSL_CONN_CONFIG(version_max);
  long max_supported_version_by_os;

  /* macOS 10.5-10.7 supported TLS 1.0 only.







|
>

<







1287
1288
1289
1290
1291
1292
1293
1294
1295
1296

1297
1298
1299
1300
1301
1302
1303
      break;
  }
  return CURLE_SSL_CONNECT_ERROR;
}
#endif

static CURLcode
set_ssl_version_min_max(struct Curl_easy *data, struct connectdata *conn,
                        int sockindex)
{

  struct ssl_connect_data *connssl = &conn->ssl[sockindex];
  struct ssl_backend_data *backend = connssl->backend;
  long ssl_version = SSL_CONN_CONFIG(version);
  long ssl_version_max = SSL_CONN_CONFIG(version_max);
  long max_supported_version_by_os;

  /* macOS 10.5-10.7 supported TLS 1.0 only.
1383
1384
1385
1386
1387
1388
1389
1390

1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
  }
#endif  /* CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS */
  failf(data, "Secure Transport: cannot set SSL protocol");
  return CURLE_SSL_CONNECT_ERROR;
}


static CURLcode sectransp_connect_step1(struct connectdata *conn,

                                        int sockindex)
{
  struct Curl_easy *data = conn->data;
  curl_socket_t sockfd = conn->sock[sockindex];
  struct ssl_connect_data *connssl = &conn->ssl[sockindex];
  struct ssl_backend_data *backend = connssl->backend;
  const char * const ssl_cafile = SSL_CONN_CONFIG(CAfile);
  const struct curl_blob *ssl_cablob = NULL;
  const bool verifypeer = SSL_CONN_CONFIG(verifypeer);
  char * const ssl_cert = SSL_SET_OPTION(primary.clientcert);







|
>


<







1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393

1394
1395
1396
1397
1398
1399
1400
  }
#endif  /* CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS */
  failf(data, "Secure Transport: cannot set SSL protocol");
  return CURLE_SSL_CONNECT_ERROR;
}


static CURLcode sectransp_connect_step1(struct Curl_easy *data,
                                        struct connectdata *conn,
                                        int sockindex)
{

  curl_socket_t sockfd = conn->sock[sockindex];
  struct ssl_connect_data *connssl = &conn->ssl[sockindex];
  struct ssl_backend_data *backend = connssl->backend;
  const char * const ssl_cafile = SSL_CONN_CONFIG(CAfile);
  const struct curl_blob *ssl_cablob = NULL;
  const bool verifypeer = SSL_CONN_CONFIG(verifypeer);
  char * const ssl_cert = SSL_SET_OPTION(primary.clientcert);
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
      break;
    case CURL_SSLVERSION_DEFAULT:
    case CURL_SSLVERSION_TLSv1_0:
    case CURL_SSLVERSION_TLSv1_1:
    case CURL_SSLVERSION_TLSv1_2:
    case CURL_SSLVERSION_TLSv1_3:
      {
        CURLcode result = set_ssl_version_min_max(conn, sockindex);
        if(result != CURLE_OK)
          return result;
        break;
      }
    case CURL_SSLVERSION_SSLv3:
      err = SSLSetProtocolVersionMin(backend->ssl_ctx, kSSLProtocol3);
      if(err != noErr) {







|







1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
      break;
    case CURL_SSLVERSION_DEFAULT:
    case CURL_SSLVERSION_TLSv1_0:
    case CURL_SSLVERSION_TLSv1_1:
    case CURL_SSLVERSION_TLSv1_2:
    case CURL_SSLVERSION_TLSv1_3:
      {
        CURLcode result = set_ssl_version_min_max(data, conn, sockindex);
        if(result != CURLE_OK)
          return result;
        break;
      }
    case CURL_SSLVERSION_SSLv3:
      err = SSLSetProtocolVersionMin(backend->ssl_ctx, kSSLProtocol3);
      if(err != noErr) {
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
                                         true);
      break;
    case CURL_SSLVERSION_TLSv1_0:
    case CURL_SSLVERSION_TLSv1_1:
    case CURL_SSLVERSION_TLSv1_2:
    case CURL_SSLVERSION_TLSv1_3:
      {
        CURLcode result = set_ssl_version_min_max(conn, sockindex);
        if(result != CURLE_OK)
          return result;
        break;
      }
    case CURL_SSLVERSION_SSLv3:
      err = SSLSetProtocolVersionEnabled(backend->ssl_ctx,
                                         kSSLProtocol3,







|







1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
                                         true);
      break;
    case CURL_SSLVERSION_TLSv1_0:
    case CURL_SSLVERSION_TLSv1_1:
    case CURL_SSLVERSION_TLSv1_2:
    case CURL_SSLVERSION_TLSv1_3:
      {
        CURLcode result = set_ssl_version_min_max(data, conn, sockindex);
        if(result != CURLE_OK)
          return result;
        break;
      }
    case CURL_SSLVERSION_SSLv3:
      err = SSLSetProtocolVersionEnabled(backend->ssl_ctx,
                                         kSSLProtocol3,
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
#endif /* CURL_BUILD_MAC_10_9 || CURL_BUILD_IOS_7 */

  /* Check if there's a cached ID we can/should use here! */
  if(SSL_SET_OPTION(primary.sessionid)) {
    char *ssl_sessionid;
    size_t ssl_sessionid_len;

    Curl_ssl_sessionid_lock(conn);
    if(!Curl_ssl_getsessionid(conn, (void **)&ssl_sessionid,
                              &ssl_sessionid_len, sockindex)) {
      /* we got a session id, use it! */
      err = SSLSetPeerID(backend->ssl_ctx, ssl_sessionid, ssl_sessionid_len);
      Curl_ssl_sessionid_unlock(conn);
      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:%ld", ssl_cafile,
                verifypeer, SSL_CONN_CONFIG(verifyhost), hostname, port);
      ssl_sessionid_len = strlen(ssl_sessionid);

      err = SSLSetPeerID(backend->ssl_ctx, ssl_sessionid, ssl_sessionid_len);
      if(err != noErr) {
        Curl_ssl_sessionid_unlock(conn);
        failf(data, "SSL: SSLSetPeerID() failed: OSStatus %d", err);
        return CURLE_SSL_CONNECT_ERROR;
      }

      result = Curl_ssl_addsessionid(conn, ssl_sessionid, ssl_sessionid_len,
                                     sockindex);
      Curl_ssl_sessionid_unlock(conn);
      if(result) {
        failf(data, "failed to store ssl session");
        return result;
      }
    }
  }








|
|



|


















|




|
|
|







1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
#endif /* CURL_BUILD_MAC_10_9 || CURL_BUILD_IOS_7 */

  /* Check if there's a cached ID we can/should use here! */
  if(SSL_SET_OPTION(primary.sessionid)) {
    char *ssl_sessionid;
    size_t ssl_sessionid_len;

    Curl_ssl_sessionid_lock(data);
    if(!Curl_ssl_getsessionid(data, conn, (void **)&ssl_sessionid,
                              &ssl_sessionid_len, sockindex)) {
      /* we got a session id, use it! */
      err = SSLSetPeerID(backend->ssl_ctx, ssl_sessionid, ssl_sessionid_len);
      Curl_ssl_sessionid_unlock(data);
      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:%ld", ssl_cafile,
                verifypeer, SSL_CONN_CONFIG(verifyhost), hostname, port);
      ssl_sessionid_len = strlen(ssl_sessionid);

      err = SSLSetPeerID(backend->ssl_ctx, ssl_sessionid, ssl_sessionid_len);
      if(err != noErr) {
        Curl_ssl_sessionid_unlock(data);
        failf(data, "SSL: SSLSetPeerID() failed: OSStatus %d", err);
        return CURLE_SSL_CONNECT_ERROR;
      }

      result = Curl_ssl_addsessionid(data, conn, ssl_sessionid,
                                     ssl_sessionid_len, sockindex);
      Curl_ssl_sessionid_unlock(data);
      if(result) {
        failf(data, "failed to store ssl session");
        return result;
      }
    }
  }

2375
2376
2377
2378
2379
2380
2381
2382

2383
2384
2385
2386
2387
2388
2389
2390
2391
    CFRelease(publicKeyBits);

  return result;
}
#endif /* SECTRANSP_PINNEDPUBKEY */

static CURLcode
sectransp_connect_step2(struct connectdata *conn, int sockindex)

{
  struct Curl_easy *data = conn->data;
  struct ssl_connect_data *connssl = &conn->ssl[sockindex];
  struct ssl_backend_data *backend = connssl->backend;
  OSStatus err;
  SSLCipherSuite cipher;
  SSLProtocol protocol = 0;
#ifndef CURL_DISABLE_PROXY
  const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name :







|
>

<







2375
2376
2377
2378
2379
2380
2381
2382
2383
2384

2385
2386
2387
2388
2389
2390
2391
    CFRelease(publicKeyBits);

  return result;
}
#endif /* SECTRANSP_PINNEDPUBKEY */

static CURLcode
sectransp_connect_step2(struct Curl_easy *data, struct connectdata *conn,
                        int sockindex)
{

  struct ssl_connect_data *connssl = &conn->ssl[sockindex];
  struct ssl_backend_data *backend = connssl->backend;
  OSStatus err;
  SSLCipherSuite cipher;
  SSLProtocol protocol = 0;
#ifndef CURL_DISABLE_PROXY
  const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name :
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428
        if(SSL_CONN_CONFIG(CAfile) && SSL_CONN_CONFIG(verifypeer)) {
          CURLcode result = verify_cert(SSL_CONN_CONFIG(CAfile), data,
                                        backend->ssl_ctx);
          if(result)
            return result;
        }
        /* the documentation says we need to call SSLHandshake() again */
        return sectransp_connect_step2(conn, sockindex);

      /* Problem with encrypt / decrypt */
      case errSSLPeerDecodeError:
        failf(data, "Decode failed");
        break;
      case errSSLDecryptionFail:
      case errSSLPeerDecryptionFail:







|







2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428
        if(SSL_CONN_CONFIG(CAfile) && SSL_CONN_CONFIG(verifypeer)) {
          CURLcode result = verify_cert(SSL_CONN_CONFIG(CAfile), data,
                                        backend->ssl_ctx);
          if(result)
            return result;
        }
        /* the documentation says we need to call SSLHandshake() again */
        return sectransp_connect_step2(data, conn, sockindex);

      /* Problem with encrypt / decrypt */
      case errSSLPeerDecodeError:
        failf(data, "Decode failed");
        break;
      case errSSLDecryptionFail:
      case errSSLPeerDecryptionFail:
2689
2690
2691
2692
2693
2694
2695
2696
2697
2698
2699
2700
2701
2702
2703
2704
2705
2706
2707
2708
2709
2710
2711
2712
2713
2714

2715
2716
2717
2718
2719
2720
2721
2722
2723
2724
        if(chosenProtocol &&
           !CFStringCompare(chosenProtocol, CFSTR(ALPN_HTTP_1_1), 0)) {
          conn->negnpn = CURL_HTTP_VERSION_1_1;
        }
        else
          infof(data, "ALPN, server did not agree to a protocol\n");

        Curl_multiuse_state(conn, conn->negnpn == CURL_HTTP_VERSION_2 ?
                            BUNDLE_MULTIPLEX : BUNDLE_NO_MULTIUSE);

        /* chosenProtocol is a reference to the string within alpnArr
           and doesn't need to be freed separately */
        if(alpnArr)
          CFRelease(alpnArr);
      }
    }
#endif

    return CURLE_OK;
  }
}

#ifndef CURL_DISABLE_VERBOSE_STRINGS
/* This should be called during step3 of the connection at the earliest */
static void
show_verbose_server_cert(struct connectdata *conn,

                         int sockindex)
{
  struct Curl_easy *data = conn->data;
  struct ssl_connect_data *connssl = &conn->ssl[sockindex];
  struct ssl_backend_data *backend = connssl->backend;
  CFArrayRef server_certs = NULL;
  SecCertificateRef server_cert;
  OSStatus err;
  CFIndex i, count;
  SecTrustRef trust = NULL;







|

















|
>


<







2689
2690
2691
2692
2693
2694
2695
2696
2697
2698
2699
2700
2701
2702
2703
2704
2705
2706
2707
2708
2709
2710
2711
2712
2713
2714
2715
2716
2717

2718
2719
2720
2721
2722
2723
2724
        if(chosenProtocol &&
           !CFStringCompare(chosenProtocol, CFSTR(ALPN_HTTP_1_1), 0)) {
          conn->negnpn = CURL_HTTP_VERSION_1_1;
        }
        else
          infof(data, "ALPN, server did not agree to a protocol\n");

        Curl_multiuse_state(data, conn->negnpn == CURL_HTTP_VERSION_2 ?
                            BUNDLE_MULTIPLEX : BUNDLE_NO_MULTIUSE);

        /* chosenProtocol is a reference to the string within alpnArr
           and doesn't need to be freed separately */
        if(alpnArr)
          CFRelease(alpnArr);
      }
    }
#endif

    return CURLE_OK;
  }
}

#ifndef CURL_DISABLE_VERBOSE_STRINGS
/* This should be called during step3 of the connection at the earliest */
static void
show_verbose_server_cert(struct Curl_easy *data,
                         struct connectdata *conn,
                         int sockindex)
{

  struct ssl_connect_data *connssl = &conn->ssl[sockindex];
  struct ssl_backend_data *backend = connssl->backend;
  CFArrayRef server_certs = NULL;
  SecCertificateRef server_cert;
  OSStatus err;
  CFIndex i, count;
  SecTrustRef trust = NULL;
2813
2814
2815
2816
2817
2818
2819
2820
2821
2822
2823
2824
2825
2826
2827
2828
2829
2830
2831
2832
2833
2834
2835
2836
2837
2838
2839
2840
2841
2842

2843
2844
2845
2846
2847
2848
2849
2850
2851
2852
2853
2854
2855
2856
2857
2858
2859
2860
2861
2862
2863
2864
2865
2866
2867
2868
2869
2870
2871
2872
2873
2874
2875
2876
    CFRelease(server_certs);
  }
#endif /* CURL_BUILD_MAC_10_7 || CURL_BUILD_IOS */
}
#endif /* !CURL_DISABLE_VERBOSE_STRINGS */

static CURLcode
sectransp_connect_step3(struct connectdata *conn,
                        int sockindex)
{
  struct Curl_easy *data = conn->data;
  struct ssl_connect_data *connssl = &conn->ssl[sockindex];

  /* There is no step 3!
   * Well, okay, if verbose mode is on, let's print the details of the
   * server certificates. */
#ifndef CURL_DISABLE_VERBOSE_STRINGS
  if(data->set.verbose)
    show_verbose_server_cert(conn, sockindex);
#endif

  connssl->connecting_state = ssl_connect_done;
  return CURLE_OK;
}

static Curl_recv sectransp_recv;
static Curl_send sectransp_send;

static CURLcode
sectransp_connect_common(struct connectdata *conn,

                         int sockindex,
                         bool nonblocking,
                         bool *done)
{
  CURLcode result;
  struct Curl_easy *data = conn->data;
  struct ssl_connect_data *connssl = &conn->ssl[sockindex];
  curl_socket_t sockfd = conn->sock[sockindex];
  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 */
    const timediff_t 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 = sectransp_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) {







|


<







|










|
>





<




















|







2813
2814
2815
2816
2817
2818
2819
2820
2821
2822

2823
2824
2825
2826
2827
2828
2829
2830
2831
2832
2833
2834
2835
2836
2837
2838
2839
2840
2841
2842
2843
2844
2845
2846
2847

2848
2849
2850
2851
2852
2853
2854
2855
2856
2857
2858
2859
2860
2861
2862
2863
2864
2865
2866
2867
2868
2869
2870
2871
2872
2873
2874
2875
    CFRelease(server_certs);
  }
#endif /* CURL_BUILD_MAC_10_7 || CURL_BUILD_IOS */
}
#endif /* !CURL_DISABLE_VERBOSE_STRINGS */

static CURLcode
sectransp_connect_step3(struct Curl_easy *data, struct connectdata *conn,
                        int sockindex)
{

  struct ssl_connect_data *connssl = &conn->ssl[sockindex];

  /* There is no step 3!
   * Well, okay, if verbose mode is on, let's print the details of the
   * server certificates. */
#ifndef CURL_DISABLE_VERBOSE_STRINGS
  if(data->set.verbose)
    show_verbose_server_cert(data, conn, sockindex);
#endif

  connssl->connecting_state = ssl_connect_done;
  return CURLE_OK;
}

static Curl_recv sectransp_recv;
static Curl_send sectransp_send;

static CURLcode
sectransp_connect_common(struct Curl_easy *data,
                         struct connectdata *conn,
                         int sockindex,
                         bool nonblocking,
                         bool *done)
{
  CURLcode result;

  struct ssl_connect_data *connssl = &conn->ssl[sockindex];
  curl_socket_t sockfd = conn->sock[sockindex];
  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 */
    const timediff_t 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 = sectransp_connect_step1(data, 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) {
2916
2917
2918
2919
2920
2921
2922
2923
2924
2925
2926
2927
2928
2929
2930
2931
2932
2933
2934
2935
2936
2937
2938
2939
2940
2941
2942
2943
2944
2945
2946
2947
2948
2949
2950
2951
2952
2953

2954
2955
2956
2957
2958
2959

2960
2961
2962
2963
2964
2965
2966
2967
2968
2969
2970
2971
2972
2973
2974

2975
2976
2977
2978


2979
2980
2981
2982
2983
2984
2985
2986
2987
2988
2989
2990
2991
2992
2993
2994
2995
2996

2997
2998
2999
3000
3001
3002
3003
3004
3005
3006
3007
3008
3009
3010
3011
3012
3013
3014
3015
3016
3017
3018
3019
3020
3021
3022

    /* 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 = sectransp_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 = sectransp_connect_step3(conn, sockindex);
    if(result)
      return result;
  }

  if(ssl_connect_done == connssl->connecting_state) {
    connssl->state = ssl_connection_complete;
    conn->recv[sockindex] = sectransp_recv;
    conn->send[sockindex] = sectransp_send;
    *done = TRUE;
  }
  else
    *done = FALSE;

  /* Reset our connect state machine */
  connssl->connecting_state = ssl_connect_1;

  return CURLE_OK;
}


static CURLcode Curl_sectransp_connect_nonblocking(struct connectdata *conn,
                                                   int sockindex, bool *done)
{
  return sectransp_connect_common(conn, sockindex, TRUE, done);
}


static CURLcode Curl_sectransp_connect(struct connectdata *conn, int sockindex)
{
  CURLcode result;
  bool done = FALSE;

  result = sectransp_connect_common(conn, sockindex, FALSE, &done);

  if(result)
    return result;

  DEBUGASSERT(done);

  return CURLE_OK;
}


static void Curl_sectransp_close(struct connectdata *conn, int sockindex)
{
  struct ssl_connect_data *connssl = &conn->ssl[sockindex];
  struct ssl_backend_data *backend = connssl->backend;



  if(backend->ssl_ctx) {
    (void)SSLClose(backend->ssl_ctx);
#if CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS
    if(SSLCreateContext != NULL)
      CFRelease(backend->ssl_ctx);
#if CURL_SUPPORT_MAC_10_8
    else
      (void)SSLDisposeContext(backend->ssl_ctx);
#endif  /* CURL_SUPPORT_MAC_10_8 */
#else
    (void)SSLDisposeContext(backend->ssl_ctx);
#endif /* CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS */
    backend->ssl_ctx = NULL;
  }
  backend->ssl_sockfd = 0;
}


static int Curl_sectransp_shutdown(struct connectdata *conn, int sockindex)
{
  struct ssl_connect_data *connssl = &conn->ssl[sockindex];
  struct ssl_backend_data *backend = connssl->backend;
  struct Curl_easy *data = conn->data;
  ssize_t nread;
  int what;
  int rc;
  char buf[120];

  if(!backend->ssl_ctx)
    return 0;

#ifndef CURL_DISABLE_FTP
  if(data->set.ftp_ccc != CURLFTPSSL_CCC_ACTIVE)
    return 0;
#endif

  Curl_sectransp_close(conn, sockindex);

  rc = 0;

  what = SOCKET_READABLE(conn->sock[sockindex], SSL_SHUTDOWN_TIMEOUT);

  for(;;) {
    if(what < 0) {







|










|



















>
|
|

|


>
|




|









>
|



>
>


















>
|



<













|







2915
2916
2917
2918
2919
2920
2921
2922
2923
2924
2925
2926
2927
2928
2929
2930
2931
2932
2933
2934
2935
2936
2937
2938
2939
2940
2941
2942
2943
2944
2945
2946
2947
2948
2949
2950
2951
2952
2953
2954
2955
2956
2957
2958
2959
2960
2961
2962
2963
2964
2965
2966
2967
2968
2969
2970
2971
2972
2973
2974
2975
2976
2977
2978
2979
2980
2981
2982
2983
2984
2985
2986
2987
2988
2989
2990
2991
2992
2993
2994
2995
2996
2997
2998
2999
3000
3001
3002
3003
3004
3005

3006
3007
3008
3009
3010
3011
3012
3013
3014
3015
3016
3017
3018
3019
3020
3021
3022
3023
3024
3025
3026

    /* 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 = sectransp_connect_step2(data, 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 = sectransp_connect_step3(data, conn, sockindex);
    if(result)
      return result;
  }

  if(ssl_connect_done == connssl->connecting_state) {
    connssl->state = ssl_connection_complete;
    conn->recv[sockindex] = sectransp_recv;
    conn->send[sockindex] = sectransp_send;
    *done = TRUE;
  }
  else
    *done = FALSE;

  /* Reset our connect state machine */
  connssl->connecting_state = ssl_connect_1;

  return CURLE_OK;
}

static CURLcode sectransp_connect_nonblocking(struct Curl_easy *data,
                                              struct connectdata *conn,
                                              int sockindex, bool *done)
{
  return sectransp_connect_common(data, conn, sockindex, TRUE, done);
}

static CURLcode sectransp_connect(struct Curl_easy *data,
                                  struct connectdata *conn, int sockindex)
{
  CURLcode result;
  bool done = FALSE;

  result = sectransp_connect_common(data, conn, sockindex, FALSE, &done);

  if(result)
    return result;

  DEBUGASSERT(done);

  return CURLE_OK;
}

static void sectransp_close(struct Curl_easy *data, struct connectdata *conn,
                            int sockindex)
{
  struct ssl_connect_data *connssl = &conn->ssl[sockindex];
  struct ssl_backend_data *backend = connssl->backend;

  (void) data;

  if(backend->ssl_ctx) {
    (void)SSLClose(backend->ssl_ctx);
#if CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS
    if(SSLCreateContext != NULL)
      CFRelease(backend->ssl_ctx);
#if CURL_SUPPORT_MAC_10_8
    else
      (void)SSLDisposeContext(backend->ssl_ctx);
#endif  /* CURL_SUPPORT_MAC_10_8 */
#else
    (void)SSLDisposeContext(backend->ssl_ctx);
#endif /* CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS */
    backend->ssl_ctx = NULL;
  }
  backend->ssl_sockfd = 0;
}

static int sectransp_shutdown(struct Curl_easy *data,
                              struct connectdata *conn, int sockindex)
{
  struct ssl_connect_data *connssl = &conn->ssl[sockindex];
  struct ssl_backend_data *backend = connssl->backend;

  ssize_t nread;
  int what;
  int rc;
  char buf[120];

  if(!backend->ssl_ctx)
    return 0;

#ifndef CURL_DISABLE_FTP
  if(data->set.ftp_ccc != CURLFTPSSL_CCC_ACTIVE)
    return 0;
#endif

  sectransp_close(data, conn, sockindex);

  rc = 0;

  what = SOCKET_READABLE(conn->sock[sockindex], SSL_SHUTDOWN_TIMEOUT);

  for(;;) {
    if(what < 0) {
3046
3047
3048
3049
3050
3051
3052
3053
3054
3055
3056
3057
3058
3059
3060
3061
3062
3063
3064
3065
3066
3067
3068
3069
3070
3071
3072
3073
3074
3075
3076
3077
3078
3079
3080
3081
3082
3083
3084
3085
3086
3087
3088
3089
3090
3091
3092
3093
3094
3095
3096
3097
3098
3099
3100
3101
3102
3103
3104
3105
3106
3107
3108
3109
3110
3111
3112
3113
3114
3115
3116
3117
3118
3119
3120
3121
3122
3123
3124
3125
3126
3127
3128
3129
3130
3131
3132
3133
3134
3135
3136
3137
3138
3139
3140
3141
3142
3143
3144
3145
3146
3147
3148
3149
3150
3151
3152
3153
3154
3155
3156
3157
3158
3159
3160
3161
3162
3163
3164
3165
3166
3167
3168
3169
3170
3171
3172
3173

    what = SOCKET_READABLE(conn->sock[sockindex], 0);
  }

  return rc;
}

static void Curl_sectransp_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 sectransp_connect_step1... */
  Curl_safefree(ptr);
}

static size_t Curl_sectransp_version(char *buffer, size_t size)
{
  return msnprintf(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
 */
static int Curl_sectransp_check_cxn(struct connectdata *conn)
{
  struct ssl_connect_data *connssl = &conn->ssl[FIRSTSOCKET];
  struct ssl_backend_data *backend = connssl->backend;
  OSStatus err;
  SSLSessionState state;

  if(backend->ssl_ctx) {
    err = SSLGetSessionState(backend->ssl_ctx, &state);
    if(err == noErr)
      return state == kSSLConnected || state == kSSLHandshake;
    return -1;
  }
  return 0;
}

static bool Curl_sectransp_data_pending(const struct connectdata *conn,
                                        int connindex)
{
  const struct ssl_connect_data *connssl = &conn->ssl[connindex];
  struct ssl_backend_data *backend = connssl->backend;
  OSStatus err;
  size_t buffer;

  if(backend->ssl_ctx) {  /* SSL is in use */
    err = SSLGetBufferedReadSize(backend->ssl_ctx, &buffer);
    if(err == noErr)
      return buffer > 0UL;
    return false;
  }
  else
    return false;
}

static CURLcode Curl_sectransp_random(struct Curl_easy *data UNUSED_PARAM,
                                      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;

  (void)data;

  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 CURLE_OK;
}

static CURLcode Curl_sectransp_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);
  return CURLE_OK;
}

static CURLcode Curl_sectransp_sha256sum(const unsigned char *tmp, /* input */
                                     size_t tmplen,
                                     unsigned char *sha256sum, /* output */
                                     size_t sha256len)
{
  assert(sha256len >= CURL_SHA256_DIGEST_LENGTH);
  (void)CC_SHA256(tmp, (CC_LONG)tmplen, sha256sum);
  return CURLE_OK;
}

static bool Curl_sectransp_false_start(void)
{
#if CURL_BUILD_MAC_10_9 || CURL_BUILD_IOS_7
  if(SSLSetSessionOption != NULL)
    return TRUE;
#endif
  return FALSE;
}

static ssize_t sectransp_send(struct connectdata *conn,
                              int sockindex,
                              const void *mem,
                              size_t len,
                              CURLcode *curlcode)
{
  /*struct Curl_easy *data = conn->data;*/
  struct ssl_connect_data *connssl = &conn->ssl[sockindex];
  struct ssl_backend_data *backend = connssl->backend;
  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







|










|












|















|
|
















|
|


















<
<
<
<
<
<
<
<
<
<
|
|
|
|






|








|





|







3050
3051
3052
3053
3054
3055
3056
3057
3058
3059
3060
3061
3062
3063
3064
3065
3066
3067
3068
3069
3070
3071
3072
3073
3074
3075
3076
3077
3078
3079
3080
3081
3082
3083
3084
3085
3086
3087
3088
3089
3090
3091
3092
3093
3094
3095
3096
3097
3098
3099
3100
3101
3102
3103
3104
3105
3106
3107
3108
3109
3110
3111
3112
3113
3114
3115
3116
3117
3118
3119
3120
3121
3122
3123
3124
3125
3126
3127
3128
3129
3130
3131
3132
3133
3134










3135
3136
3137
3138
3139
3140
3141
3142
3143
3144
3145
3146
3147
3148
3149
3150
3151
3152
3153
3154
3155
3156
3157
3158
3159
3160
3161
3162
3163
3164
3165
3166
3167

    what = SOCKET_READABLE(conn->sock[sockindex], 0);
  }

  return rc;
}

static void sectransp_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 sectransp_connect_step1... */
  Curl_safefree(ptr);
}

static size_t sectransp_version(char *buffer, size_t size)
{
  return msnprintf(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
 */
static int sectransp_check_cxn(struct connectdata *conn)
{
  struct ssl_connect_data *connssl = &conn->ssl[FIRSTSOCKET];
  struct ssl_backend_data *backend = connssl->backend;
  OSStatus err;
  SSLSessionState state;

  if(backend->ssl_ctx) {
    err = SSLGetSessionState(backend->ssl_ctx, &state);
    if(err == noErr)
      return state == kSSLConnected || state == kSSLHandshake;
    return -1;
  }
  return 0;
}

static bool sectransp_data_pending(const struct connectdata *conn,
                                   int connindex)
{
  const struct ssl_connect_data *connssl = &conn->ssl[connindex];
  struct ssl_backend_data *backend = connssl->backend;
  OSStatus err;
  size_t buffer;

  if(backend->ssl_ctx) {  /* SSL is in use */
    err = SSLGetBufferedReadSize(backend->ssl_ctx, &buffer);
    if(err == noErr)
      return buffer > 0UL;
    return false;
  }
  else
    return false;
}

static CURLcode sectransp_random(struct Curl_easy *data UNUSED_PARAM,
                                 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;

  (void)data;

  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 CURLE_OK;
}











static CURLcode sectransp_sha256sum(const unsigned char *tmp, /* input */
                                    size_t tmplen,
                                    unsigned char *sha256sum, /* output */
                                    size_t sha256len)
{
  assert(sha256len >= CURL_SHA256_DIGEST_LENGTH);
  (void)CC_SHA256(tmp, (CC_LONG)tmplen, sha256sum);
  return CURLE_OK;
}

static bool sectransp_false_start(void)
{
#if CURL_BUILD_MAC_10_9 || CURL_BUILD_IOS_7
  if(SSLSetSessionOption != NULL)
    return TRUE;
#endif
  return FALSE;
}

static ssize_t sectransp_send(struct Curl_easy *data,
                              int sockindex,
                              const void *mem,
                              size_t len,
                              CURLcode *curlcode)
{
  struct connectdata *conn = data->conn;
  struct ssl_connect_data *connssl = &conn->ssl[sockindex];
  struct ssl_backend_data *backend = connssl->backend;
  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
3194
3195
3196
3197
3198
3199
3200
3201
3202
3203
3204
3205
3206
3207
3208
3209
3210
3211
3212
3213
3214
3215
3216
3217
3218
3219
3220
3221
3222
3223
3224
3225
3226
3227
3228
3229
3230
3231
3232
3233
3234
3235
3236
3237
3238
3239
3240
        processed = backend->ssl_write_buffered_length;
        backend->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(backend->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 */
          backend->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 sectransp_recv(struct connectdata *conn,
                              int num,
                              char *buf,
                              size_t buffersize,
                              CURLcode *curlcode)
{
  /*struct Curl_easy *data = conn->data;*/
  struct ssl_connect_data *connssl = &conn->ssl[num];
  struct ssl_backend_data *backend = connssl->backend;
  size_t processed = 0UL;
  OSStatus err;

  again:
  err = SSLRead(backend->ssl_ctx, buf, buffersize, &processed);







|
















|








|





|







3188
3189
3190
3191
3192
3193
3194
3195
3196
3197
3198
3199
3200
3201
3202
3203
3204
3205
3206
3207
3208
3209
3210
3211
3212
3213
3214
3215
3216
3217
3218
3219
3220
3221
3222
3223
3224
3225
3226
3227
3228
3229
3230
3231
3232
3233
3234
        processed = backend->ssl_write_buffered_length;
        backend->ssl_write_buffered_length = 0UL;
        break;
      case errSSLWouldBlock: /* argh, try again */
        *curlcode = CURLE_AGAIN;
        return -1L;
      default:
        failf(data, "SSLWrite() returned error %d", err);
        *curlcode = CURLE_SEND_ERROR;
        return -1L;
    }
  }
  else {
    /* We've got new data to write: */
    err = SSLWrite(backend->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 */
          backend->ssl_write_buffered_length = len;
          *curlcode = CURLE_AGAIN;
          return -1L;
        default:
          failf(data, "SSLWrite() returned error %d", err);
          *curlcode = CURLE_SEND_ERROR;
          return -1L;
      }
    }
  }
  return (ssize_t)processed;
}

static ssize_t sectransp_recv(struct Curl_easy *data,
                              int num,
                              char *buf,
                              size_t buffersize,
                              CURLcode *curlcode)
{
  struct connectdata *conn = data->conn;
  struct ssl_connect_data *connssl = &conn->ssl[num];
  struct ssl_backend_data *backend = connssl->backend;
  size_t processed = 0UL;
  OSStatus err;

  again:
  err = SSLRead(backend->ssl_ctx, buf, buffersize, &processed);
3258
3259
3260
3261
3262
3263
3264
3265
3266
3267
3268
3269
3270
3271
3272
3273
3274
3275
3276
3277
3278
3279
3280
3281
3282
3283
3284
3285
3286
3287
3288
3289
3290
3291
3292
3293
3294
3295
3296
3297
3298
3299
3300
3301
3302
3303
3304
3305
3306
3307
3308
3309
3310
3311
3312
3313
3314
3315
3316
3317
3318
3319
3320
3321
3322
3323
3324
3325
3326
        return -1L;
        break;

        /* The below is errSSLPeerAuthCompleted; it's not defined in
           Leopard's headers */
      case -9841:
        if(SSL_CONN_CONFIG(CAfile) && SSL_CONN_CONFIG(verifypeer)) {
          CURLcode result = verify_cert(SSL_CONN_CONFIG(CAfile), conn->data,
                                        backend->ssl_ctx);
          if(result)
            return result;
        }
        goto again;
      default:
        failf(conn->data, "SSLRead() return error %d", err);
        *curlcode = CURLE_RECV_ERROR;
        return -1L;
        break;
    }
  }
  return (ssize_t)processed;
}

static void *Curl_sectransp_get_internals(struct ssl_connect_data *connssl,
                                          CURLINFO info UNUSED_PARAM)
{
  struct ssl_backend_data *backend = connssl->backend;
  (void)info;
  return backend->ssl_ctx;
}

const struct Curl_ssl Curl_ssl_sectransp = {
  { CURLSSLBACKEND_SECURETRANSPORT, "secure-transport" }, /* info */

#ifdef SECTRANSP_PINNEDPUBKEY
  SSLSUPP_PINNEDPUBKEY,
#else
  0,
#endif /* SECTRANSP_PINNEDPUBKEY */

  sizeof(struct ssl_backend_data),

  Curl_none_init,                     /* init */
  Curl_none_cleanup,                  /* cleanup */
  Curl_sectransp_version,             /* version */
  Curl_sectransp_check_cxn,           /* check_cxn */
  Curl_sectransp_shutdown,            /* shutdown */
  Curl_sectransp_data_pending,        /* data_pending */
  Curl_sectransp_random,              /* random */
  Curl_none_cert_status_request,      /* cert_status_request */
  Curl_sectransp_connect,             /* connect */
  Curl_sectransp_connect_nonblocking, /* connect_nonblocking */
  Curl_sectransp_get_internals,       /* get_internals */
  Curl_sectransp_close,               /* close_one */
  Curl_none_close_all,                /* close_all */
  Curl_sectransp_session_free,        /* session_free */
  Curl_none_set_engine,               /* set_engine */
  Curl_none_set_engine_default,       /* set_engine_default */
  Curl_none_engines_list,             /* engines_list */
  Curl_sectransp_false_start,         /* false_start */
  Curl_sectransp_md5sum,              /* md5sum */
  Curl_sectransp_sha256sum            /* sha256sum */
};

#ifdef __clang__
#pragma clang diagnostic pop
#endif

#endif /* USE_SECTRANSP */







|






|








|
|



















|
|
|
|
|

|
|
|
|

|



|
<
|







3252
3253
3254
3255
3256
3257
3258
3259
3260
3261
3262
3263
3264
3265
3266
3267
3268
3269
3270
3271
3272
3273
3274
3275
3276
3277
3278
3279
3280
3281
3282
3283
3284
3285
3286
3287
3288
3289
3290
3291
3292
3293
3294
3295
3296
3297
3298
3299
3300
3301
3302
3303
3304
3305
3306
3307
3308
3309
3310
3311

3312
3313
3314
3315
3316
3317
3318
3319
        return -1L;
        break;

        /* The below is errSSLPeerAuthCompleted; it's not defined in
           Leopard's headers */
      case -9841:
        if(SSL_CONN_CONFIG(CAfile) && SSL_CONN_CONFIG(verifypeer)) {
          CURLcode result = verify_cert(SSL_CONN_CONFIG(CAfile), data,
                                        backend->ssl_ctx);
          if(result)
            return result;
        }
        goto again;
      default:
        failf(data, "SSLRead() return error %d", err);
        *curlcode = CURLE_RECV_ERROR;
        return -1L;
        break;
    }
  }
  return (ssize_t)processed;
}

static void *sectransp_get_internals(struct ssl_connect_data *connssl,
                                     CURLINFO info UNUSED_PARAM)
{
  struct ssl_backend_data *backend = connssl->backend;
  (void)info;
  return backend->ssl_ctx;
}

const struct Curl_ssl Curl_ssl_sectransp = {
  { CURLSSLBACKEND_SECURETRANSPORT, "secure-transport" }, /* info */

#ifdef SECTRANSP_PINNEDPUBKEY
  SSLSUPP_PINNEDPUBKEY,
#else
  0,
#endif /* SECTRANSP_PINNEDPUBKEY */

  sizeof(struct ssl_backend_data),

  Curl_none_init,                     /* init */
  Curl_none_cleanup,                  /* cleanup */
  sectransp_version,                  /* version */
  sectransp_check_cxn,                /* check_cxn */
  sectransp_shutdown,                 /* shutdown */
  sectransp_data_pending,             /* data_pending */
  sectransp_random,                   /* random */
  Curl_none_cert_status_request,      /* cert_status_request */
  sectransp_connect,                  /* connect */
  sectransp_connect_nonblocking,      /* connect_nonblocking */
  sectransp_get_internals,            /* get_internals */
  sectransp_close,                    /* close_one */
  Curl_none_close_all,                /* close_all */
  sectransp_session_free,             /* session_free */
  Curl_none_set_engine,               /* set_engine */
  Curl_none_set_engine_default,       /* set_engine_default */
  Curl_none_engines_list,             /* engines_list */
  sectransp_false_start,              /* false_start */

  sectransp_sha256sum                 /* sha256sum */
};

#ifdef __clang__
#pragma clang diagnostic pop
#endif

#endif /* USE_SECTRANSP */
Changes to jni/curl/lib/vtls/vtls.c.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2020, 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 https://curl.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







|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2021, 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 https://curl.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
71
72
73
74
75
76
77

78
79
80
81
82
83
84

85
86

87
88

89
90
91
92
93
94
95

/* 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)))

#define CLONE_STRING(var)                    \

  if(source->var) {                          \
    dest->var = strdup(source->var);         \
    if(!dest->var)                           \
      return FALSE;                          \
  }                                          \
  else                                       \
    dest->var = NULL;


#define CLONE_BLOB(var)                         \

  if(blobdup(&dest->var, source->var))         \
    return FALSE;


static CURLcode blobdup(struct curl_blob **dest,
                        struct curl_blob *src)
{
  DEBUGASSERT(dest);
  DEBUGASSERT(!*dest);
  if(src) {







>
|
|
|
|
|
|
|
>

|
>
|
|
>







71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99

/* 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)))

#define CLONE_STRING(var)                    \
  do {                                       \
    if(source->var) {                        \
      dest->var = strdup(source->var);       \
      if(!dest->var)                         \
        return FALSE;                        \
    }                                        \
    else                                     \
      dest->var = NULL;                      \
  } while(0)

#define CLONE_BLOB(var)                        \
  do {                                         \
    if(blobdup(&dest->var, source->var))       \
      return FALSE;                            \
  } while(0)

static CURLcode blobdup(struct curl_blob **dest,
                        struct curl_blob *src)
{
  DEBUGASSERT(dest);
  DEBUGASSERT(!*dest);
  if(src) {
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
  Curl_safefree(sslc->cipher_list13);
  Curl_safefree(sslc->pinned_key);
  Curl_safefree(sslc->cert_blob);
  Curl_safefree(sslc->curves);
}

#ifdef USE_SSL
static int multissl_init(const struct Curl_ssl *backend);
#endif

int Curl_ssl_backend(void)
{
#ifdef USE_SSL
  multissl_init(NULL);
  return Curl_ssl->info.id;
#else
  return (int)CURLSSLBACKEND_NONE;
#endif
}

#ifdef USE_SSL







|





|







185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
  Curl_safefree(sslc->cipher_list13);
  Curl_safefree(sslc->pinned_key);
  Curl_safefree(sslc->cert_blob);
  Curl_safefree(sslc->curves);
}

#ifdef USE_SSL
static int multissl_setup(const struct Curl_ssl *backend);
#endif

int Curl_ssl_backend(void)
{
#ifdef USE_SSL
  multissl_setup(NULL);
  return Curl_ssl->info.id;
#else
  return (int)CURLSSLBACKEND_NONE;
#endif
}

#ifdef USE_SSL
283
284
285
286
287
288
289
290






























291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363

364
365
366
367
368
369
370
371
372
373
374
375
376
    conn->ssl[sockindex].backend = pbdata;
  }
  return CURLE_OK;
}
#endif

CURLcode
Curl_ssl_connect(struct connectdata *conn, int sockindex)






























{
  CURLcode result;

#ifndef CURL_DISABLE_PROXY
  if(conn->bits.proxy_ssl_connected[sockindex]) {
    result = ssl_connect_init_proxy(conn, sockindex);
    if(result)
      return result;
  }
#endif

  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 = Curl_ssl->connect_blocking(conn, sockindex);

  if(!result)
    Curl_pgrsTime(conn->data, TIMER_APPCONNECT); /* SSL is connected */

  return result;
}

CURLcode
Curl_ssl_connect_nonblocking(struct connectdata *conn, int sockindex,
                             bool *done)
{
  CURLcode result;
#ifndef CURL_DISABLE_PROXY
  if(conn->bits.proxy_ssl_connected[sockindex]) {
    result = ssl_connect_init_proxy(conn, sockindex);
    if(result)
      return result;
  }
#endif
  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;
  result = Curl_ssl->connect_nonblocking(conn, sockindex, done);
  if(!result && *done)
    Curl_pgrsTime(conn->data, TIMER_APPCONNECT); /* SSL is connected */
  return result;
}

/*
 * Lock shared SSL session data
 */
void Curl_ssl_sessionid_lock(struct connectdata *conn)
{
  if(SSLSESSION_SHARED(conn->data))
    Curl_share_lock(conn->data,
                    CURL_LOCK_DATA_SSL_SESSION, CURL_LOCK_ACCESS_SINGLE);
}

/*
 * Unlock shared SSL session data
 */
void Curl_ssl_sessionid_unlock(struct connectdata *conn)
{
  if(SSLSESSION_SHARED(conn->data))
    Curl_share_unlock(conn->data, CURL_LOCK_DATA_SSL_SESSION);
}

/*
 * 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.
 */
bool Curl_ssl_getsessionid(struct connectdata *conn,

                           void **ssl_sessionid,
                           size_t *idsize, /* set 0 if unknown */
                           int sockindex)
{
  struct Curl_ssl_session *check;
  struct Curl_easy *data = conn->data;
  size_t i;
  long *general_age;
  bool no_match = TRUE;

#ifndef CURL_DISABLE_PROXY
  const bool isProxy = CONNECT_PROXY_SSL();
  struct ssl_primary_config * const ssl_config = isProxy ?







|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>










<
|


<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<


|

|






|

|
<
|





|

|
|






|
>





<







287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334

335
336
337



























338
339
340
341
342
343
344
345
346
347
348
349
350
351

352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374

375
376
377
378
379
380
381
    conn->ssl[sockindex].backend = pbdata;
  }
  return CURLE_OK;
}
#endif

CURLcode
Curl_ssl_connect(struct Curl_easy *data, struct connectdata *conn,
                 int sockindex)
{
  CURLcode result;

#ifndef CURL_DISABLE_PROXY
  if(conn->bits.proxy_ssl_connected[sockindex]) {
    result = ssl_connect_init_proxy(conn, sockindex);
    if(result)
      return result;
  }
#endif

  if(!ssl_prefs_check(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 = Curl_ssl->connect_blocking(data, conn, sockindex);

  if(!result)
    Curl_pgrsTime(data, TIMER_APPCONNECT); /* SSL is connected */

  return result;
}

CURLcode
Curl_ssl_connect_nonblocking(struct Curl_easy *data, struct connectdata *conn,
                             int sockindex, bool *done)
{
  CURLcode result;

#ifndef CURL_DISABLE_PROXY
  if(conn->bits.proxy_ssl_connected[sockindex]) {
    result = ssl_connect_init_proxy(conn, sockindex);
    if(result)
      return result;
  }
#endif

  if(!ssl_prefs_check(data))
    return CURLE_SSL_CONNECT_ERROR;




























  /* mark this is being ssl requested from here on. */
  conn->ssl[sockindex].use = TRUE;
  result = Curl_ssl->connect_nonblocking(data, conn, sockindex, done);
  if(!result && *done)
    Curl_pgrsTime(data, TIMER_APPCONNECT); /* SSL is connected */
  return result;
}

/*
 * Lock shared SSL session data
 */
void Curl_ssl_sessionid_lock(struct Curl_easy *data)
{
  if(SSLSESSION_SHARED(data))

    Curl_share_lock(data, CURL_LOCK_DATA_SSL_SESSION, CURL_LOCK_ACCESS_SINGLE);
}

/*
 * Unlock shared SSL session data
 */
void Curl_ssl_sessionid_unlock(struct Curl_easy *data)
{
  if(SSLSESSION_SHARED(data))
    Curl_share_unlock(data, CURL_LOCK_DATA_SSL_SESSION);
}

/*
 * 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.
 */
bool Curl_ssl_getsessionid(struct Curl_easy *data,
                           struct connectdata *conn,
                           void **ssl_sessionid,
                           size_t *idsize, /* set 0 if unknown */
                           int sockindex)
{
  struct Curl_ssl_session *check;

  size_t i;
  long *general_age;
  bool no_match = TRUE;

#ifndef CURL_DISABLE_PROXY
  const bool isProxy = CONNECT_PROXY_SSL();
  struct ssl_primary_config * const ssl_config = isProxy ?
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477

478
479
480
481
482
483
484
485
486
487
488
489
490
    Curl_safefree(session->conn_to_host);
  }
}

/*
 * Delete the given session ID from the cache.
 */
void Curl_ssl_delsessionid(struct connectdata *conn, void *ssl_sessionid)
{
  size_t i;
  struct Curl_easy *data = conn->data;

  for(i = 0; i < data->set.general_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;
    }
  }
}

/*
 * 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.
 */
CURLcode Curl_ssl_addsessionid(struct connectdata *conn,

                               void *ssl_sessionid,
                               size_t idsize,
                               int sockindex)
{
  size_t i;
  struct Curl_easy *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;
  char *clone_conn_to_host;
  int conn_to_port;
  long *general_age;
#ifndef CURL_DISABLE_PROXY







|


<

















|
>





<







454
455
456
457
458
459
460
461
462
463

464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487

488
489
490
491
492
493
494
    Curl_safefree(session->conn_to_host);
  }
}

/*
 * Delete the given session ID from the cache.
 */
void Curl_ssl_delsessionid(struct Curl_easy *data, void *ssl_sessionid)
{
  size_t i;


  for(i = 0; i < data->set.general_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;
    }
  }
}

/*
 * 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.
 */
CURLcode Curl_ssl_addsessionid(struct Curl_easy *data,
                               struct connectdata *conn,
                               void *ssl_sessionid,
                               size_t idsize,
                               int sockindex)
{
  size_t i;

  struct Curl_ssl_session *store = &data->state.session[0];
  long oldest_age = data->state.session[0].age; /* zero if unused */
  char *clone_host;
  char *clone_conn_to_host;
  int conn_to_port;
  long *general_age;
#ifndef CURL_DISABLE_PROXY
616
617
618
619
620
621
622
623

624
625
626
627
628
629
630

631
632
633
634
635
636
637
638
639
  (void)conn;
  (void)socks;
  return GETSOCK_BLANK;
}
/* USE_OPENSSL || USE_GNUTLS || USE_SCHANNEL || USE_SECTRANSP || USE_NSS */
#endif

void Curl_ssl_close(struct connectdata *conn, int sockindex)

{
  DEBUGASSERT((sockindex <= 1) && (sockindex >= -1));
  Curl_ssl->close_one(conn, sockindex);
  conn->ssl[sockindex].state = ssl_connection_none;
}

CURLcode Curl_ssl_shutdown(struct connectdata *conn, int sockindex)

{
  if(Curl_ssl->shut_down(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;







|
>


|



|
>

|







620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
  (void)conn;
  (void)socks;
  return GETSOCK_BLANK;
}
/* USE_OPENSSL || USE_GNUTLS || USE_SCHANNEL || USE_SECTRANSP || USE_NSS */
#endif

void Curl_ssl_close(struct Curl_easy *data, struct connectdata *conn,
                    int sockindex)
{
  DEBUGASSERT((sockindex <= 1) && (sockindex >= -1));
  Curl_ssl->close_one(data, conn, sockindex);
  conn->ssl[sockindex].state = ssl_connection_none;
}

CURLcode Curl_ssl_shutdown(struct Curl_easy *data, struct connectdata *conn,
                           int sockindex)
{
  if(Curl_ssl->shut_down(data, 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;
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
  /* store the info in the SSL section */
  data->set.general_ssl.max_ssl_sessions = amount;
  data->state.session = session;
  data->state.sessionage = 1; /* this is brand new */
  return CURLE_OK;
}

static size_t Curl_multissl_version(char *buffer, size_t size);

size_t Curl_ssl_version(char *buffer, size_t size)
{
#ifdef CURL_WITH_MULTI_SSL
  return Curl_multissl_version(buffer, size);
#else
  return Curl_ssl->version(buffer, size);
#endif
}

/*
 * This function tries to determine connection status.







|




|







686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
  /* store the info in the SSL section */
  data->set.general_ssl.max_ssl_sessions = amount;
  data->state.session = session;
  data->state.sessionage = 1; /* this is brand new */
  return CURLE_OK;
}

static size_t multissl_version(char *buffer, size_t size);

size_t Curl_ssl_version(char *buffer, size_t size)
{
#ifdef CURL_WITH_MULTI_SSL
  return multissl_version(buffer, size);
#else
  return Curl_ssl->version(buffer, size);
#endif
}

/*
 * This function tries to determine connection status.
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
  Curl_safefree(buf);
  Curl_safefree(pem_ptr);
  fclose(fp);

  return result;
}

#ifndef CURL_DISABLE_CRYPTO_AUTH
CURLcode Curl_ssl_md5sum(unsigned char *tmp, /* input */
                         size_t tmplen,
                         unsigned char *md5sum, /* output */
                         size_t md5len)
{
  return Curl_ssl->md5sum(tmp, tmplen, md5sum, md5len);
}
#endif

/*
 * Check whether the SSL backend supports the status_request extension.
 */
bool Curl_ssl_cert_status_request(void)
{
  return Curl_ssl->cert_status_request();
}







<
<
<
<
<
<
<
<
<
<







1032
1033
1034
1035
1036
1037
1038










1039
1040
1041
1042
1043
1044
1045
  Curl_safefree(buf);
  Curl_safefree(pem_ptr);
  fclose(fp);

  return result;
}











/*
 * Check whether the SSL backend supports the status_request extension.
 */
bool Curl_ssl_cert_status_request(void)
{
  return Curl_ssl->cert_status_request();
}
1072
1073
1074
1075
1076
1077
1078

1079
1080
1081

1082
1083
1084
1085
1086
1087
1088
{
  return 1;
}

void Curl_none_cleanup(void)
{ }


int Curl_none_shutdown(struct connectdata *conn UNUSED_PARAM,
                       int sockindex UNUSED_PARAM)
{

  (void)conn;
  (void)sockindex;
  return 0;
}

int Curl_none_check_cxn(struct connectdata *conn UNUSED_PARAM)
{







>
|


>







1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
{
  return 1;
}

void Curl_none_cleanup(void)
{ }

int Curl_none_shutdown(struct Curl_easy *data UNUSED_PARAM,
                       struct connectdata *conn UNUSED_PARAM,
                       int sockindex UNUSED_PARAM)
{
  (void)data;
  (void)conn;
  (void)sockindex;
  return 0;
}

int Curl_none_check_cxn(struct connectdata *conn UNUSED_PARAM)
{
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186

1187
1188
1189
1190
1191
1192
1193
1194

1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209

1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
}

bool Curl_none_false_start(void)
{
  return FALSE;
}

#ifndef CURL_DISABLE_CRYPTO_AUTH
CURLcode Curl_none_md5sum(unsigned char *input, size_t inputlen,
                          unsigned char *md5sum, size_t md5len UNUSED_PARAM)
{
  struct MD5_context *MD5pw;

  (void)md5len;

  MD5pw = Curl_MD5_init(Curl_DIGEST_MD5);
  if(!MD5pw)
    return CURLE_OUT_OF_MEMORY;
  Curl_MD5_update(MD5pw, input, curlx_uztoui(inputlen));
  Curl_MD5_final(MD5pw, md5sum);
  return CURLE_OK;
}
#else
CURLcode Curl_none_md5sum(unsigned char *input UNUSED_PARAM,
                          size_t inputlen UNUSED_PARAM,
                          unsigned char *md5sum UNUSED_PARAM,
                          size_t md5len UNUSED_PARAM)
{
  (void)input;
  (void)inputlen;
  (void)md5sum;
  (void)md5len;
  return CURLE_NOT_BUILT_IN;
}
#endif

static int Curl_multissl_init(void)
{
  if(multissl_init(NULL))
    return 1;
  return Curl_ssl->init();
}


static CURLcode Curl_multissl_connect(struct connectdata *conn, int sockindex)
{
  if(multissl_init(NULL))
    return CURLE_FAILED_INIT;
  return Curl_ssl->connect_blocking(conn, sockindex);
}

static CURLcode Curl_multissl_connect_nonblocking(struct connectdata *conn,

                                                  int sockindex, bool *done)
{
  if(multissl_init(NULL))
    return CURLE_FAILED_INIT;
  return Curl_ssl->connect_nonblocking(conn, sockindex, done);
}

static void *Curl_multissl_get_internals(struct ssl_connect_data *connssl,
                                         CURLINFO info)
{
  if(multissl_init(NULL))
    return NULL;
  return Curl_ssl->get_internals(connssl, info);
}


static void Curl_multissl_close(struct connectdata *conn, int sockindex)
{
  if(multissl_init(NULL))
    return;
  Curl_ssl->close_one(conn, sockindex);
}

static const struct Curl_ssl Curl_ssl_multi = {
  { CURLSSLBACKEND_NONE, "multi" },  /* info */
  0, /* supports nothing */
  (size_t)-1, /* something insanely large to be on the safe side */

  Curl_multissl_init,                /* init */
  Curl_none_cleanup,                 /* cleanup */
  Curl_multissl_version,             /* version */
  Curl_none_check_cxn,               /* check_cxn */
  Curl_none_shutdown,                /* shutdown */
  Curl_none_data_pending,            /* data_pending */
  Curl_none_random,                  /* random */
  Curl_none_cert_status_request,     /* cert_status_request */
  Curl_multissl_connect,             /* connect */
  Curl_multissl_connect_nonblocking, /* connect_nonblocking */
  Curl_multissl_get_internals,       /* get_internals */
  Curl_multissl_close,               /* close_one */
  Curl_none_close_all,               /* close_all */
  Curl_none_session_free,            /* session_free */
  Curl_none_set_engine,              /* set_engine */
  Curl_none_set_engine_default,      /* set_engine_default */
  Curl_none_engines_list,            /* engines_list */
  Curl_none_false_start,             /* false_start */
  Curl_none_md5sum,                  /* md5sum */
  NULL                               /* sha256sum */
};

const struct Curl_ssl *Curl_ssl =
#if defined(CURL_WITH_MULTI_SSL)
  &Curl_ssl_multi;
#elif defined(USE_WOLFSSL)







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|

|




>
|

|

|


|
>
|

|

|


|
|

|




>
|

|

|







|

|





|
|
|
|






<







1142
1143
1144
1145
1146
1147
1148





























1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211

1212
1213
1214
1215
1216
1217
1218
}

bool Curl_none_false_start(void)
{
  return FALSE;
}






























static int multissl_init(void)
{
  if(multissl_setup(NULL))
    return 1;
  return Curl_ssl->init();
}

static CURLcode multissl_connect(struct Curl_easy *data,
                                 struct connectdata *conn, int sockindex)
{
  if(multissl_setup(NULL))
    return CURLE_FAILED_INIT;
  return Curl_ssl->connect_blocking(data, conn, sockindex);
}

static CURLcode multissl_connect_nonblocking(struct Curl_easy *data,
                                             struct connectdata *conn,
                                             int sockindex, bool *done)
{
  if(multissl_setup(NULL))
    return CURLE_FAILED_INIT;
  return Curl_ssl->connect_nonblocking(data, conn, sockindex, done);
}

static void *multissl_get_internals(struct ssl_connect_data *connssl,
                                    CURLINFO info)
{
  if(multissl_setup(NULL))
    return NULL;
  return Curl_ssl->get_internals(connssl, info);
}

static void multissl_close(struct Curl_easy *data, struct connectdata *conn,
                           int sockindex)
{
  if(multissl_setup(NULL))
    return;
  Curl_ssl->close_one(data, conn, sockindex);
}

static const struct Curl_ssl Curl_ssl_multi = {
  { CURLSSLBACKEND_NONE, "multi" },  /* info */
  0, /* supports nothing */
  (size_t)-1, /* something insanely large to be on the safe side */

  multissl_init,                     /* init */
  Curl_none_cleanup,                 /* cleanup */
  multissl_version,                  /* version */
  Curl_none_check_cxn,               /* check_cxn */
  Curl_none_shutdown,                /* shutdown */
  Curl_none_data_pending,            /* data_pending */
  Curl_none_random,                  /* random */
  Curl_none_cert_status_request,     /* cert_status_request */
  multissl_connect,                  /* connect */
  multissl_connect_nonblocking,      /* connect_nonblocking */
  multissl_get_internals,            /* get_internals */
  multissl_close,                    /* close_one */
  Curl_none_close_all,               /* close_all */
  Curl_none_session_free,            /* session_free */
  Curl_none_set_engine,              /* set_engine */
  Curl_none_set_engine_default,      /* set_engine_default */
  Curl_none_engines_list,            /* engines_list */
  Curl_none_false_start,             /* false_start */

  NULL                               /* sha256sum */
};

const struct Curl_ssl *Curl_ssl =
#if defined(CURL_WITH_MULTI_SSL)
  &Curl_ssl_multi;
#elif defined(USE_WOLFSSL)
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
#endif
#if defined(USE_BEARSSL)
  &Curl_ssl_bearssl,
#endif
  NULL
};

static size_t Curl_multissl_version(char *buffer, size_t size)
{
  static const struct Curl_ssl *selected;
  static char backends[200];
  static size_t backends_len;
  const struct Curl_ssl *current;

  current = Curl_ssl == &Curl_ssl_multi ? available_backends[0] : Curl_ssl;







|







1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
#endif
#if defined(USE_BEARSSL)
  &Curl_ssl_bearssl,
#endif
  NULL
};

static size_t multissl_version(char *buffer, size_t size)
{
  static const struct Curl_ssl *selected;
  static char backends[200];
  static size_t backends_len;
  const struct Curl_ssl *current;

  current = Curl_ssl == &Curl_ssl_multi ? available_backends[0] : Curl_ssl;
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
    return size - 1;
  }

  strcpy(buffer, backends);
  return backends_len;
}

static int multissl_init(const struct Curl_ssl *backend)
{
  const char *env;
  char *env_tmp;

  if(Curl_ssl != &Curl_ssl_multi)
    return 1;








|







1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
    return size - 1;
  }

  strcpy(buffer, backends);
  return backends_len;
}

static int multissl_setup(const struct Curl_ssl *backend)
{
  const char *env;
  char *env_tmp;

  if(Curl_ssl != &Curl_ssl_multi)
    return 1;

1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
#else
           CURLSSLSET_UNKNOWN_BACKEND;
#endif

  for(i = 0; available_backends[i]; i++) {
    if(available_backends[i]->info.id == id ||
       (name && strcasecompare(available_backends[i]->info.name, name))) {
      multissl_init(available_backends[i]);
      return CURLSSLSET_OK;
    }
  }

  return CURLSSLSET_UNKNOWN_BACKEND;
}








|







1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
#else
           CURLSSLSET_UNKNOWN_BACKEND;
#endif

  for(i = 0; available_backends[i]; i++) {
    if(available_backends[i]->info.id == id ||
       (name && strcasecompare(available_backends[i]->info.name, name))) {
      multissl_setup(available_backends[i]);
      return CURLSSLSET_OK;
    }
  }

  return CURLSSLSET_UNKNOWN_BACKEND;
}

Changes to jni/curl/lib/vtls/vtls.h.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#ifndef HEADER_CURL_VTLS_H
#define HEADER_CURL_VTLS_H
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2020, 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 https://curl.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









|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#ifndef HEADER_CURL_VTLS_H
#define HEADER_CURL_VTLS_H
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2021, 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 https://curl.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
43
44
45
46
47
48
49

50
51
52
53
54
55
56
57
58
59

60

61
62

63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85

86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
  size_t sizeof_ssl_backend_data;

  int (*init)(void);
  void (*cleanup)(void);

  size_t (*version)(char *buffer, size_t size);
  int (*check_cxn)(struct connectdata *cxn);

  int (*shut_down)(struct connectdata *conn, int sockindex);
  bool (*data_pending)(const struct connectdata *conn,
                       int connindex);

  /* return 0 if a find random is filled in */
  CURLcode (*random)(struct Curl_easy *data, unsigned char *entropy,
                     size_t length);
  bool (*cert_status_request)(void);

  CURLcode (*connect_blocking)(struct connectdata *conn, int sockindex);

  CURLcode (*connect_nonblocking)(struct connectdata *conn, int sockindex,

                                  bool *done);
  void *(*get_internals)(struct ssl_connect_data *connssl, CURLINFO info);

  void (*close_one)(struct connectdata *conn, int sockindex);
  void (*close_all)(struct Curl_easy *data);
  void (*session_free)(void *ptr);

  CURLcode (*set_engine)(struct Curl_easy *data, const char *engine);
  CURLcode (*set_engine_default)(struct Curl_easy *data);
  struct curl_slist *(*engines_list)(struct Curl_easy *data);

  bool (*false_start)(void);

  CURLcode (*md5sum)(unsigned char *input, size_t inputlen,
                     unsigned char *md5sum, size_t md5sumlen);
  CURLcode (*sha256sum)(const unsigned char *input, size_t inputlen,
                    unsigned char *sha256sum, size_t sha256sumlen);
};

#ifdef USE_SSL
extern const struct Curl_ssl *Curl_ssl;
#endif

int Curl_none_init(void);
void Curl_none_cleanup(void);
int Curl_none_shutdown(struct connectdata *conn, int sockindex);

int Curl_none_check_cxn(struct connectdata *conn);
CURLcode Curl_none_random(struct Curl_easy *data, unsigned char *entropy,
                          size_t length);
void Curl_none_close_all(struct Curl_easy *data);
void Curl_none_session_free(void *ptr);
bool Curl_none_data_pending(const struct connectdata *conn, int connindex);
bool Curl_none_cert_status_request(void);
CURLcode Curl_none_set_engine(struct Curl_easy *data, const char *engine);
CURLcode Curl_none_set_engine_default(struct Curl_easy *data);
struct curl_slist *Curl_none_engines_list(struct Curl_easy *data);
bool Curl_none_false_start(void);
bool Curl_ssl_tls13_ciphersuites(void);
CURLcode Curl_none_md5sum(unsigned char *input, size_t inputlen,
                          unsigned char *md5sum, size_t md5len);

#include "openssl.h"        /* OpenSSL versions */
#include "gtls.h"           /* GnuTLS versions */
#include "nssg.h"           /* NSS versions */
#include "gskit.h"          /* Global Secure ToolKit versions */
#include "wolfssl.h"        /* wolfSSL versions */
#include "schannel.h"       /* Schannel SSPI version */







>
|








|
>
|
>


>
|








<
<
<










|
>












<
<







43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75



76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99


100
101
102
103
104
105
106
  size_t sizeof_ssl_backend_data;

  int (*init)(void);
  void (*cleanup)(void);

  size_t (*version)(char *buffer, size_t size);
  int (*check_cxn)(struct connectdata *cxn);
  int (*shut_down)(struct Curl_easy *data, struct connectdata *conn,
                   int sockindex);
  bool (*data_pending)(const struct connectdata *conn,
                       int connindex);

  /* return 0 if a find random is filled in */
  CURLcode (*random)(struct Curl_easy *data, unsigned char *entropy,
                     size_t length);
  bool (*cert_status_request)(void);

  CURLcode (*connect_blocking)(struct Curl_easy *data,
                               struct connectdata *conn, int sockindex);
  CURLcode (*connect_nonblocking)(struct Curl_easy *data,
                                  struct connectdata *conn, int sockindex,
                                  bool *done);
  void *(*get_internals)(struct ssl_connect_data *connssl, CURLINFO info);
  void (*close_one)(struct Curl_easy *data, struct connectdata *conn,
                    int sockindex);
  void (*close_all)(struct Curl_easy *data);
  void (*session_free)(void *ptr);

  CURLcode (*set_engine)(struct Curl_easy *data, const char *engine);
  CURLcode (*set_engine_default)(struct Curl_easy *data);
  struct curl_slist *(*engines_list)(struct Curl_easy *data);

  bool (*false_start)(void);



  CURLcode (*sha256sum)(const unsigned char *input, size_t inputlen,
                    unsigned char *sha256sum, size_t sha256sumlen);
};

#ifdef USE_SSL
extern const struct Curl_ssl *Curl_ssl;
#endif

int Curl_none_init(void);
void Curl_none_cleanup(void);
int Curl_none_shutdown(struct Curl_easy *data, struct connectdata *conn,
                       int sockindex);
int Curl_none_check_cxn(struct connectdata *conn);
CURLcode Curl_none_random(struct Curl_easy *data, unsigned char *entropy,
                          size_t length);
void Curl_none_close_all(struct Curl_easy *data);
void Curl_none_session_free(void *ptr);
bool Curl_none_data_pending(const struct connectdata *conn, int connindex);
bool Curl_none_cert_status_request(void);
CURLcode Curl_none_set_engine(struct Curl_easy *data, const char *engine);
CURLcode Curl_none_set_engine_default(struct Curl_easy *data);
struct curl_slist *Curl_none_engines_list(struct Curl_easy *data);
bool Curl_none_false_start(void);
bool Curl_ssl_tls13_ciphersuites(void);



#include "openssl.h"        /* OpenSSL versions */
#include "gtls.h"           /* GnuTLS versions */
#include "nssg.h"           /* NSS versions */
#include "gskit.h"          /* Global Secure ToolKit versions */
#include "wolfssl.h"        /* wolfSSL versions */
#include "schannel.h"       /* Schannel SSPI version */
161
162
163
164
165
166
167
168

169

170
171
172
173
174
175

176

177
178
179
180
181
182
183
int Curl_ssl_getsock(struct connectdata *conn, curl_socket_t *socks);

int Curl_ssl_backend(void);

#ifdef USE_SSL
int Curl_ssl_init(void);
void Curl_ssl_cleanup(void);
CURLcode Curl_ssl_connect(struct connectdata *conn, int sockindex);

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) */
void Curl_ssl_close_all(struct Curl_easy *data);
void Curl_ssl_close(struct connectdata *conn, int sockindex);

CURLcode Curl_ssl_shutdown(struct connectdata *conn, int sockindex);

CURLcode Curl_ssl_set_engine(struct Curl_easy *data, const char *engine);
/* Sets engine as default for all SSL operations */
CURLcode Curl_ssl_set_engine_default(struct Curl_easy *data);
struct curl_slist *Curl_ssl_engines_list(struct Curl_easy *data);

/* init the SSL session ID cache */
CURLcode Curl_ssl_initsessions(struct Curl_easy *, size_t);







|
>
|
>





|
>
|
>







161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
int Curl_ssl_getsock(struct connectdata *conn, curl_socket_t *socks);

int Curl_ssl_backend(void);

#ifdef USE_SSL
int Curl_ssl_init(void);
void Curl_ssl_cleanup(void);
CURLcode Curl_ssl_connect(struct Curl_easy *data, struct connectdata *conn,
                          int sockindex);
CURLcode Curl_ssl_connect_nonblocking(struct Curl_easy *data,
                                      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) */
void Curl_ssl_close_all(struct Curl_easy *data);
void Curl_ssl_close(struct Curl_easy *data, struct connectdata *conn,
                    int sockindex);
CURLcode Curl_ssl_shutdown(struct Curl_easy *data, struct connectdata *conn,
                           int sockindex);
CURLcode Curl_ssl_set_engine(struct Curl_easy *data, const char *engine);
/* Sets engine as default for all SSL operations */
CURLcode Curl_ssl_set_engine_default(struct Curl_easy *data);
struct curl_slist *Curl_ssl_engines_list(struct Curl_easy *data);

/* init the SSL session ID cache */
CURLcode Curl_ssl_initsessions(struct Curl_easy *, size_t);
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219

220
221
222
223
224
225
226
227
228

229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
/* Lock session cache mutex.
 * Call this before calling other Curl_ssl_*session* functions
 * Caller should unlock this mutex as soon as possible, as it may block
 * other SSL connection from making progress.
 * The purpose of explicitly locking SSL session cache data is to allow
 * individual SSL engines to manage session lifetime in their specific way.
 */
void Curl_ssl_sessionid_lock(struct connectdata *conn);

/* Unlock session cache mutex */
void Curl_ssl_sessionid_unlock(struct connectdata *conn);

/* extract a session ID
 * Sessionid mutex must be locked (see Curl_ssl_sessionid_lock).
 * Caller must make sure that the ownership of returned sessionid object
 * is properly taken (e.g. its refcount is incremented
 * under sessionid mutex).
 */
bool Curl_ssl_getsessionid(struct connectdata *conn,

                           void **ssl_sessionid,
                           size_t *idsize, /* set 0 if unknown */
                           int sockindex);
/* add a new session ID
 * Sessionid mutex must be locked (see Curl_ssl_sessionid_lock).
 * Caller must ensure that it has properly shared ownership of this sessionid
 * object with cache (e.g. incrementing refcount on success)
 */
CURLcode Curl_ssl_addsessionid(struct connectdata *conn,

                               void *ssl_sessionid,
                               size_t idsize,
                               int sockindex);
/* Kill a single session ID entry in the cache
 * Sessionid mutex must be locked (see Curl_ssl_sessionid_lock).
 * This will call engine-specific curlssl_session_free function, which must
 * take sessionid object ownership from sessionid cache
 * (e.g. decrement refcount).
 */
void Curl_ssl_kill_session(struct Curl_ssl_session *session);
/* delete a session from the cache
 * Sessionid mutex must be locked (see Curl_ssl_sessionid_lock).
 * This will call engine-specific curlssl_session_free function, which must
 * take sessionid object ownership from sessionid cache
 * (e.g. decrement refcount).
 */
void Curl_ssl_delsessionid(struct connectdata *conn, void *ssl_sessionid);

/* get N random bytes into the buffer */
CURLcode Curl_ssl_random(struct Curl_easy *data, unsigned char *buffer,
                         size_t length);
CURLcode Curl_ssl_md5sum(unsigned char *tmp, /* input */
                         size_t tmplen,
                         unsigned char *md5sum, /* output */
                         size_t md5len);
/* Check pinned public key. */
CURLcode Curl_pin_peer_pubkey(struct Curl_easy *data,
                              const char *pinnedpubkey,
                              const unsigned char *pubkey, size_t pubkeylen);

bool Curl_ssl_cert_status_request(void);

bool Curl_ssl_false_start(void);

#define SSL_SHUTDOWN_TIMEOUT 10000 /* ms */

#else /* if not USE_SSL */

/* 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_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
#define Curl_ssl_tls13_ciphersuites() FALSE
#endif

#endif /* HEADER_CURL_VTLS_H */







|


|







|
>








|
>
















|




<
<
<
<
















|

|
|









|








205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255




256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
/* Lock session cache mutex.
 * Call this before calling other Curl_ssl_*session* functions
 * Caller should unlock this mutex as soon as possible, as it may block
 * other SSL connection from making progress.
 * The purpose of explicitly locking SSL session cache data is to allow
 * individual SSL engines to manage session lifetime in their specific way.
 */
void Curl_ssl_sessionid_lock(struct Curl_easy *data);

/* Unlock session cache mutex */
void Curl_ssl_sessionid_unlock(struct Curl_easy *data);

/* extract a session ID
 * Sessionid mutex must be locked (see Curl_ssl_sessionid_lock).
 * Caller must make sure that the ownership of returned sessionid object
 * is properly taken (e.g. its refcount is incremented
 * under sessionid mutex).
 */
bool Curl_ssl_getsessionid(struct Curl_easy *data,
                           struct connectdata *conn,
                           void **ssl_sessionid,
                           size_t *idsize, /* set 0 if unknown */
                           int sockindex);
/* add a new session ID
 * Sessionid mutex must be locked (see Curl_ssl_sessionid_lock).
 * Caller must ensure that it has properly shared ownership of this sessionid
 * object with cache (e.g. incrementing refcount on success)
 */
CURLcode Curl_ssl_addsessionid(struct Curl_easy *data,
                               struct connectdata *conn,
                               void *ssl_sessionid,
                               size_t idsize,
                               int sockindex);
/* Kill a single session ID entry in the cache
 * Sessionid mutex must be locked (see Curl_ssl_sessionid_lock).
 * This will call engine-specific curlssl_session_free function, which must
 * take sessionid object ownership from sessionid cache
 * (e.g. decrement refcount).
 */
void Curl_ssl_kill_session(struct Curl_ssl_session *session);
/* delete a session from the cache
 * Sessionid mutex must be locked (see Curl_ssl_sessionid_lock).
 * This will call engine-specific curlssl_session_free function, which must
 * take sessionid object ownership from sessionid cache
 * (e.g. decrement refcount).
 */
void Curl_ssl_delsessionid(struct Curl_easy *data, void *ssl_sessionid);

/* get N random bytes into the buffer */
CURLcode Curl_ssl_random(struct Curl_easy *data, unsigned char *buffer,
                         size_t length);




/* Check pinned public key. */
CURLcode Curl_pin_peer_pubkey(struct Curl_easy *data,
                              const char *pinnedpubkey,
                              const unsigned char *pubkey, size_t pubkeylen);

bool Curl_ssl_cert_status_request(void);

bool Curl_ssl_false_start(void);

#define SSL_SHUTDOWN_TIMEOUT 10000 /* ms */

#else /* if not USE_SSL */

/* 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,z) CURLE_NOT_BUILT_IN
#define Curl_ssl_close_all(x) Curl_nop_stmt
#define Curl_ssl_close(x,y,z) Curl_nop_stmt
#define Curl_ssl_shutdown(x,y,z) 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_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,w) 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
#define Curl_ssl_tls13_ciphersuites() FALSE
#endif

#endif /* HEADER_CURL_VTLS_H */
Changes to jni/curl/lib/vtls/wolfssl.c.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2020, 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 https://curl.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







|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2021, 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 https://curl.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
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
}

/*
 * This function loads all the client/CA certificates and CRLs. Setup the TLS
 * layer and do all necessary magic.
 */
static CURLcode
wolfssl_connect_step1(struct connectdata *conn,
                     int sockindex)
{
  char *ciphers;
  struct Curl_easy *data = conn->data;
  struct ssl_connect_data *connssl = &conn->ssl[sockindex];
  struct ssl_backend_data *backend = connssl->backend;
  SSL_METHOD* req_method = NULL;
  curl_socket_t sockfd = conn->sock[sockindex];
#ifdef HAVE_SNI
  bool sni = FALSE;
#define use_sni(x)  sni = (x)







|



<







213
214
215
216
217
218
219
220
221
222
223

224
225
226
227
228
229
230
}

/*
 * This function loads all the client/CA certificates and CRLs. Setup the TLS
 * layer and do all necessary magic.
 */
static CURLcode
wolfssl_connect_step1(struct Curl_easy *data, struct connectdata *conn,
                     int sockindex)
{
  char *ciphers;

  struct ssl_connect_data *connssl = &conn->ssl[sockindex];
  struct ssl_backend_data *backend = connssl->backend;
  SSL_METHOD* req_method = NULL;
  curl_socket_t sockfd = conn->sock[sockindex];
#ifdef HAVE_SNI
  bool sni = FALSE;
#define use_sni(x)  sni = (x)
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267

268
269




270
271
272
273
274
275
276
    infof(data, "wolfSSL <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:
#ifdef WOLFSSL_ALLOW_TLSV10
    req_method = TLSv1_client_method();
    use_sni(TRUE);
#else
    failf(data, "wolfSSL does not support TLS 1.0");
    return CURLE_NOT_BUILT_IN;
#endif
    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_TLSv1_3:
#ifdef WOLFSSL_TLS13







|








>


>
>
>
>







251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
    infof(data, "wolfSSL <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:
#if defined(WOLFSSL_ALLOW_TLSV10) && !defined(NO_OLD_TLS)
    req_method = TLSv1_client_method();
    use_sni(TRUE);
#else
    failf(data, "wolfSSL does not support TLS 1.0");
    return CURLE_NOT_BUILT_IN;
#endif
    break;
  case CURL_SSLVERSION_TLSv1_1:
#ifndef NO_OLD_TLS
    req_method = TLSv1_1_client_method();
    use_sni(TRUE);
#else
    failf(data, "wolfSSL does not support TLS 1.1");
    return CURLE_NOT_BUILT_IN;
#endif
    break;
  case CURL_SSLVERSION_TLSv1_2:
    req_method = TLSv1_2_client_method();
    use_sni(TRUE);
    break;
  case CURL_SSLVERSION_TLSv1_3:
#ifdef WOLFSSL_TLS13
496
497
498
499
500
501
502







503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
#if defined(HAVE_SECRET_CALLBACK) && defined(WOLFSSL_TLS13)
    wolfSSL_set_tls13_secret_cb(backend->handle,
                                wolfssl_tls13_secret_callback, NULL);
#endif
  }
#endif /* OPENSSL_EXTRA */








  /* Check if there's a cached ID we can/should use here! */
  if(SSL_SET_OPTION(primary.sessionid)) {
    void *ssl_sessionid = NULL;

    Curl_ssl_sessionid_lock(conn);
    if(!Curl_ssl_getsessionid(conn, &ssl_sessionid, NULL, sockindex)) {
      /* we got a session id, use it! */
      if(!SSL_set_session(backend->handle, ssl_sessionid)) {
        char error_buffer[WOLFSSL_MAX_ERROR_SZ];
        Curl_ssl_sessionid_unlock(conn);
        failf(data, "SSL: SSL_set_session failed: %s",
              ERR_error_string(SSL_get_error(backend->handle, 0),
                               error_buffer));
        return CURLE_SSL_CONNECT_ERROR;
      }
      /* Informational message */
      infof(data, "SSL re-using session ID\n");
    }
    Curl_ssl_sessionid_unlock(conn);
  }

  /* pass the raw socket into the SSL layer */
  if(!SSL_set_fd(backend->handle, (int)sockfd)) {
    failf(data, "SSL: SSL_set_fd failed");
    return CURLE_SSL_CONNECT_ERROR;
  }

  connssl->connecting_state = ssl_connect_2;
  return CURLE_OK;
}


static CURLcode
wolfssl_connect_step2(struct connectdata *conn,
                     int sockindex)
{
  int ret = -1;
  struct Curl_easy *data = conn->data;
  struct ssl_connect_data *connssl = &conn->ssl[sockindex];
  struct ssl_backend_data *backend = connssl->backend;
#ifndef CURL_DISABLE_PROXY
  const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name :
    conn->host.name;
  const char * const dispname = SSL_IS_PROXY() ?
    conn->http_proxy.host.dispname : conn->host.dispname;







>
>
>
>
>
>
>




|
|



|








|














|



<







500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550

551
552
553
554
555
556
557
#if defined(HAVE_SECRET_CALLBACK) && defined(WOLFSSL_TLS13)
    wolfSSL_set_tls13_secret_cb(backend->handle,
                                wolfssl_tls13_secret_callback, NULL);
#endif
  }
#endif /* OPENSSL_EXTRA */

#ifdef HAVE_SECURE_RENEGOTIATION
  if(wolfSSL_UseSecureRenegotiation(backend->handle) != SSL_SUCCESS) {
    failf(data, "SSL: failed setting secure renegotiation");
    return CURLE_SSL_CONNECT_ERROR;
  }
#endif /* HAVE_SECURE_RENEGOTIATION */

  /* Check if there's a cached ID we can/should use here! */
  if(SSL_SET_OPTION(primary.sessionid)) {
    void *ssl_sessionid = NULL;

    Curl_ssl_sessionid_lock(data);
    if(!Curl_ssl_getsessionid(data, conn, &ssl_sessionid, NULL, sockindex)) {
      /* we got a session id, use it! */
      if(!SSL_set_session(backend->handle, ssl_sessionid)) {
        char error_buffer[WOLFSSL_MAX_ERROR_SZ];
        Curl_ssl_sessionid_unlock(data);
        failf(data, "SSL: SSL_set_session failed: %s",
              ERR_error_string(SSL_get_error(backend->handle, 0),
                               error_buffer));
        return CURLE_SSL_CONNECT_ERROR;
      }
      /* Informational message */
      infof(data, "SSL re-using session ID\n");
    }
    Curl_ssl_sessionid_unlock(data);
  }

  /* pass the raw socket into the SSL layer */
  if(!SSL_set_fd(backend->handle, (int)sockfd)) {
    failf(data, "SSL: SSL_set_fd failed");
    return CURLE_SSL_CONNECT_ERROR;
  }

  connssl->connecting_state = ssl_connect_2;
  return CURLE_OK;
}


static CURLcode
wolfssl_connect_step2(struct Curl_easy *data, struct connectdata *conn,
                     int sockindex)
{
  int ret = -1;

  struct ssl_connect_data *connssl = &conn->ssl[sockindex];
  struct ssl_backend_data *backend = connssl->backend;
#ifndef CURL_DISABLE_PROXY
  const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name :
    conn->host.name;
  const char * const dispname = SSL_IS_PROXY() ?
    conn->http_proxy.host.dispname : conn->host.dispname;
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
      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",
            dispname);
      return CURLE_PEER_FAILED_VERIFICATION;
#else
      /* When the wolfssl_check_domain_name() is used and you desire to
       * continue on a DOMAIN_NAME_MISMATCH, i.e. 'conn->ssl_config.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







|







614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
      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\"",
            dispname);
      return CURLE_PEER_FAILED_VERIFICATION;
#else
      /* When the wolfssl_check_domain_name() is used and you desire to
       * continue on a DOMAIN_NAME_MISMATCH, i.e. 'conn->ssl_config.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
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
        return CURLE_OK;
      }
#endif
    }
#if LIBWOLFSSL_VERSION_HEX >= 0x02007000 /* 2.7.0 */
    else if(ASN_NO_SIGNER_E == detail) {
      if(SSL_CONN_CONFIG(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");







|







641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
        return CURLE_OK;
      }
#endif
    }
#if LIBWOLFSSL_VERSION_HEX >= 0x02007000 /* 2.7.0 */
    else if(ASN_NO_SIGNER_E == detail) {
      if(SSL_CONN_CONFIG(verifypeer)) {
        failf(data, "\tCA signer not available for verification");
        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");
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
              !memcmp(protocol, NGHTTP2_PROTO_VERSION_ID,
                      NGHTTP2_PROTO_VERSION_ID_LEN))
        conn->negnpn = CURL_HTTP_VERSION_2;
#endif
      else
        infof(data, "ALPN, unrecognized protocol %.*s\n", protocol_len,
              protocol);
      Curl_multiuse_state(conn, conn->negnpn == CURL_HTTP_VERSION_2 ?
                          BUNDLE_MULTIPLEX : BUNDLE_NO_MULTIUSE);
    }
    else if(rc == SSL_ALPN_NOT_FOUND)
      infof(data, "ALPN, server did not agree to a protocol\n");
    else {
      failf(data, "ALPN, failure getting protocol, error %d", rc);
      return CURLE_SSL_CONNECT_ERROR;







|







729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
              !memcmp(protocol, NGHTTP2_PROTO_VERSION_ID,
                      NGHTTP2_PROTO_VERSION_ID_LEN))
        conn->negnpn = CURL_HTTP_VERSION_2;
#endif
      else
        infof(data, "ALPN, unrecognized protocol %.*s\n", protocol_len,
              protocol);
      Curl_multiuse_state(data, conn->negnpn == CURL_HTTP_VERSION_2 ?
                          BUNDLE_MULTIPLEX : BUNDLE_NO_MULTIUSE);
    }
    else if(rc == SSL_ALPN_NOT_FOUND)
      infof(data, "ALPN, server did not agree to a protocol\n");
    else {
      failf(data, "ALPN, failure getting protocol, error %d", rc);
      return CURLE_SSL_CONNECT_ERROR;
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803

804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829

830
831
832
833


834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851

852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932

933
934
935
936


937
938
939
940
941
942
943
944
945
946
947

948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
#endif

  return CURLE_OK;
}


static CURLcode
wolfssl_connect_step3(struct connectdata *conn,
                     int sockindex)
{
  CURLcode result = CURLE_OK;
  struct Curl_easy *data = conn->data;
  struct ssl_connect_data *connssl = &conn->ssl[sockindex];
  struct ssl_backend_data *backend = connssl->backend;

  DEBUGASSERT(ssl_connect_3 == connssl->connecting_state);

  if(SSL_SET_OPTION(primary.sessionid)) {
    bool incache;
    SSL_SESSION *our_ssl_sessionid;
    void *old_ssl_sessionid = NULL;

    our_ssl_sessionid = SSL_get_session(backend->handle);

    Curl_ssl_sessionid_lock(conn);
    incache = !(Curl_ssl_getsessionid(conn, &old_ssl_sessionid, NULL,
                                      sockindex));
    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 */, sockindex);
      if(result) {
        Curl_ssl_sessionid_unlock(conn);
        failf(data, "failed to store ssl session");
        return result;
      }
    }
    Curl_ssl_sessionid_unlock(conn);
  }

  connssl->connecting_state = ssl_connect_done;

  return result;
}


static ssize_t wolfssl_send(struct connectdata *conn,
                           int sockindex,
                           const void *mem,
                           size_t len,
                           CURLcode *curlcode)
{

  struct ssl_connect_data *connssl = &conn->ssl[sockindex];
  struct ssl_backend_data *backend = connssl->backend;
  char error_buffer[WOLFSSL_MAX_ERROR_SZ];
  int memlen = (len > (size_t)INT_MAX) ? INT_MAX : (int)len;
  int rc = SSL_write(backend->handle, mem, memlen);

  if(rc < 0) {
    int err = SSL_get_error(backend->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;
}


static void Curl_wolfssl_close(struct connectdata *conn, int sockindex)
{
  struct ssl_connect_data *connssl = &conn->ssl[sockindex];
  struct ssl_backend_data *backend = connssl->backend;



  if(backend->handle) {
    (void)SSL_shutdown(backend->handle);
    SSL_free(backend->handle);
    backend->handle = NULL;
  }
  if(backend->ctx) {
    SSL_CTX_free(backend->ctx);
    backend->ctx = NULL;
  }
}

static ssize_t wolfssl_recv(struct connectdata *conn,
                            int num,
                            char *buf,
                            size_t buffersize,
                            CURLcode *curlcode)
{

  struct ssl_connect_data *connssl = &conn->ssl[num];
  struct ssl_backend_data *backend = connssl->backend;
  char error_buffer[WOLFSSL_MAX_ERROR_SZ];
  int buffsize = (buffersize > (size_t)INT_MAX) ? INT_MAX : (int)buffersize;
  int nread = SSL_read(backend->handle, buf, buffsize);

  if(nread < 0) {
    int err = SSL_get_error(backend->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;
}


static void Curl_wolfssl_session_free(void *ptr)
{
  (void)ptr;
  /* wolfSSL reuses sessions on own, no free */
}


static size_t Curl_wolfssl_version(char *buffer, size_t size)
{
#if LIBWOLFSSL_VERSION_HEX >= 0x03006000
  return msnprintf(buffer, size, "wolfSSL/%s", wolfSSL_lib_version());
#elif defined(WOLFSSL_VERSION)
  return msnprintf(buffer, size, "wolfSSL/%s", WOLFSSL_VERSION);
#endif
}


static int Curl_wolfssl_init(void)
{
#ifdef OPENSSL_EXTRA
  Curl_tls_keylog_open();
#endif
  return (wolfSSL_Init() == SSL_SUCCESS);
}


static void Curl_wolfssl_cleanup(void)
{
  wolfSSL_Cleanup();
#ifdef OPENSSL_EXTRA
  Curl_tls_keylog_close();
#endif
}


static bool Curl_wolfssl_data_pending(const struct connectdata *conn,
                                      int connindex)
{
  const struct ssl_connect_data *connssl = &conn->ssl[connindex];
  struct ssl_backend_data *backend = connssl->backend;
  if(backend->handle)   /* SSL is in use */
    return (0 != SSL_pending(backend->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)
 */
static int Curl_wolfssl_shutdown(struct connectdata *conn, int sockindex)

{
  int retval = 0;
  struct ssl_connect_data *connssl = &conn->ssl[sockindex];
  struct ssl_backend_data *backend = connssl->backend;



  if(backend->handle) {
    SSL_free(backend->handle);
    backend->handle = NULL;
  }
  return retval;
}


static CURLcode
wolfssl_connect_common(struct connectdata *conn,

                      int sockindex,
                      bool nonblocking,
                      bool *done)
{
  CURLcode result;
  struct Curl_easy *data = conn->data;
  struct ssl_connect_data *connssl = &conn->ssl[sockindex];
  curl_socket_t sockfd = conn->sock[sockindex];
  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 */
    const timediff_t 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 = wolfssl_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) {







|



<












|
|




|





|


|




|








|
|
|
|
|

>
















|









>
|



>
>












|





>


















|
|
<








|






|









|








|








|
|














|
>




>
>










|
>





<




















|







755
756
757
758
759
760
761
762
763
764
765

766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885

886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969

970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
#endif

  return CURLE_OK;
}


static CURLcode
wolfssl_connect_step3(struct Curl_easy *data, struct connectdata *conn,
                     int sockindex)
{
  CURLcode result = CURLE_OK;

  struct ssl_connect_data *connssl = &conn->ssl[sockindex];
  struct ssl_backend_data *backend = connssl->backend;

  DEBUGASSERT(ssl_connect_3 == connssl->connecting_state);

  if(SSL_SET_OPTION(primary.sessionid)) {
    bool incache;
    SSL_SESSION *our_ssl_sessionid;
    void *old_ssl_sessionid = NULL;

    our_ssl_sessionid = SSL_get_session(backend->handle);

    Curl_ssl_sessionid_lock(data);
    incache = !(Curl_ssl_getsessionid(data, conn, &old_ssl_sessionid, NULL,
                                      sockindex));
    if(incache) {
      if(old_ssl_sessionid != our_ssl_sessionid) {
        infof(data, "old SSL session ID is stale, removing\n");
        Curl_ssl_delsessionid(data, old_ssl_sessionid);
        incache = FALSE;
      }
    }

    if(!incache) {
      result = Curl_ssl_addsessionid(data, conn, our_ssl_sessionid,
                                     0 /* unknown size */, sockindex);
      if(result) {
        Curl_ssl_sessionid_unlock(data);
        failf(data, "failed to store ssl session");
        return result;
      }
    }
    Curl_ssl_sessionid_unlock(data);
  }

  connssl->connecting_state = ssl_connect_done;

  return result;
}


static ssize_t wolfssl_send(struct Curl_easy *data,
                            int sockindex,
                            const void *mem,
                            size_t len,
                            CURLcode *curlcode)
{
  struct connectdata *conn = data->conn;
  struct ssl_connect_data *connssl = &conn->ssl[sockindex];
  struct ssl_backend_data *backend = connssl->backend;
  char error_buffer[WOLFSSL_MAX_ERROR_SZ];
  int memlen = (len > (size_t)INT_MAX) ? INT_MAX : (int)len;
  int rc = SSL_write(backend->handle, mem, memlen);

  if(rc < 0) {
    int err = SSL_get_error(backend->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(data, "SSL write: %s, errno %d",
            ERR_error_string(err, error_buffer),
            SOCKERRNO);
      *curlcode = CURLE_SEND_ERROR;
      return -1;
    }
  }
  return rc;
}

static void wolfssl_close(struct Curl_easy *data, struct connectdata *conn,
                          int sockindex)
{
  struct ssl_connect_data *connssl = &conn->ssl[sockindex];
  struct ssl_backend_data *backend = connssl->backend;

  (void) data;

  if(backend->handle) {
    (void)SSL_shutdown(backend->handle);
    SSL_free(backend->handle);
    backend->handle = NULL;
  }
  if(backend->ctx) {
    SSL_CTX_free(backend->ctx);
    backend->ctx = NULL;
  }
}

static ssize_t wolfssl_recv(struct Curl_easy *data,
                            int num,
                            char *buf,
                            size_t buffersize,
                            CURLcode *curlcode)
{
  struct connectdata *conn = data->conn;
  struct ssl_connect_data *connssl = &conn->ssl[num];
  struct ssl_backend_data *backend = connssl->backend;
  char error_buffer[WOLFSSL_MAX_ERROR_SZ];
  int buffsize = (buffersize > (size_t)INT_MAX) ? INT_MAX : (int)buffersize;
  int nread = SSL_read(backend->handle, buf, buffsize);

  if(nread < 0) {
    int err = SSL_get_error(backend->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(data, "SSL read: %s, errno %d",
            ERR_error_string(err, error_buffer), SOCKERRNO);

      *curlcode = CURLE_RECV_ERROR;
      return -1;
    }
  }
  return nread;
}


static void wolfssl_session_free(void *ptr)
{
  (void)ptr;
  /* wolfSSL reuses sessions on own, no free */
}


static size_t wolfssl_version(char *buffer, size_t size)
{
#if LIBWOLFSSL_VERSION_HEX >= 0x03006000
  return msnprintf(buffer, size, "wolfSSL/%s", wolfSSL_lib_version());
#elif defined(WOLFSSL_VERSION)
  return msnprintf(buffer, size, "wolfSSL/%s", WOLFSSL_VERSION);
#endif
}


static int wolfssl_init(void)
{
#ifdef OPENSSL_EXTRA
  Curl_tls_keylog_open();
#endif
  return (wolfSSL_Init() == SSL_SUCCESS);
}


static void wolfssl_cleanup(void)
{
  wolfSSL_Cleanup();
#ifdef OPENSSL_EXTRA
  Curl_tls_keylog_close();
#endif
}


static bool wolfssl_data_pending(const struct connectdata *conn,
                                 int connindex)
{
  const struct ssl_connect_data *connssl = &conn->ssl[connindex];
  struct ssl_backend_data *backend = connssl->backend;
  if(backend->handle)   /* SSL is in use */
    return (0 != SSL_pending(backend->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)
 */
static int wolfssl_shutdown(struct Curl_easy *data, struct connectdata *conn,
                            int sockindex)
{
  int retval = 0;
  struct ssl_connect_data *connssl = &conn->ssl[sockindex];
  struct ssl_backend_data *backend = connssl->backend;

  (void) data;

  if(backend->handle) {
    SSL_free(backend->handle);
    backend->handle = NULL;
  }
  return retval;
}


static CURLcode
wolfssl_connect_common(struct Curl_easy *data,
                      struct connectdata *conn,
                      int sockindex,
                      bool nonblocking,
                      bool *done)
{
  CURLcode result;

  struct ssl_connect_data *connssl = &conn->ssl[sockindex];
  curl_socket_t sockfd = conn->sock[sockindex];
  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 */
    const timediff_t 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 = wolfssl_connect_step1(data, 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) {
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058

1059
1060
1061
1062
1063
1064
1065

1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
    /* 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 = wolfssl_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 = wolfssl_connect_step3(conn, sockindex);
    if(result)
      return result;
  }

  if(ssl_connect_done == connssl->connecting_state) {
    connssl->state = ssl_connection_complete;
    conn->recv[sockindex] = wolfssl_recv;
    conn->send[sockindex] = wolfssl_send;
    *done = TRUE;
  }
  else
    *done = FALSE;

  /* Reset our connect state machine */
  connssl->connecting_state = ssl_connect_1;

  return CURLE_OK;
}



static CURLcode Curl_wolfssl_connect_nonblocking(struct connectdata *conn,
                                                int sockindex, bool *done)
{
  return wolfssl_connect_common(conn, sockindex, TRUE, done);
}



static CURLcode Curl_wolfssl_connect(struct connectdata *conn, int sockindex)
{
  CURLcode result;
  bool done = FALSE;

  result = wolfssl_connect_common(conn, sockindex, FALSE, &done);
  if(result)
    return result;

  DEBUGASSERT(done);

  return CURLE_OK;
}

static CURLcode Curl_wolfssl_random(struct Curl_easy *data,
                                   unsigned char *entropy, size_t length)
{
  WC_RNG rng;
  (void)data;
  if(wc_InitRng(&rng))
    return CURLE_FAILED_INIT;
  if(length > UINT_MAX)
    return CURLE_FAILED_INIT;
  if(wc_RNG_GenerateBlock(&rng, entropy, (unsigned)length))
    return CURLE_FAILED_INIT;
  if(wc_FreeRng(&rng))
    return CURLE_FAILED_INIT;
  return CURLE_OK;
}

static CURLcode Curl_wolfssl_sha256sum(const unsigned char *tmp, /* input */
                                       size_t tmplen,
                                       unsigned char *sha256sum /* output */,
                                       size_t unused)
{
  wc_Sha256 SHA256pw;
  (void)unused;
  wc_InitSha256(&SHA256pw);
  wc_Sha256Update(&SHA256pw, tmp, (word32)tmplen);
  wc_Sha256Final(&SHA256pw, sha256sum);
  return CURLE_OK;
}

static void *Curl_wolfssl_get_internals(struct ssl_connect_data *connssl,
                                        CURLINFO info UNUSED_PARAM)
{
  struct ssl_backend_data *backend = connssl->backend;
  (void)info;
  return backend->handle;
}

const struct Curl_ssl Curl_ssl_wolfssl = {
  { CURLSSLBACKEND_WOLFSSL, "WolfSSL" }, /* info */

#ifdef KEEP_PEER_CERT
  SSLSUPP_PINNEDPUBKEY |
#endif
  SSLSUPP_SSL_CTX,

  sizeof(struct ssl_backend_data),

  Curl_wolfssl_init,                /* init */
  Curl_wolfssl_cleanup,             /* cleanup */
  Curl_wolfssl_version,             /* version */
  Curl_none_check_cxn,             /* check_cxn */
  Curl_wolfssl_shutdown,            /* shutdown */
  Curl_wolfssl_data_pending,        /* data_pending */
  Curl_wolfssl_random,              /* random */
  Curl_none_cert_status_request,   /* cert_status_request */
  Curl_wolfssl_connect,             /* connect */
  Curl_wolfssl_connect_nonblocking, /* connect_nonblocking */
  Curl_wolfssl_get_internals,       /* get_internals */
  Curl_wolfssl_close,               /* close_one */
  Curl_none_close_all,             /* close_all */
  Curl_wolfssl_session_free,        /* session_free */
  Curl_none_set_engine,            /* set_engine */
  Curl_none_set_engine_default,    /* set_engine_default */
  Curl_none_engines_list,          /* engines_list */
  Curl_none_false_start,           /* false_start */
  Curl_none_md5sum,                /* md5sum */
  Curl_wolfssl_sha256sum            /* sha256sum */
};

#endif







|








|




















>
|
|

|



>
|




|








|
|














|
|
|
|









|

















|
|
|

|
|
|

|
|
|
|

|




<
|



1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162

1163
1164
1165
1166
    /* 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 = wolfssl_connect_step2(data, 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 = wolfssl_connect_step3(data, conn, sockindex);
    if(result)
      return result;
  }

  if(ssl_connect_done == connssl->connecting_state) {
    connssl->state = ssl_connection_complete;
    conn->recv[sockindex] = wolfssl_recv;
    conn->send[sockindex] = wolfssl_send;
    *done = TRUE;
  }
  else
    *done = FALSE;

  /* Reset our connect state machine */
  connssl->connecting_state = ssl_connect_1;

  return CURLE_OK;
}


static CURLcode wolfssl_connect_nonblocking(struct Curl_easy *data,
                                            struct connectdata *conn,
                                            int sockindex, bool *done)
{
  return wolfssl_connect_common(data, conn, sockindex, TRUE, done);
}


static CURLcode wolfssl_connect(struct Curl_easy *data,
                                struct connectdata *conn, int sockindex)
{
  CURLcode result;
  bool done = FALSE;

  result = wolfssl_connect_common(data, conn, sockindex, FALSE, &done);
  if(result)
    return result;

  DEBUGASSERT(done);

  return CURLE_OK;
}

static CURLcode wolfssl_random(struct Curl_easy *data,
                               unsigned char *entropy, size_t length)
{
  WC_RNG rng;
  (void)data;
  if(wc_InitRng(&rng))
    return CURLE_FAILED_INIT;
  if(length > UINT_MAX)
    return CURLE_FAILED_INIT;
  if(wc_RNG_GenerateBlock(&rng, entropy, (unsigned)length))
    return CURLE_FAILED_INIT;
  if(wc_FreeRng(&rng))
    return CURLE_FAILED_INIT;
  return CURLE_OK;
}

static CURLcode wolfssl_sha256sum(const unsigned char *tmp, /* input */
                                  size_t tmplen,
                                  unsigned char *sha256sum /* output */,
                                  size_t unused)
{
  wc_Sha256 SHA256pw;
  (void)unused;
  wc_InitSha256(&SHA256pw);
  wc_Sha256Update(&SHA256pw, tmp, (word32)tmplen);
  wc_Sha256Final(&SHA256pw, sha256sum);
  return CURLE_OK;
}

static void *wolfssl_get_internals(struct ssl_connect_data *connssl,
                                        CURLINFO info UNUSED_PARAM)
{
  struct ssl_backend_data *backend = connssl->backend;
  (void)info;
  return backend->handle;
}

const struct Curl_ssl Curl_ssl_wolfssl = {
  { CURLSSLBACKEND_WOLFSSL, "WolfSSL" }, /* info */

#ifdef KEEP_PEER_CERT
  SSLSUPP_PINNEDPUBKEY |
#endif
  SSLSUPP_SSL_CTX,

  sizeof(struct ssl_backend_data),

  wolfssl_init,                    /* init */
  wolfssl_cleanup,                 /* cleanup */
  wolfssl_version,                 /* version */
  Curl_none_check_cxn,             /* check_cxn */
  wolfssl_shutdown,                /* shutdown */
  wolfssl_data_pending,            /* data_pending */
  wolfssl_random,                  /* random */
  Curl_none_cert_status_request,   /* cert_status_request */
  wolfssl_connect,                 /* connect */
  wolfssl_connect_nonblocking,     /* connect_nonblocking */
  wolfssl_get_internals,           /* get_internals */
  wolfssl_close,                   /* close_one */
  Curl_none_close_all,             /* close_all */
  wolfssl_session_free,            /* session_free */
  Curl_none_set_engine,            /* set_engine */
  Curl_none_set_engine_default,    /* set_engine_default */
  Curl_none_engines_list,          /* engines_list */
  Curl_none_false_start,           /* false_start */

  wolfssl_sha256sum                /* sha256sum */
};

#endif
Changes to jni/curl/lib/warnless.c.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2020, 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 https://curl.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







|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2021, 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 https://curl.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
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
#  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
*/

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







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







146
147
148
149
150
151
152



















153
154
155
156
157
158
159
#  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 size_t to signed curl_off_t
Changes to jni/curl/lib/warnless.h.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#ifndef HEADER_CURL_WARNLESS_H
#define HEADER_CURL_WARNLESS_H
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2020, 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 https://curl.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









|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#ifndef HEADER_CURL_WARNLESS_H
#define HEADER_CURL_WARNLESS_H
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2021, 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 https://curl.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
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
#define CURLX_FUNCTION_CAST(target_type, func) \
  (target_type)(void (*) (void))(func)

unsigned short curlx_ultous(unsigned long ulnum);

unsigned char curlx_ultouc(unsigned long ulnum);

int curlx_ultosi(unsigned long ulnum);

int curlx_uztosi(size_t uznum);

curl_off_t curlx_uztoso(size_t uznum);

unsigned long curlx_uztoul(size_t uznum);

unsigned int curlx_uztoui(size_t uznum);







<
<







29
30
31
32
33
34
35


36
37
38
39
40
41
42
#define CURLX_FUNCTION_CAST(target_type, func) \
  (target_type)(void (*) (void))(func)

unsigned short curlx_ultous(unsigned long ulnum);

unsigned char curlx_ultouc(unsigned long ulnum);



int curlx_uztosi(size_t uznum);

curl_off_t curlx_uztoso(size_t uznum);

unsigned long curlx_uztoul(size_t uznum);

unsigned int curlx_uztoui(size_t uznum);
Changes to jni/curl/lib/x509asn1.c.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2020, 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 https://curl.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







|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2021, 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 https://curl.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
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
        do_pubkey_field(data, certnum, "dh(g)", &elem);
        do_pubkey_field(data, certnum, "dh(pub_key)", &pk);
      }
    }
  }
}

CURLcode Curl_extract_certinfo(struct connectdata *conn,
                               int certnum,
                               const char *beg,
                               const char *end)
{
  struct Curl_X509certificate cert;
  struct Curl_easy *data = conn->data;
  struct Curl_asn1Element param;
  const char *ccp;
  char *cp1;
  size_t cl1;
  char *cp2;
  CURLcode result;
  unsigned long version;







|





<







941
942
943
944
945
946
947
948
949
950
951
952
953

954
955
956
957
958
959
960
        do_pubkey_field(data, certnum, "dh(g)", &elem);
        do_pubkey_field(data, certnum, "dh(pub_key)", &pk);
      }
    }
  }
}

CURLcode Curl_extract_certinfo(struct Curl_easy *data,
                               int certnum,
                               const char *beg,
                               const char *end)
{
  struct Curl_X509certificate cert;

  struct Curl_asn1Element param;
  const char *ccp;
  char *cp1;
  size_t cl1;
  char *cp2;
  CURLcode result;
  unsigned long version;
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
    return NULL;

  matched = !strcmp(p, oid);
  free((char *) p);
  return matched? ccp: NULL;
}

CURLcode Curl_verifyhost(struct connectdata *conn,
                         const char *beg, const char *end)
{
  struct Curl_easy *data = conn->data;
  struct Curl_X509certificate cert;
  struct Curl_asn1Element dn;
  struct Curl_asn1Element elem;
  struct Curl_asn1Element ext;
  struct Curl_asn1Element name;
  const char *p;
  const char *q;







|


<







1127
1128
1129
1130
1131
1132
1133
1134
1135
1136

1137
1138
1139
1140
1141
1142
1143
    return NULL;

  matched = !strcmp(p, oid);
  free((char *) p);
  return matched? ccp: NULL;
}

CURLcode Curl_verifyhost(struct Curl_easy *data, struct connectdata *conn,
                         const char *beg, const char *end)
{

  struct Curl_X509certificate cert;
  struct Curl_asn1Element dn;
  struct Curl_asn1Element elem;
  struct Curl_asn1Element ext;
  struct Curl_asn1Element name;
  const char *p;
  const char *q;
Changes to jni/curl/lib/x509asn1.h.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#ifndef HEADER_CURL_X509ASN1_H
#define HEADER_CURL_X509ASN1_H

/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2020, 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 https://curl.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










|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#ifndef HEADER_CURL_X509ASN1_H
#define HEADER_CURL_X509ASN1_H

/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2021, 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 https://curl.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
121
122
123
124
125
126
127
128
129
130
131
132
133

const char *Curl_getASN1Element(struct Curl_asn1Element *elem,
                                const char *beg, const char *end);
const char *Curl_ASN1tostr(struct Curl_asn1Element *elem, int type);
const char *Curl_DNtostr(struct Curl_asn1Element *dn);
int Curl_parseX509(struct Curl_X509certificate *cert,
                   const char *beg, const char *end);
CURLcode Curl_extract_certinfo(struct connectdata *conn, int certnum,
                               const char *beg, const char *end);
CURLcode Curl_verifyhost(struct connectdata *conn,
                         const char *beg, const char *end);
#endif /* USE_GSKIT or USE_NSS or USE_GNUTLS or USE_WOLFSSL or USE_SCHANNEL */
#endif /* HEADER_CURL_X509ASN1_H */







|

|



121
122
123
124
125
126
127
128
129
130
131
132
133

const char *Curl_getASN1Element(struct Curl_asn1Element *elem,
                                const char *beg, const char *end);
const char *Curl_ASN1tostr(struct Curl_asn1Element *elem, int type);
const char *Curl_DNtostr(struct Curl_asn1Element *dn);
int Curl_parseX509(struct Curl_X509certificate *cert,
                   const char *beg, const char *end);
CURLcode Curl_extract_certinfo(struct Curl_easy *data, int certnum,
                               const char *beg, const char *end);
CURLcode Curl_verifyhost(struct Curl_easy *data, struct connectdata *conn,
                         const char *beg, const char *end);
#endif /* USE_GSKIT or USE_NSS or USE_GNUTLS or USE_WOLFSSL or USE_SCHANNEL */
#endif /* HEADER_CURL_X509ASN1_H */
Changes to jni/curl/ltmain.sh.
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.


PROGRAM=libtool
PACKAGE=libtool
VERSION="2.4.6 Debian-2.4.6-14"
package_revision=2.4.6


## ------ ##
## Usage. ##
## ------ ##








|







27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.


PROGRAM=libtool
PACKAGE=libtool
VERSION="2.4.6 Debian-2.4.6-15"
package_revision=2.4.6


## ------ ##
## Usage. ##
## ------ ##

2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
include the following information:

       host-triplet:   $host
       shell:          $SHELL
       compiler:       $LTCC
       compiler flags: $LTCFLAGS
       linker:         $LD (gnu? $with_gnu_ld)
       version:        $progname $scriptversion Debian-2.4.6-14
       automake:       `($AUTOMAKE --version) 2>/dev/null |$SED 1q`
       autoconf:       `($AUTOCONF --version) 2>/dev/null |$SED 1q`

Report bugs to <bug-libtool@gnu.org>.
GNU libtool home page: <http://www.gnu.org/s/libtool/>.
General help using GNU software: <http://www.gnu.org/gethelp/>."
    exit 0







|







2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
include the following information:

       host-triplet:   $host
       shell:          $SHELL
       compiler:       $LTCC
       compiler flags: $LTCFLAGS
       linker:         $LD (gnu? $with_gnu_ld)
       version:        $progname $scriptversion Debian-2.4.6-15
       automake:       `($AUTOMAKE --version) 2>/dev/null |$SED 1q`
       autoconf:       `($AUTOCONF --version) 2>/dev/null |$SED 1q`

Report bugs to <bug-libtool@gnu.org>.
GNU libtool home page: <http://www.gnu.org/s/libtool/>.
General help using GNU software: <http://www.gnu.org/gethelp/>."
    exit 0
Changes to jni/curl/m4/curl-compilers.m4.
944
945
946
947
948
949
950

951
952
953
954
955
956
957
            if test "$compiler_num" -lt "400"; then
              tmp_CFLAGS="$tmp_CFLAGS -Wno-varargs"
            fi
          fi
          dnl clang 7 or later
          if test "$compiler_num" -ge "700"; then
            CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [assign-enum])

          fi
        fi
        ;;
        #
      DEC_C)
        #
        if test "$want_warnings" = "yes"; then







>







944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
            if test "$compiler_num" -lt "400"; then
              tmp_CFLAGS="$tmp_CFLAGS -Wno-varargs"
            fi
          fi
          dnl clang 7 or later
          if test "$compiler_num" -ge "700"; then
            CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [assign-enum])
            CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [extra-semi-stmt])
          fi
        fi
        ;;
        #
      DEC_C)
        #
        if test "$want_warnings" = "yes"; then
Changes to jni/curl/m4/libtool.m4.
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
    darwin1.*)
      _lt_dar_allow_undefined='$wl-flat_namespace $wl-undefined ${wl}suppress' ;;
    darwin*) # darwin 5.x on
      # if running on 10.5 or later, the deployment target defaults
      # to the OS version, if on x86, and 10.4, the deployment
      # target defaults to 10.4. Don't you love it?
      case ${MACOSX_DEPLOYMENT_TARGET-10.0},$host in
	10.0,*86*-darwin8*|10.0,*-darwin[[91]]*)
	  _lt_dar_allow_undefined='$wl-undefined ${wl}dynamic_lookup' ;;
	10.[[012]][[,.]]*)
	  _lt_dar_allow_undefined='$wl-flat_namespace $wl-undefined ${wl}suppress' ;;
	10.*)
	  _lt_dar_allow_undefined='$wl-undefined ${wl}dynamic_lookup' ;;
      esac
    ;;
  esac
    if test yes = "$lt_cv_apple_cc_single_mod"; then
      _lt_dar_single_mod='$single_module'
    fi







|



|







1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
    darwin1.*)
      _lt_dar_allow_undefined='$wl-flat_namespace $wl-undefined ${wl}suppress' ;;
    darwin*) # darwin 5.x on
      # if running on 10.5 or later, the deployment target defaults
      # to the OS version, if on x86, and 10.4, the deployment
      # target defaults to 10.4. Don't you love it?
      case ${MACOSX_DEPLOYMENT_TARGET-10.0},$host in
	10.0,*86*-darwin8*|10.0,*-darwin[[912]]*)
	  _lt_dar_allow_undefined='$wl-undefined ${wl}dynamic_lookup' ;;
	10.[[012]][[,.]]*)
	  _lt_dar_allow_undefined='$wl-flat_namespace $wl-undefined ${wl}suppress' ;;
	10.*|11.*)
	  _lt_dar_allow_undefined='$wl-undefined ${wl}dynamic_lookup' ;;
      esac
    ;;
  esac
    if test yes = "$lt_cv_apple_cc_single_mod"; then
      _lt_dar_single_mod='$single_module'
    fi
Changes to jni/curl/packages/DOS/README.
1
2
3
4


5
6
7
8
9
10
11




Gisle Vanem made curl build fine on DOS (and MingW) with djgpp, OpenSSL and his
Watt-32 stack.

'make djgpp' in the root curl dir should build it fine.



Note 1: djgpp 2.04 beta has a sscanf() bug so the URL parsing isn't
        done properly. Use djgpp 2.03 until they fix it.

Note 2: Compile Watt-32 (and OpenSSL) with the same version of djgpp.
        Otherwise things go wrong because things like FS-extensions and
        errnos have been changed between releases.







|
>
>







>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
Gisle Vanem made curl build fine on DOS (and MingW) with djgpp, OpenSSL and his
Watt-32 stack.

'make -f Makefile.dist djgpp' in the root curl dir should build it fine.
Or enter 'lib' and do a 'make -f Makefile.dj clean all' to first delete
'lib/curl_config.h' which is possibly from a previous incompatible Windows-build.

Note 1: djgpp 2.04 beta has a sscanf() bug so the URL parsing isn't
        done properly. Use djgpp 2.03 until they fix it.

Note 2: Compile Watt-32 (and OpenSSL) with the same version of djgpp.
        Otherwise things go wrong because things like FS-extensions and
        errnos have been changed between releases.
        
Note 3: Several 'USE_x' variables in 'common.dj' are on the 'USE_x ?= 0'
        form (conditional variable assignment). So one can build like this:
          c:\curl\lib> make -f makefile.dj USE_OPENSSL=1 USE_ZLIB=1 clean all
Changes to jni/curl/packages/DOS/common.dj.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
#***************************************************************************
#                                  _   _ ____  _
#  Project                     ___| | | |  _ \| |
#                             / __| | | | |_) | |
#                            | (__| |_| |  _ <| |___
#                             \___|\___/|_| \_\_____|
#
# Copyright (C) 1998 - 2020, 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 https://curl.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.
#
###########################################################################
#
# Common defines for curl (djgpp/Watt-32)
#
# Assumes you've unpacked curl with long-file names
# I.e use "set LFN=y" before untaring on Win9x/XP.
# Requires sed, yacc, rm and the usual stuff.
#
# Define TOPDIR before including this file.

.SUFFIXES: .exe .y

MAKEFILE = Makefile.dj
OBJ_DIR = djgpp

#
# Find out if using a Unix-like shell or a DOS command interpreter
#
ifneq ($(findstring COMMAND.COM,$(SHELL)),COMMAND.COM)







|


















|



<
<







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30


31
32
33
34
35
36
37
#***************************************************************************
#                                  _   _ ____  _
#  Project                     ___| | | |  _ \| |
#                             / __| | | | |_) | |
#                            | (__| |_| |  _ <| |___
#                             \___|\___/|_| \_\_____|
#
# Copyright (C) 1998 - 2021, 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 https://curl.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.
#
###########################################################################
#
# Common defines for curl (djgpp/Watt-32)
#
# Assumes you've unpacked curl with long-file names
# I.e use "set LFN=y" before untaring on Win9x/XP.
# Requires sed, rm and the usual stuff.
#
# Define TOPDIR before including this file.



MAKEFILE = Makefile.dj
OBJ_DIR = djgpp

#
# Find out if using a Unix-like shell or a DOS command interpreter
#
ifneq ($(findstring COMMAND.COM,$(SHELL)),COMMAND.COM)
57
58
59
60
61
62
63















64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99





100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120























121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
  COPY   = copy
  DELETE = del
  MKDIR  = mkdir
  RMDIR  = rmdir
  DS     = \$(NOTHING)
endif
















#
# OpenSSL is available from www.openssl.org and builds okay
# with djgpp/Watt-32. Set to 0 if you don't need https URLs
# (reduces curl.exe with approx 700 kB)
#
USE_SSL = 0

#
# Use zlib for contents encoding
#
USE_ZLIB = 0

#
# Use libidn for international domain names
#
USE_IDNA = 0

#
# Use Watt-32 IPv6 stack (only IPv6 name resolution working at the moment)
#
USE_IPV6 = 0

#
# Use C-Ares resolver library
#
USE_ARES = 0

#
# Enable debug code in libcurl/curl
#
USE_DEBUG = 0

#
# Enable memory tracking code in libcurl/curl
#
USE_CURLDEBUG = 0






default: all

#
# Root directory for Waterloo tcp/ip etc. Change to suite.
# WATT_ROOT should be set during Watt-32 install.
#
WATT32_ROOT  = $(subst \,/,$(WATT_ROOT))
OPENSSL_ROOT = e:/net/openssl.099
ZLIB_ROOT    = $(DJDIR)/contrib/zlib
LIBIDN_ROOT  = $(TOPDIR)/../IDN/libidn
ARES_ROOT    = $(TOPDIR)/ares

CC   = gcc
YACC = bison -y

CFLAGS = -g -O2 -I. -I$(TOPDIR)/include -I$(TOPDIR)/lib \
         -I$(WATT32_ROOT)/inc -Wall -DHAVE_CONFIG_H

ifeq ($(USE_SSL),1)
  CFLAGS += -DUSE_OPENSSL -I$(OPENSSL_ROOT)























endif

ifeq ($(USE_ZLIB),1)
  CFLAGS += -DUSE_ZLIB -I$(ZLIB_ROOT)
endif

ifeq ($(USE_IPV6),1)
  CFLAGS += -DENABLE_IPV6
endif

ifeq ($(USE_ARES),1)
  CFLAGS += -DUSE_ARES -I$(ARES_ROOT)
endif

ifeq ($(USE_IDNA),1)
  CFLAGS += -DHAVE_LIBIDN -DHAVE_IDN_FREE_H -DHAVE_IDN_FREE -DHAVE_TLD_H \
            -DHAVE_TLD_STRERROR -I$(LIBIDN_ROOT)/lib
endif








>
>
>
>
>
>
>
>
>
>
>
>
>
>
>





|


|

|




|




|




|




|




|
>
>
>
>
>







|
|
|
|
|

<
<
<



|
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>











|







55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130



131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
  COPY   = copy
  DELETE = del
  MKDIR  = mkdir
  RMDIR  = rmdir
  DS     = \$(NOTHING)
endif

ifeq ($(OS),Windows_NT)
  #
  # Windows hosted djgpp cross compiler. Get it from:
  #   https://github.com/andrewwutw/build-djgpp/releases
  #
  DJ_PREFIX ?= c:/some-path/djgpp/bin/i586-pc-msdosdjgpp-
  CC = $(DJ_PREFIX)gcc

else
  #
  # The normal djgpp 'gcc' for MSDOS.
  #
  CC = gcc
endif

#
# OpenSSL is available from www.openssl.org and builds okay
# with djgpp/Watt-32. Set to 0 if you don't need https URLs
# (reduces curl.exe with approx 700 kB)
#
USE_OPENSSL ?= 0

#
# Use zlib for contents encoding. Needed for 'USE_OPENSSL=1' too.
#
USE_ZLIB ?= 0

#
# Use libidn for international domain names
#
USE_IDNA ?= 0

#
# Use Watt-32 IPv6 stack (only IPv6 name resolution working at the moment)
#
USE_IPV6 ?= 0

#
# Use C-Ares resolver library
#
USE_ARES ?= 0

#
# Enable debug code in libcurl/curl
#
USE_DEBUG ?= 0

#
# Enable memory tracking code in libcurl/curl
#
USE_CURLDEBUG ?= 0

#
# Generate a .map file in 'link_EXE' macro
#
MAKE_MAP_FILE ?= 0

default: all

#
# Root directory for Waterloo tcp/ip etc. Change to suite.
# WATT_ROOT should be set during Watt-32 install.
#
WATT32_ROOT   = $(realpath $(WATT_ROOT))
OPENSSL_ROOT ?= $(TOPDIR)/../crypto/OpenSSL
ZLIB_ROOT    ?= e:/djgpp/contrib/zlib
LIBIDN_ROOT  ?= $(TOPDIR)/../IDN/libidn
ARES_ROOT    ?= $(TOPDIR)/../DNS/c-ares




CFLAGS = -g -O2 -I. -I$(TOPDIR)/include -I$(TOPDIR)/lib \
         -I$(WATT32_ROOT)/inc -Wall -DHAVE_CONFIG_H

ifeq ($(USE_OPENSSL),1)
  CFLAGS += -DUSE_OPENSSL -I$(OPENSSL_ROOT)/include

  #
  # Squelch the warnings on deprecated functions.
  #
  CFLAGS += -DOPENSSL_SUPPRESS_DEPRECATED

  #
  # Use some of these too?
  #
  # CFLAGS += -DUSE_TLS_SRP=1                    \
  #           -DHAVE_ENGINE_LOAD_BUILTIN_ENGINES \
  #           -DHAVE_OPENSSL_PKCS12_H            \
  #           -DHAVE_SSLV2_CLIENT_METHOD         \
  #           -DOPENSSL_NO_DEPRECATED

  #
  # 'libcomm.a' is normally 'libcommon.a'. But to keep it 8+3 clean, it's
  # shortened to 'libcomm.a'. The official OpenSSL build was recently changed
  # and this "Common" library was added for several of the Crypto Providers.
  #
  OPENSSL_LIBS = $(OPENSSL_ROOT)/lib/libssl.a   \
                 $(OPENSSL_ROOT)/lib/libcrypt.a \
                 $(OPENSSL_ROOT)/lib/libcomm.a
endif

ifeq ($(USE_ZLIB),1)
  CFLAGS += -DUSE_ZLIB -I$(ZLIB_ROOT)
endif

ifeq ($(USE_IPV6),1)
  CFLAGS += -DENABLE_IPV6
endif

ifeq ($(USE_ARES),1)
  CFLAGS += -DUSE_ARES -I$(ARES_ROOT)/include
endif

ifeq ($(USE_IDNA),1)
  CFLAGS += -DHAVE_LIBIDN -DHAVE_IDN_FREE_H -DHAVE_IDN_FREE -DHAVE_TLD_H \
            -DHAVE_TLD_STRERROR -I$(LIBIDN_ROOT)/lib
endif

148
149
150
151
152
153
154





























155
156
157
$(OBJ_DIR):
	$(MKDIR) $(OBJ_DIR)

$(OBJ_DIR)/%.o: %.c
	$(CC) $(CFLAGS) -o $@ -c $<
	@echo






























depend: $(DEPEND_PREREQ) $(MAKEFILE)
	$(CC) -MM $(CFLAGS) $(CSOURCES) | \
	sed -e 's/^\([a-zA-Z0-9_-]*\.o:\)/$$(OBJ_DIR)\/\1/' > depend.dj







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

|
<
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223

$(OBJ_DIR):
	$(MKDIR) $(OBJ_DIR)

$(OBJ_DIR)/%.o: %.c
	$(CC) $(CFLAGS) -o $@ -c $<
	@echo

#
# Link-EXE macro:
#   $(1): the .exe
#   $(2): the .o-files and libraries
#
ifeq ($(MAKE_MAP_FILE),1)
  define link_EXE
    $(CC) -o $(1) $(LDFLAGS) -Wl,--print-map,--sort-common $(2) > $(1:.exe=.map)
  endef
else
  define link_EXE
    $(CC) $(LDFLAGS) -o $(1) $(2)
  endef
endif

$(TOPDIR)/docs/curl.1: $(wildcard $(TOPDIR)/docs/cmdline-opts/*.d)
	cd $(TOPDIR)/docs/cmdline-opts; \
	perl gen.pl mainpage > ../$(TOPDIR)/docs/curl.1

DEP_REPLACE = sed -e 's@\(.*\)\.o: @\n$$(OBJ_DIR)\/\1.o: @' \
                  -e 's@$(ARES_ROOT)@$$(ARES_ROOT)@g'       \
                  -e 's@$(OPENSSL_ROOT)@$$(OPENSSL_ROOT)@g' \
                  -e 's@$(WATT32_ROOT)@$$(WATT32_ROOT)@g'   \
                  -e 's@$(ZLIB_ROOT)@$$(ZLIB_ROOT)@g'

#
# One may have to do 'make -f Makefile.dj clean' first in case
# a foreign 'curl_config.h' is making trouble.
#
depend: $(DEPEND_PREREQ) $(MAKEFILE)
	$(CC) -MM $(CFLAGS) $(CSOURCES) | $(DEP_REPLACE) > depend.dj

Changes to jni/curl/packages/Makefile.in.
323
324
325
326
327
328
329

330
331
332
333
334
335
336
STRIP = @STRIP@
SUPPORT_FEATURES = @SUPPORT_FEATURES@
SUPPORT_PROTOCOLS = @SUPPORT_PROTOCOLS@
USE_ARES = @USE_ARES@
USE_BEARSSL = @USE_BEARSSL@
USE_GNUTLS = @USE_GNUTLS@
USE_GNUTLS_NETTLE = @USE_GNUTLS_NETTLE@

USE_LIBRTMP = @USE_LIBRTMP@
USE_LIBSSH = @USE_LIBSSH@
USE_LIBSSH2 = @USE_LIBSSH2@
USE_MBEDTLS = @USE_MBEDTLS@
USE_MESALINK = @USE_MESALINK@
USE_NGHTTP2 = @USE_NGHTTP2@
USE_NGHTTP3 = @USE_NGHTTP3@







>







323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
STRIP = @STRIP@
SUPPORT_FEATURES = @SUPPORT_FEATURES@
SUPPORT_PROTOCOLS = @SUPPORT_PROTOCOLS@
USE_ARES = @USE_ARES@
USE_BEARSSL = @USE_BEARSSL@
USE_GNUTLS = @USE_GNUTLS@
USE_GNUTLS_NETTLE = @USE_GNUTLS_NETTLE@
USE_HYPER = @USE_HYPER@
USE_LIBRTMP = @USE_LIBRTMP@
USE_LIBSSH = @USE_LIBSSH@
USE_LIBSSH2 = @USE_LIBSSH2@
USE_MBEDTLS = @USE_MBEDTLS@
USE_MESALINK = @USE_MESALINK@
USE_NGHTTP2 = @USE_NGHTTP2@
USE_NGHTTP3 = @USE_NGHTTP3@
Changes to jni/curl/packages/OS400/ccsidcurl.c.
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
Curl_formget_callback_ccsid(void *arg, const char *buf, size_t len)
{
  struct cfcdata *p;
  char *b;
  int l;
  size_t ret;

  p = (cfcdata *) arg;

  if((long) len <= 0)
    return (*p->append)(p->arg, buf, len);

  b = malloc(MAX_CONV_EXPANSION * len);

  if(!b)







|







1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
Curl_formget_callback_ccsid(void *arg, const char *buf, size_t len)
{
  struct cfcdata *p;
  char *b;
  int l;
  size_t ret;

  p = (struct cfcdata *) arg;

  if((long) len <= 0)
    return (*p->append)(p->arg, buf, len);

  b = malloc(MAX_CONV_EXPANSION * len);

  if(!b)
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
}


int
curl_formget_ccsid(struct curl_httppost *form, void *arg,
                   curl_formget_callback append, unsigned int ccsid)
{
  cfcdata lcfc;

  lcfc.append = append;
  lcfc.arg = arg;
  lcfc.ccsid = ccsid;
  return curl_formget(form, (void *) &lcfc, Curl_formget_callback_ccsid);
}








|







1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
}


int
curl_formget_ccsid(struct curl_httppost *form, void *arg,
                   curl_formget_callback append, unsigned int ccsid)
{
  struct cfcdata lcfc;

  lcfc.append = append;
  lcfc.arg = arg;
  lcfc.ccsid = ccsid;
  return curl_formget(form, (void *) &lcfc, Curl_formget_callback_ccsid);
}

Changes to jni/curl/packages/vms/Makefile.in.
263
264
265
266
267
268
269

270
271
272
273
274
275
276
STRIP = @STRIP@
SUPPORT_FEATURES = @SUPPORT_FEATURES@
SUPPORT_PROTOCOLS = @SUPPORT_PROTOCOLS@
USE_ARES = @USE_ARES@
USE_BEARSSL = @USE_BEARSSL@
USE_GNUTLS = @USE_GNUTLS@
USE_GNUTLS_NETTLE = @USE_GNUTLS_NETTLE@

USE_LIBRTMP = @USE_LIBRTMP@
USE_LIBSSH = @USE_LIBSSH@
USE_LIBSSH2 = @USE_LIBSSH2@
USE_MBEDTLS = @USE_MBEDTLS@
USE_MESALINK = @USE_MESALINK@
USE_NGHTTP2 = @USE_NGHTTP2@
USE_NGHTTP3 = @USE_NGHTTP3@







>







263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
STRIP = @STRIP@
SUPPORT_FEATURES = @SUPPORT_FEATURES@
SUPPORT_PROTOCOLS = @SUPPORT_PROTOCOLS@
USE_ARES = @USE_ARES@
USE_BEARSSL = @USE_BEARSSL@
USE_GNUTLS = @USE_GNUTLS@
USE_GNUTLS_NETTLE = @USE_GNUTLS_NETTLE@
USE_HYPER = @USE_HYPER@
USE_LIBRTMP = @USE_LIBRTMP@
USE_LIBSSH = @USE_LIBSSH@
USE_LIBSSH2 = @USE_LIBSSH2@
USE_MBEDTLS = @USE_MBEDTLS@
USE_MESALINK = @USE_MESALINK@
USE_NGHTTP2 = @USE_NGHTTP2@
USE_NGHTTP3 = @USE_NGHTTP3@
Changes to jni/curl/packages/vms/config_h.com.
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
$write tf "#endif"
$write tf "#endif"
$write tf ""
$!
$write tf " /* Allow compiler builtins */"
$write tf "/*-------------------------*/"
$write tf "#ifdef __DECC_VER"
$write tf "#include <non_existant_dir:builtins.h>"
$write tf "#endif"
$!
$write tf ""
$return
$!
$! gosub to write out the tail for config.h and close it
$!---------------------------------------------------------







|







2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
$write tf "#endif"
$write tf "#endif"
$write tf ""
$!
$write tf " /* Allow compiler builtins */"
$write tf "/*-------------------------*/"
$write tf "#ifdef __DECC_VER"
$write tf "#include <non_existent_dir:builtins.h>"
$write tf "#endif"
$!
$write tf ""
$return
$!
$! gosub to write out the tail for config.h and close it
$!---------------------------------------------------------
Changes to jni/curl/packages/vms/readme.
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
The (brute-force) DCL based builder is [.packages.vms]build_vms.com.
Comments in this procedure describe various optional parameters which
enable or disable optional program features, or which control the build
in other ways.  Product files (.EXE, .H, .LIS, .MAP, .OBJ, .OLB, ...)
should be produced in an architecture-specific subdirectory under this
directory ([.ALPHA], [.IA64], [.VAX]).

The file curl_gnv_build_steps.txt contains information on buildling using
the GNV tool kit, building a shared libcurl, and producting a PCSI kit for
distribution.  The curl_gnv_build_steps.text is included in the release
notes file of the PCSI kit.

The building with 64 bit pointers does not currently work.

The build procedure will detect if HP OpenSSL, LDAP, and Kerberos are
installed and default to building with them.







|
|







164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
The (brute-force) DCL based builder is [.packages.vms]build_vms.com.
Comments in this procedure describe various optional parameters which
enable or disable optional program features, or which control the build
in other ways.  Product files (.EXE, .H, .LIS, .MAP, .OBJ, .OLB, ...)
should be produced in an architecture-specific subdirectory under this
directory ([.ALPHA], [.IA64], [.VAX]).

The file curl_gnv_build_steps.txt contains information on building using
the GNV tool kit, building a shared libcurl, and producing a PCSI kit for
distribution.  The curl_gnv_build_steps.text is included in the release
notes file of the PCSI kit.

The building with 64 bit pointers does not currently work.

The build procedure will detect if HP OpenSSL, LDAP, and Kerberos are
installed and default to building with them.
Changes to jni/curl/projects/Windows/VC10/lib/libcurl.vcxproj.
2324
2325
2326
2327
2328
2329
2330

2331
2332
2333
2334
2335
2336
2337
  </ItemDefinitionGroup>
  <ItemGroup>
    <ClCompile Include="..\..\..\..\lib\altsvc.c" />
    <ClCompile Include="..\..\..\..\lib\amigaos.c" />
    <ClCompile Include="..\..\..\..\lib\asyn-ares.c" />
    <ClCompile Include="..\..\..\..\lib\asyn-thread.c" />
    <ClCompile Include="..\..\..\..\lib\base64.c" />

    <ClCompile Include="..\..\..\..\lib\conncache.c" />
    <ClCompile Include="..\..\..\..\lib\connect.c" />
    <ClCompile Include="..\..\..\..\lib\content_encoding.c" />
    <ClCompile Include="..\..\..\..\lib\cookie.c" />
    <ClCompile Include="..\..\..\..\lib\curl_addrinfo.c" />
    <ClCompile Include="..\..\..\..\lib\curl_ctype.c" />
    <ClCompile Include="..\..\..\..\lib\curl_des.c" />







>







2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
  </ItemDefinitionGroup>
  <ItemGroup>
    <ClCompile Include="..\..\..\..\lib\altsvc.c" />
    <ClCompile Include="..\..\..\..\lib\amigaos.c" />
    <ClCompile Include="..\..\..\..\lib\asyn-ares.c" />
    <ClCompile Include="..\..\..\..\lib\asyn-thread.c" />
    <ClCompile Include="..\..\..\..\lib\base64.c" />
    <ClCompile Include="..\..\..\..\lib\c-hyper.c" />
    <ClCompile Include="..\..\..\..\lib\conncache.c" />
    <ClCompile Include="..\..\..\..\lib\connect.c" />
    <ClCompile Include="..\..\..\..\lib\content_encoding.c" />
    <ClCompile Include="..\..\..\..\lib\cookie.c" />
    <ClCompile Include="..\..\..\..\lib\curl_addrinfo.c" />
    <ClCompile Include="..\..\..\..\lib\curl_ctype.c" />
    <ClCompile Include="..\..\..\..\lib\curl_des.c" />
2372
2373
2374
2375
2376
2377
2378

2379
2380
2381
2382
2383
2384
2385
    <ClCompile Include="..\..\..\..\lib\hostcheck.c" />
    <ClCompile Include="..\..\..\..\lib\hostip4.c" />
    <ClCompile Include="..\..\..\..\lib\hostip6.c" />
    <ClCompile Include="..\..\..\..\lib\hostip.c" />
    <ClCompile Include="..\..\..\..\lib\hostsyn.c" />
    <ClCompile Include="..\..\..\..\lib\hsts.c" />
    <ClCompile Include="..\..\..\..\lib\http2.c" />

    <ClCompile Include="..\..\..\..\lib\http.c" />
    <ClCompile Include="..\..\..\..\lib\http_chunks.c" />
    <ClCompile Include="..\..\..\..\lib\http_digest.c" />
    <ClCompile Include="..\..\..\..\lib\http_negotiate.c" />
    <ClCompile Include="..\..\..\..\lib\http_ntlm.c" />
    <ClCompile Include="..\..\..\..\lib\http_proxy.c" />
    <ClCompile Include="..\..\..\..\lib\idn_win32.c" />







>







2373
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
2384
2385
2386
2387
    <ClCompile Include="..\..\..\..\lib\hostcheck.c" />
    <ClCompile Include="..\..\..\..\lib\hostip4.c" />
    <ClCompile Include="..\..\..\..\lib\hostip6.c" />
    <ClCompile Include="..\..\..\..\lib\hostip.c" />
    <ClCompile Include="..\..\..\..\lib\hostsyn.c" />
    <ClCompile Include="..\..\..\..\lib\hsts.c" />
    <ClCompile Include="..\..\..\..\lib\http2.c" />
    <ClCompile Include="..\..\..\..\lib\http_aws_sigv4.c" />
    <ClCompile Include="..\..\..\..\lib\http.c" />
    <ClCompile Include="..\..\..\..\lib\http_chunks.c" />
    <ClCompile Include="..\..\..\..\lib\http_digest.c" />
    <ClCompile Include="..\..\..\..\lib\http_negotiate.c" />
    <ClCompile Include="..\..\..\..\lib\http_ntlm.c" />
    <ClCompile Include="..\..\..\..\lib\http_proxy.c" />
    <ClCompile Include="..\..\..\..\lib\idn_win32.c" />
2474
2475
2476
2477
2478
2479
2480

2481
2482
2483
2484
2485
2486
2487
    <ClCompile Include="..\..\..\..\lib\vtls\wolfssl.c" />
  </ItemGroup>
  <ItemGroup>
    <ClInclude Include="..\..\..\..\lib\altsvc.h" />
    <ClInclude Include="..\..\..\..\lib\amigaos.h" />
    <ClInclude Include="..\..\..\..\lib\arpa_telnet.h" />
    <ClInclude Include="..\..\..\..\lib\asyn.h" />

    <ClInclude Include="..\..\..\..\lib\config-win32.h" />
    <ClInclude Include="..\..\..\..\lib\conncache.h" />
    <ClInclude Include="..\..\..\..\lib\connect.h" />
    <ClInclude Include="..\..\..\..\lib\content_encoding.h" />
    <ClInclude Include="..\..\..\..\lib\cookie.h" />
    <ClInclude Include="..\..\..\..\lib\curl_addrinfo.h" />
    <ClInclude Include="..\..\..\..\lib\curl_base64.h" />







>







2476
2477
2478
2479
2480
2481
2482
2483
2484
2485
2486
2487
2488
2489
2490
    <ClCompile Include="..\..\..\..\lib\vtls\wolfssl.c" />
  </ItemGroup>
  <ItemGroup>
    <ClInclude Include="..\..\..\..\lib\altsvc.h" />
    <ClInclude Include="..\..\..\..\lib\amigaos.h" />
    <ClInclude Include="..\..\..\..\lib\arpa_telnet.h" />
    <ClInclude Include="..\..\..\..\lib\asyn.h" />
    <ClInclude Include="..\..\..\..\lib\c-hyper.h" />
    <ClInclude Include="..\..\..\..\lib\config-win32.h" />
    <ClInclude Include="..\..\..\..\lib\conncache.h" />
    <ClInclude Include="..\..\..\..\lib\connect.h" />
    <ClInclude Include="..\..\..\..\lib\content_encoding.h" />
    <ClInclude Include="..\..\..\..\lib\cookie.h" />
    <ClInclude Include="..\..\..\..\lib\curl_addrinfo.h" />
    <ClInclude Include="..\..\..\..\lib\curl_base64.h" />
2528
2529
2530
2531
2532
2533
2534

2535
2536
2537
2538
2539
2540
2541
    <ClInclude Include="..\..\..\..\lib\getinfo.h" />
    <ClInclude Include="..\..\..\..\lib\gopher.h" />
    <ClInclude Include="..\..\..\..\lib\hash.h" />
    <ClInclude Include="..\..\..\..\lib\hostcheck.h" />
    <ClInclude Include="..\..\..\..\lib\hostip.h" />
    <ClInclude Include="..\..\..\..\lib\hsts.h" />
    <ClInclude Include="..\..\..\..\lib\http2.h" />

    <ClInclude Include="..\..\..\..\lib\http_chunks.h" />
    <ClInclude Include="..\..\..\..\lib\http_digest.h" />
    <ClInclude Include="..\..\..\..\lib\http.h" />
    <ClInclude Include="..\..\..\..\lib\http_negotiate.h" />
    <ClInclude Include="..\..\..\..\lib\http_ntlm.h" />
    <ClInclude Include="..\..\..\..\lib\http_proxy.h" />
    <ClInclude Include="..\..\..\..\lib\if2ip.h" />







>







2531
2532
2533
2534
2535
2536
2537
2538
2539
2540
2541
2542
2543
2544
2545
    <ClInclude Include="..\..\..\..\lib\getinfo.h" />
    <ClInclude Include="..\..\..\..\lib\gopher.h" />
    <ClInclude Include="..\..\..\..\lib\hash.h" />
    <ClInclude Include="..\..\..\..\lib\hostcheck.h" />
    <ClInclude Include="..\..\..\..\lib\hostip.h" />
    <ClInclude Include="..\..\..\..\lib\hsts.h" />
    <ClInclude Include="..\..\..\..\lib\http2.h" />
    <ClInclude Include="..\..\..\..\lib\http_aws_sigv4.h" />
    <ClInclude Include="..\..\..\..\lib\http_chunks.h" />
    <ClInclude Include="..\..\..\..\lib\http_digest.h" />
    <ClInclude Include="..\..\..\..\lib\http.h" />
    <ClInclude Include="..\..\..\..\lib\http_negotiate.h" />
    <ClInclude Include="..\..\..\..\lib\http_ntlm.h" />
    <ClInclude Include="..\..\..\..\lib\http_proxy.h" />
    <ClInclude Include="..\..\..\..\lib\if2ip.h" />
Changes to jni/curl/projects/Windows/VC11/lib/libcurl.vcxproj.
2380
2381
2382
2383
2384
2385
2386

2387
2388
2389
2390
2391
2392
2393
  </ItemDefinitionGroup>
  <ItemGroup>
    <ClCompile Include="..\..\..\..\lib\altsvc.c" />
    <ClCompile Include="..\..\..\..\lib\amigaos.c" />
    <ClCompile Include="..\..\..\..\lib\asyn-ares.c" />
    <ClCompile Include="..\..\..\..\lib\asyn-thread.c" />
    <ClCompile Include="..\..\..\..\lib\base64.c" />

    <ClCompile Include="..\..\..\..\lib\conncache.c" />
    <ClCompile Include="..\..\..\..\lib\connect.c" />
    <ClCompile Include="..\..\..\..\lib\content_encoding.c" />
    <ClCompile Include="..\..\..\..\lib\cookie.c" />
    <ClCompile Include="..\..\..\..\lib\curl_addrinfo.c" />
    <ClCompile Include="..\..\..\..\lib\curl_ctype.c" />
    <ClCompile Include="..\..\..\..\lib\curl_des.c" />







>







2380
2381
2382
2383
2384
2385
2386
2387
2388
2389
2390
2391
2392
2393
2394
  </ItemDefinitionGroup>
  <ItemGroup>
    <ClCompile Include="..\..\..\..\lib\altsvc.c" />
    <ClCompile Include="..\..\..\..\lib\amigaos.c" />
    <ClCompile Include="..\..\..\..\lib\asyn-ares.c" />
    <ClCompile Include="..\..\..\..\lib\asyn-thread.c" />
    <ClCompile Include="..\..\..\..\lib\base64.c" />
    <ClCompile Include="..\..\..\..\lib\c-hyper.c" />
    <ClCompile Include="..\..\..\..\lib\conncache.c" />
    <ClCompile Include="..\..\..\..\lib\connect.c" />
    <ClCompile Include="..\..\..\..\lib\content_encoding.c" />
    <ClCompile Include="..\..\..\..\lib\cookie.c" />
    <ClCompile Include="..\..\..\..\lib\curl_addrinfo.c" />
    <ClCompile Include="..\..\..\..\lib\curl_ctype.c" />
    <ClCompile Include="..\..\..\..\lib\curl_des.c" />
2428
2429
2430
2431
2432
2433
2434

2435
2436
2437
2438
2439
2440
2441
    <ClCompile Include="..\..\..\..\lib\hostcheck.c" />
    <ClCompile Include="..\..\..\..\lib\hostip4.c" />
    <ClCompile Include="..\..\..\..\lib\hostip6.c" />
    <ClCompile Include="..\..\..\..\lib\hostip.c" />
    <ClCompile Include="..\..\..\..\lib\hostsyn.c" />
    <ClCompile Include="..\..\..\..\lib\hsts.c" />
    <ClCompile Include="..\..\..\..\lib\http2.c" />

    <ClCompile Include="..\..\..\..\lib\http.c" />
    <ClCompile Include="..\..\..\..\lib\http_chunks.c" />
    <ClCompile Include="..\..\..\..\lib\http_digest.c" />
    <ClCompile Include="..\..\..\..\lib\http_negotiate.c" />
    <ClCompile Include="..\..\..\..\lib\http_ntlm.c" />
    <ClCompile Include="..\..\..\..\lib\http_proxy.c" />
    <ClCompile Include="..\..\..\..\lib\idn_win32.c" />







>







2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
    <ClCompile Include="..\..\..\..\lib\hostcheck.c" />
    <ClCompile Include="..\..\..\..\lib\hostip4.c" />
    <ClCompile Include="..\..\..\..\lib\hostip6.c" />
    <ClCompile Include="..\..\..\..\lib\hostip.c" />
    <ClCompile Include="..\..\..\..\lib\hostsyn.c" />
    <ClCompile Include="..\..\..\..\lib\hsts.c" />
    <ClCompile Include="..\..\..\..\lib\http2.c" />
    <ClCompile Include="..\..\..\..\lib\http_aws_sigv4.c" />
    <ClCompile Include="..\..\..\..\lib\http.c" />
    <ClCompile Include="..\..\..\..\lib\http_chunks.c" />
    <ClCompile Include="..\..\..\..\lib\http_digest.c" />
    <ClCompile Include="..\..\..\..\lib\http_negotiate.c" />
    <ClCompile Include="..\..\..\..\lib\http_ntlm.c" />
    <ClCompile Include="..\..\..\..\lib\http_proxy.c" />
    <ClCompile Include="..\..\..\..\lib\idn_win32.c" />
2530
2531
2532
2533
2534
2535
2536

2537
2538
2539
2540
2541
2542
2543
    <ClCompile Include="..\..\..\..\lib\vtls\wolfssl.c" />
  </ItemGroup>
  <ItemGroup>
    <ClInclude Include="..\..\..\..\lib\altsvc.h" />
    <ClInclude Include="..\..\..\..\lib\amigaos.h" />
    <ClInclude Include="..\..\..\..\lib\arpa_telnet.h" />
    <ClInclude Include="..\..\..\..\lib\asyn.h" />

    <ClInclude Include="..\..\..\..\lib\config-win32.h" />
    <ClInclude Include="..\..\..\..\lib\conncache.h" />
    <ClInclude Include="..\..\..\..\lib\connect.h" />
    <ClInclude Include="..\..\..\..\lib\content_encoding.h" />
    <ClInclude Include="..\..\..\..\lib\cookie.h" />
    <ClInclude Include="..\..\..\..\lib\curl_addrinfo.h" />
    <ClInclude Include="..\..\..\..\lib\curl_base64.h" />







>







2532
2533
2534
2535
2536
2537
2538
2539
2540
2541
2542
2543
2544
2545
2546
    <ClCompile Include="..\..\..\..\lib\vtls\wolfssl.c" />
  </ItemGroup>
  <ItemGroup>
    <ClInclude Include="..\..\..\..\lib\altsvc.h" />
    <ClInclude Include="..\..\..\..\lib\amigaos.h" />
    <ClInclude Include="..\..\..\..\lib\arpa_telnet.h" />
    <ClInclude Include="..\..\..\..\lib\asyn.h" />
    <ClInclude Include="..\..\..\..\lib\c-hyper.h" />
    <ClInclude Include="..\..\..\..\lib\config-win32.h" />
    <ClInclude Include="..\..\..\..\lib\conncache.h" />
    <ClInclude Include="..\..\..\..\lib\connect.h" />
    <ClInclude Include="..\..\..\..\lib\content_encoding.h" />
    <ClInclude Include="..\..\..\..\lib\cookie.h" />
    <ClInclude Include="..\..\..\..\lib\curl_addrinfo.h" />
    <ClInclude Include="..\..\..\..\lib\curl_base64.h" />
2584
2585
2586
2587
2588
2589
2590

2591
2592
2593
2594
2595
2596
2597
    <ClInclude Include="..\..\..\..\lib\getinfo.h" />
    <ClInclude Include="..\..\..\..\lib\gopher.h" />
    <ClInclude Include="..\..\..\..\lib\hash.h" />
    <ClInclude Include="..\..\..\..\lib\hostcheck.h" />
    <ClInclude Include="..\..\..\..\lib\hostip.h" />
    <ClInclude Include="..\..\..\..\lib\hsts.h" />
    <ClInclude Include="..\..\..\..\lib\http2.h" />

    <ClInclude Include="..\..\..\..\lib\http_chunks.h" />
    <ClInclude Include="..\..\..\..\lib\http_digest.h" />
    <ClInclude Include="..\..\..\..\lib\http.h" />
    <ClInclude Include="..\..\..\..\lib\http_negotiate.h" />
    <ClInclude Include="..\..\..\..\lib\http_ntlm.h" />
    <ClInclude Include="..\..\..\..\lib\http_proxy.h" />
    <ClInclude Include="..\..\..\..\lib\if2ip.h" />







>







2587
2588
2589
2590
2591
2592
2593
2594
2595
2596
2597
2598
2599
2600
2601
    <ClInclude Include="..\..\..\..\lib\getinfo.h" />
    <ClInclude Include="..\..\..\..\lib\gopher.h" />
    <ClInclude Include="..\..\..\..\lib\hash.h" />
    <ClInclude Include="..\..\..\..\lib\hostcheck.h" />
    <ClInclude Include="..\..\..\..\lib\hostip.h" />
    <ClInclude Include="..\..\..\..\lib\hsts.h" />
    <ClInclude Include="..\..\..\..\lib\http2.h" />
    <ClInclude Include="..\..\..\..\lib\http_aws_sigv4.h" />
    <ClInclude Include="..\..\..\..\lib\http_chunks.h" />
    <ClInclude Include="..\..\..\..\lib\http_digest.h" />
    <ClInclude Include="..\..\..\..\lib\http.h" />
    <ClInclude Include="..\..\..\..\lib\http_negotiate.h" />
    <ClInclude Include="..\..\..\..\lib\http_ntlm.h" />
    <ClInclude Include="..\..\..\..\lib\http_proxy.h" />
    <ClInclude Include="..\..\..\..\lib\if2ip.h" />
Changes to jni/curl/projects/Windows/VC12/lib/libcurl.vcxproj.
2380
2381
2382
2383
2384
2385
2386

2387
2388
2389
2390
2391
2392
2393
  </ItemDefinitionGroup>
  <ItemGroup>
    <ClCompile Include="..\..\..\..\lib\altsvc.c" />
    <ClCompile Include="..\..\..\..\lib\amigaos.c" />
    <ClCompile Include="..\..\..\..\lib\asyn-ares.c" />
    <ClCompile Include="..\..\..\..\lib\asyn-thread.c" />
    <ClCompile Include="..\..\..\..\lib\base64.c" />

    <ClCompile Include="..\..\..\..\lib\conncache.c" />
    <ClCompile Include="..\..\..\..\lib\connect.c" />
    <ClCompile Include="..\..\..\..\lib\content_encoding.c" />
    <ClCompile Include="..\..\..\..\lib\cookie.c" />
    <ClCompile Include="..\..\..\..\lib\curl_addrinfo.c" />
    <ClCompile Include="..\..\..\..\lib\curl_ctype.c" />
    <ClCompile Include="..\..\..\..\lib\curl_des.c" />







>







2380
2381
2382
2383
2384
2385
2386
2387
2388
2389
2390
2391
2392
2393
2394
  </ItemDefinitionGroup>
  <ItemGroup>
    <ClCompile Include="..\..\..\..\lib\altsvc.c" />
    <ClCompile Include="..\..\..\..\lib\amigaos.c" />
    <ClCompile Include="..\..\..\..\lib\asyn-ares.c" />
    <ClCompile Include="..\..\..\..\lib\asyn-thread.c" />
    <ClCompile Include="..\..\..\..\lib\base64.c" />
    <ClCompile Include="..\..\..\..\lib\c-hyper.c" />
    <ClCompile Include="..\..\..\..\lib\conncache.c" />
    <ClCompile Include="..\..\..\..\lib\connect.c" />
    <ClCompile Include="..\..\..\..\lib\content_encoding.c" />
    <ClCompile Include="..\..\..\..\lib\cookie.c" />
    <ClCompile Include="..\..\..\..\lib\curl_addrinfo.c" />
    <ClCompile Include="..\..\..\..\lib\curl_ctype.c" />
    <ClCompile Include="..\..\..\..\lib\curl_des.c" />
2428
2429
2430
2431
2432
2433
2434

2435
2436
2437
2438
2439
2440
2441
    <ClCompile Include="..\..\..\..\lib\hostcheck.c" />
    <ClCompile Include="..\..\..\..\lib\hostip4.c" />
    <ClCompile Include="..\..\..\..\lib\hostip6.c" />
    <ClCompile Include="..\..\..\..\lib\hostip.c" />
    <ClCompile Include="..\..\..\..\lib\hostsyn.c" />
    <ClCompile Include="..\..\..\..\lib\hsts.c" />
    <ClCompile Include="..\..\..\..\lib\http2.c" />

    <ClCompile Include="..\..\..\..\lib\http.c" />
    <ClCompile Include="..\..\..\..\lib\http_chunks.c" />
    <ClCompile Include="..\..\..\..\lib\http_digest.c" />
    <ClCompile Include="..\..\..\..\lib\http_negotiate.c" />
    <ClCompile Include="..\..\..\..\lib\http_ntlm.c" />
    <ClCompile Include="..\..\..\..\lib\http_proxy.c" />
    <ClCompile Include="..\..\..\..\lib\idn_win32.c" />







>







2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
    <ClCompile Include="..\..\..\..\lib\hostcheck.c" />
    <ClCompile Include="..\..\..\..\lib\hostip4.c" />
    <ClCompile Include="..\..\..\..\lib\hostip6.c" />
    <ClCompile Include="..\..\..\..\lib\hostip.c" />
    <ClCompile Include="..\..\..\..\lib\hostsyn.c" />
    <ClCompile Include="..\..\..\..\lib\hsts.c" />
    <ClCompile Include="..\..\..\..\lib\http2.c" />
    <ClCompile Include="..\..\..\..\lib\http_aws_sigv4.c" />
    <ClCompile Include="..\..\..\..\lib\http.c" />
    <ClCompile Include="..\..\..\..\lib\http_chunks.c" />
    <ClCompile Include="..\..\..\..\lib\http_digest.c" />
    <ClCompile Include="..\..\..\..\lib\http_negotiate.c" />
    <ClCompile Include="..\..\..\..\lib\http_ntlm.c" />
    <ClCompile Include="..\..\..\..\lib\http_proxy.c" />
    <ClCompile Include="..\..\..\..\lib\idn_win32.c" />
2530
2531
2532
2533
2534
2535
2536

2537
2538
2539
2540
2541
2542
2543
    <ClCompile Include="..\..\..\..\lib\vtls\wolfssl.c" />
  </ItemGroup>
  <ItemGroup>
    <ClInclude Include="..\..\..\..\lib\altsvc.h" />
    <ClInclude Include="..\..\..\..\lib\amigaos.h" />
    <ClInclude Include="..\..\..\..\lib\arpa_telnet.h" />
    <ClInclude Include="..\..\..\..\lib\asyn.h" />

    <ClInclude Include="..\..\..\..\lib\config-win32.h" />
    <ClInclude Include="..\..\..\..\lib\conncache.h" />
    <ClInclude Include="..\..\..\..\lib\connect.h" />
    <ClInclude Include="..\..\..\..\lib\content_encoding.h" />
    <ClInclude Include="..\..\..\..\lib\cookie.h" />
    <ClInclude Include="..\..\..\..\lib\curl_addrinfo.h" />
    <ClInclude Include="..\..\..\..\lib\curl_base64.h" />







>







2532
2533
2534
2535
2536
2537
2538
2539
2540
2541
2542
2543
2544
2545
2546
    <ClCompile Include="..\..\..\..\lib\vtls\wolfssl.c" />
  </ItemGroup>
  <ItemGroup>
    <ClInclude Include="..\..\..\..\lib\altsvc.h" />
    <ClInclude Include="..\..\..\..\lib\amigaos.h" />
    <ClInclude Include="..\..\..\..\lib\arpa_telnet.h" />
    <ClInclude Include="..\..\..\..\lib\asyn.h" />
    <ClInclude Include="..\..\..\..\lib\c-hyper.h" />
    <ClInclude Include="..\..\..\..\lib\config-win32.h" />
    <ClInclude Include="..\..\..\..\lib\conncache.h" />
    <ClInclude Include="..\..\..\..\lib\connect.h" />
    <ClInclude Include="..\..\..\..\lib\content_encoding.h" />
    <ClInclude Include="..\..\..\..\lib\cookie.h" />
    <ClInclude Include="..\..\..\..\lib\curl_addrinfo.h" />
    <ClInclude Include="..\..\..\..\lib\curl_base64.h" />
2584
2585
2586
2587
2588
2589
2590

2591
2592
2593
2594
2595
2596
2597
    <ClInclude Include="..\..\..\..\lib\getinfo.h" />
    <ClInclude Include="..\..\..\..\lib\gopher.h" />
    <ClInclude Include="..\..\..\..\lib\hash.h" />
    <ClInclude Include="..\..\..\..\lib\hostcheck.h" />
    <ClInclude Include="..\..\..\..\lib\hostip.h" />
    <ClInclude Include="..\..\..\..\lib\hsts.h" />
    <ClInclude Include="..\..\..\..\lib\http2.h" />

    <ClInclude Include="..\..\..\..\lib\http_chunks.h" />
    <ClInclude Include="..\..\..\..\lib\http_digest.h" />
    <ClInclude Include="..\..\..\..\lib\http.h" />
    <ClInclude Include="..\..\..\..\lib\http_negotiate.h" />
    <ClInclude Include="..\..\..\..\lib\http_ntlm.h" />
    <ClInclude Include="..\..\..\..\lib\http_proxy.h" />
    <ClInclude Include="..\..\..\..\lib\if2ip.h" />







>







2587
2588
2589
2590
2591
2592
2593
2594
2595
2596
2597
2598
2599
2600
2601
    <ClInclude Include="..\..\..\..\lib\getinfo.h" />
    <ClInclude Include="..\..\..\..\lib\gopher.h" />
    <ClInclude Include="..\..\..\..\lib\hash.h" />
    <ClInclude Include="..\..\..\..\lib\hostcheck.h" />
    <ClInclude Include="..\..\..\..\lib\hostip.h" />
    <ClInclude Include="..\..\..\..\lib\hsts.h" />
    <ClInclude Include="..\..\..\..\lib\http2.h" />
    <ClInclude Include="..\..\..\..\lib\http_aws_sigv4.h" />
    <ClInclude Include="..\..\..\..\lib\http_chunks.h" />
    <ClInclude Include="..\..\..\..\lib\http_digest.h" />
    <ClInclude Include="..\..\..\..\lib\http.h" />
    <ClInclude Include="..\..\..\..\lib\http_negotiate.h" />
    <ClInclude Include="..\..\..\..\lib\http_ntlm.h" />
    <ClInclude Include="..\..\..\..\lib\http_proxy.h" />
    <ClInclude Include="..\..\..\..\lib\if2ip.h" />
Changes to jni/curl/projects/Windows/VC14/lib/libcurl.vcxproj.
2380
2381
2382
2383
2384
2385
2386

2387
2388
2389
2390
2391
2392
2393
  </ItemDefinitionGroup>
  <ItemGroup>
    <ClCompile Include="..\..\..\..\lib\altsvc.c" />
    <ClCompile Include="..\..\..\..\lib\amigaos.c" />
    <ClCompile Include="..\..\..\..\lib\asyn-ares.c" />
    <ClCompile Include="..\..\..\..\lib\asyn-thread.c" />
    <ClCompile Include="..\..\..\..\lib\base64.c" />

    <ClCompile Include="..\..\..\..\lib\conncache.c" />
    <ClCompile Include="..\..\..\..\lib\connect.c" />
    <ClCompile Include="..\..\..\..\lib\content_encoding.c" />
    <ClCompile Include="..\..\..\..\lib\cookie.c" />
    <ClCompile Include="..\..\..\..\lib\curl_addrinfo.c" />
    <ClCompile Include="..\..\..\..\lib\curl_ctype.c" />
    <ClCompile Include="..\..\..\..\lib\curl_des.c" />







>







2380
2381
2382
2383
2384
2385
2386
2387
2388
2389
2390
2391
2392
2393
2394
  </ItemDefinitionGroup>
  <ItemGroup>
    <ClCompile Include="..\..\..\..\lib\altsvc.c" />
    <ClCompile Include="..\..\..\..\lib\amigaos.c" />
    <ClCompile Include="..\..\..\..\lib\asyn-ares.c" />
    <ClCompile Include="..\..\..\..\lib\asyn-thread.c" />
    <ClCompile Include="..\..\..\..\lib\base64.c" />
    <ClCompile Include="..\..\..\..\lib\c-hyper.c" />
    <ClCompile Include="..\..\..\..\lib\conncache.c" />
    <ClCompile Include="..\..\..\..\lib\connect.c" />
    <ClCompile Include="..\..\..\..\lib\content_encoding.c" />
    <ClCompile Include="..\..\..\..\lib\cookie.c" />
    <ClCompile Include="..\..\..\..\lib\curl_addrinfo.c" />
    <ClCompile Include="..\..\..\..\lib\curl_ctype.c" />
    <ClCompile Include="..\..\..\..\lib\curl_des.c" />
2428
2429
2430
2431
2432
2433
2434

2435
2436
2437
2438
2439
2440
2441
    <ClCompile Include="..\..\..\..\lib\hostcheck.c" />
    <ClCompile Include="..\..\..\..\lib\hostip4.c" />
    <ClCompile Include="..\..\..\..\lib\hostip6.c" />
    <ClCompile Include="..\..\..\..\lib\hostip.c" />
    <ClCompile Include="..\..\..\..\lib\hostsyn.c" />
    <ClCompile Include="..\..\..\..\lib\hsts.c" />
    <ClCompile Include="..\..\..\..\lib\http2.c" />

    <ClCompile Include="..\..\..\..\lib\http.c" />
    <ClCompile Include="..\..\..\..\lib\http_chunks.c" />
    <ClCompile Include="..\..\..\..\lib\http_digest.c" />
    <ClCompile Include="..\..\..\..\lib\http_negotiate.c" />
    <ClCompile Include="..\..\..\..\lib\http_ntlm.c" />
    <ClCompile Include="..\..\..\..\lib\http_proxy.c" />
    <ClCompile Include="..\..\..\..\lib\idn_win32.c" />







>







2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
    <ClCompile Include="..\..\..\..\lib\hostcheck.c" />
    <ClCompile Include="..\..\..\..\lib\hostip4.c" />
    <ClCompile Include="..\..\..\..\lib\hostip6.c" />
    <ClCompile Include="..\..\..\..\lib\hostip.c" />
    <ClCompile Include="..\..\..\..\lib\hostsyn.c" />
    <ClCompile Include="..\..\..\..\lib\hsts.c" />
    <ClCompile Include="..\..\..\..\lib\http2.c" />
    <ClCompile Include="..\..\..\..\lib\http_aws_sigv4.c" />
    <ClCompile Include="..\..\..\..\lib\http.c" />
    <ClCompile Include="..\..\..\..\lib\http_chunks.c" />
    <ClCompile Include="..\..\..\..\lib\http_digest.c" />
    <ClCompile Include="..\..\..\..\lib\http_negotiate.c" />
    <ClCompile Include="..\..\..\..\lib\http_ntlm.c" />
    <ClCompile Include="..\..\..\..\lib\http_proxy.c" />
    <ClCompile Include="..\..\..\..\lib\idn_win32.c" />
2530
2531
2532
2533
2534
2535
2536

2537
2538
2539
2540
2541
2542
2543
    <ClCompile Include="..\..\..\..\lib\vtls\wolfssl.c" />
  </ItemGroup>
  <ItemGroup>
    <ClInclude Include="..\..\..\..\lib\altsvc.h" />
    <ClInclude Include="..\..\..\..\lib\amigaos.h" />
    <ClInclude Include="..\..\..\..\lib\arpa_telnet.h" />
    <ClInclude Include="..\..\..\..\lib\asyn.h" />

    <ClInclude Include="..\..\..\..\lib\config-win32.h" />
    <ClInclude Include="..\..\..\..\lib\conncache.h" />
    <ClInclude Include="..\..\..\..\lib\connect.h" />
    <ClInclude Include="..\..\..\..\lib\content_encoding.h" />
    <ClInclude Include="..\..\..\..\lib\cookie.h" />
    <ClInclude Include="..\..\..\..\lib\curl_addrinfo.h" />
    <ClInclude Include="..\..\..\..\lib\curl_base64.h" />







>







2532
2533
2534
2535
2536
2537
2538
2539
2540
2541
2542
2543
2544
2545
2546
    <ClCompile Include="..\..\..\..\lib\vtls\wolfssl.c" />
  </ItemGroup>
  <ItemGroup>
    <ClInclude Include="..\..\..\..\lib\altsvc.h" />
    <ClInclude Include="..\..\..\..\lib\amigaos.h" />
    <ClInclude Include="..\..\..\..\lib\arpa_telnet.h" />
    <ClInclude Include="..\..\..\..\lib\asyn.h" />
    <ClInclude Include="..\..\..\..\lib\c-hyper.h" />
    <ClInclude Include="..\..\..\..\lib\config-win32.h" />
    <ClInclude Include="..\..\..\..\lib\conncache.h" />
    <ClInclude Include="..\..\..\..\lib\connect.h" />
    <ClInclude Include="..\..\..\..\lib\content_encoding.h" />
    <ClInclude Include="..\..\..\..\lib\cookie.h" />
    <ClInclude Include="..\..\..\..\lib\curl_addrinfo.h" />
    <ClInclude Include="..\..\..\..\lib\curl_base64.h" />
2584
2585
2586
2587
2588
2589
2590

2591
2592
2593
2594
2595
2596
2597
    <ClInclude Include="..\..\..\..\lib\getinfo.h" />
    <ClInclude Include="..\..\..\..\lib\gopher.h" />
    <ClInclude Include="..\..\..\..\lib\hash.h" />
    <ClInclude Include="..\..\..\..\lib\hostcheck.h" />
    <ClInclude Include="..\..\..\..\lib\hostip.h" />
    <ClInclude Include="..\..\..\..\lib\hsts.h" />
    <ClInclude Include="..\..\..\..\lib\http2.h" />

    <ClInclude Include="..\..\..\..\lib\http_chunks.h" />
    <ClInclude Include="..\..\..\..\lib\http_digest.h" />
    <ClInclude Include="..\..\..\..\lib\http.h" />
    <ClInclude Include="..\..\..\..\lib\http_negotiate.h" />
    <ClInclude Include="..\..\..\..\lib\http_ntlm.h" />
    <ClInclude Include="..\..\..\..\lib\http_proxy.h" />
    <ClInclude Include="..\..\..\..\lib\if2ip.h" />







>







2587
2588
2589
2590
2591
2592
2593
2594
2595
2596
2597
2598
2599
2600
2601
    <ClInclude Include="..\..\..\..\lib\getinfo.h" />
    <ClInclude Include="..\..\..\..\lib\gopher.h" />
    <ClInclude Include="..\..\..\..\lib\hash.h" />
    <ClInclude Include="..\..\..\..\lib\hostcheck.h" />
    <ClInclude Include="..\..\..\..\lib\hostip.h" />
    <ClInclude Include="..\..\..\..\lib\hsts.h" />
    <ClInclude Include="..\..\..\..\lib\http2.h" />
    <ClInclude Include="..\..\..\..\lib\http_aws_sigv4.h" />
    <ClInclude Include="..\..\..\..\lib\http_chunks.h" />
    <ClInclude Include="..\..\..\..\lib\http_digest.h" />
    <ClInclude Include="..\..\..\..\lib\http.h" />
    <ClInclude Include="..\..\..\..\lib\http_negotiate.h" />
    <ClInclude Include="..\..\..\..\lib\http_ntlm.h" />
    <ClInclude Include="..\..\..\..\lib\http_proxy.h" />
    <ClInclude Include="..\..\..\..\lib\if2ip.h" />
Changes to jni/curl/projects/Windows/VC15/lib/libcurl.vcxproj.
2352
2353
2354
2355
2356
2357
2358

2359
2360
2361
2362
2363
2364
2365
  </ItemDefinitionGroup>
  <ItemGroup>
    <ClCompile Include="..\..\..\..\lib\altsvc.c" />
    <ClCompile Include="..\..\..\..\lib\amigaos.c" />
    <ClCompile Include="..\..\..\..\lib\asyn-ares.c" />
    <ClCompile Include="..\..\..\..\lib\asyn-thread.c" />
    <ClCompile Include="..\..\..\..\lib\base64.c" />

    <ClCompile Include="..\..\..\..\lib\conncache.c" />
    <ClCompile Include="..\..\..\..\lib\connect.c" />
    <ClCompile Include="..\..\..\..\lib\content_encoding.c" />
    <ClCompile Include="..\..\..\..\lib\cookie.c" />
    <ClCompile Include="..\..\..\..\lib\curl_addrinfo.c" />
    <ClCompile Include="..\..\..\..\lib\curl_ctype.c" />
    <ClCompile Include="..\..\..\..\lib\curl_des.c" />







>







2352
2353
2354
2355
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
  </ItemDefinitionGroup>
  <ItemGroup>
    <ClCompile Include="..\..\..\..\lib\altsvc.c" />
    <ClCompile Include="..\..\..\..\lib\amigaos.c" />
    <ClCompile Include="..\..\..\..\lib\asyn-ares.c" />
    <ClCompile Include="..\..\..\..\lib\asyn-thread.c" />
    <ClCompile Include="..\..\..\..\lib\base64.c" />
    <ClCompile Include="..\..\..\..\lib\c-hyper.c" />
    <ClCompile Include="..\..\..\..\lib\conncache.c" />
    <ClCompile Include="..\..\..\..\lib\connect.c" />
    <ClCompile Include="..\..\..\..\lib\content_encoding.c" />
    <ClCompile Include="..\..\..\..\lib\cookie.c" />
    <ClCompile Include="..\..\..\..\lib\curl_addrinfo.c" />
    <ClCompile Include="..\..\..\..\lib\curl_ctype.c" />
    <ClCompile Include="..\..\..\..\lib\curl_des.c" />
2400
2401
2402
2403
2404
2405
2406

2407
2408
2409
2410
2411
2412
2413
    <ClCompile Include="..\..\..\..\lib\hostcheck.c" />
    <ClCompile Include="..\..\..\..\lib\hostip4.c" />
    <ClCompile Include="..\..\..\..\lib\hostip6.c" />
    <ClCompile Include="..\..\..\..\lib\hostip.c" />
    <ClCompile Include="..\..\..\..\lib\hostsyn.c" />
    <ClCompile Include="..\..\..\..\lib\hsts.c" />
    <ClCompile Include="..\..\..\..\lib\http2.c" />

    <ClCompile Include="..\..\..\..\lib\http.c" />
    <ClCompile Include="..\..\..\..\lib\http_chunks.c" />
    <ClCompile Include="..\..\..\..\lib\http_digest.c" />
    <ClCompile Include="..\..\..\..\lib\http_negotiate.c" />
    <ClCompile Include="..\..\..\..\lib\http_ntlm.c" />
    <ClCompile Include="..\..\..\..\lib\http_proxy.c" />
    <ClCompile Include="..\..\..\..\lib\idn_win32.c" />







>







2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
    <ClCompile Include="..\..\..\..\lib\hostcheck.c" />
    <ClCompile Include="..\..\..\..\lib\hostip4.c" />
    <ClCompile Include="..\..\..\..\lib\hostip6.c" />
    <ClCompile Include="..\..\..\..\lib\hostip.c" />
    <ClCompile Include="..\..\..\..\lib\hostsyn.c" />
    <ClCompile Include="..\..\..\..\lib\hsts.c" />
    <ClCompile Include="..\..\..\..\lib\http2.c" />
    <ClCompile Include="..\..\..\..\lib\http_aws_sigv4.c" />
    <ClCompile Include="..\..\..\..\lib\http.c" />
    <ClCompile Include="..\..\..\..\lib\http_chunks.c" />
    <ClCompile Include="..\..\..\..\lib\http_digest.c" />
    <ClCompile Include="..\..\..\..\lib\http_negotiate.c" />
    <ClCompile Include="..\..\..\..\lib\http_ntlm.c" />
    <ClCompile Include="..\..\..\..\lib\http_proxy.c" />
    <ClCompile Include="..\..\..\..\lib\idn_win32.c" />
2502
2503
2504
2505
2506
2507
2508

2509
2510
2511
2512
2513
2514
2515
    <ClCompile Include="..\..\..\..\lib\vtls\wolfssl.c" />
  </ItemGroup>
  <ItemGroup>
    <ClInclude Include="..\..\..\..\lib\altsvc.h" />
    <ClInclude Include="..\..\..\..\lib\amigaos.h" />
    <ClInclude Include="..\..\..\..\lib\arpa_telnet.h" />
    <ClInclude Include="..\..\..\..\lib\asyn.h" />

    <ClInclude Include="..\..\..\..\lib\config-win32.h" />
    <ClInclude Include="..\..\..\..\lib\conncache.h" />
    <ClInclude Include="..\..\..\..\lib\connect.h" />
    <ClInclude Include="..\..\..\..\lib\content_encoding.h" />
    <ClInclude Include="..\..\..\..\lib\cookie.h" />
    <ClInclude Include="..\..\..\..\lib\curl_addrinfo.h" />
    <ClInclude Include="..\..\..\..\lib\curl_base64.h" />







>







2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
    <ClCompile Include="..\..\..\..\lib\vtls\wolfssl.c" />
  </ItemGroup>
  <ItemGroup>
    <ClInclude Include="..\..\..\..\lib\altsvc.h" />
    <ClInclude Include="..\..\..\..\lib\amigaos.h" />
    <ClInclude Include="..\..\..\..\lib\arpa_telnet.h" />
    <ClInclude Include="..\..\..\..\lib\asyn.h" />
    <ClInclude Include="..\..\..\..\lib\c-hyper.h" />
    <ClInclude Include="..\..\..\..\lib\config-win32.h" />
    <ClInclude Include="..\..\..\..\lib\conncache.h" />
    <ClInclude Include="..\..\..\..\lib\connect.h" />
    <ClInclude Include="..\..\..\..\lib\content_encoding.h" />
    <ClInclude Include="..\..\..\..\lib\cookie.h" />
    <ClInclude Include="..\..\..\..\lib\curl_addrinfo.h" />
    <ClInclude Include="..\..\..\..\lib\curl_base64.h" />
2556
2557
2558
2559
2560
2561
2562

2563
2564
2565
2566
2567
2568
2569
    <ClInclude Include="..\..\..\..\lib\getinfo.h" />
    <ClInclude Include="..\..\..\..\lib\gopher.h" />
    <ClInclude Include="..\..\..\..\lib\hash.h" />
    <ClInclude Include="..\..\..\..\lib\hostcheck.h" />
    <ClInclude Include="..\..\..\..\lib\hostip.h" />
    <ClInclude Include="..\..\..\..\lib\hsts.h" />
    <ClInclude Include="..\..\..\..\lib\http2.h" />

    <ClInclude Include="..\..\..\..\lib\http_chunks.h" />
    <ClInclude Include="..\..\..\..\lib\http_digest.h" />
    <ClInclude Include="..\..\..\..\lib\http.h" />
    <ClInclude Include="..\..\..\..\lib\http_negotiate.h" />
    <ClInclude Include="..\..\..\..\lib\http_ntlm.h" />
    <ClInclude Include="..\..\..\..\lib\http_proxy.h" />
    <ClInclude Include="..\..\..\..\lib\if2ip.h" />







>







2559
2560
2561
2562
2563
2564
2565
2566
2567
2568
2569
2570
2571
2572
2573
    <ClInclude Include="..\..\..\..\lib\getinfo.h" />
    <ClInclude Include="..\..\..\..\lib\gopher.h" />
    <ClInclude Include="..\..\..\..\lib\hash.h" />
    <ClInclude Include="..\..\..\..\lib\hostcheck.h" />
    <ClInclude Include="..\..\..\..\lib\hostip.h" />
    <ClInclude Include="..\..\..\..\lib\hsts.h" />
    <ClInclude Include="..\..\..\..\lib\http2.h" />
    <ClInclude Include="..\..\..\..\lib\http_aws_sigv4.h" />
    <ClInclude Include="..\..\..\..\lib\http_chunks.h" />
    <ClInclude Include="..\..\..\..\lib\http_digest.h" />
    <ClInclude Include="..\..\..\..\lib\http.h" />
    <ClInclude Include="..\..\..\..\lib\http_negotiate.h" />
    <ClInclude Include="..\..\..\..\lib\http_ntlm.h" />
    <ClInclude Include="..\..\..\..\lib\http_proxy.h" />
    <ClInclude Include="..\..\..\..\lib\if2ip.h" />
Changes to jni/curl/projects/Windows/VC6/lib/libcurl.dsp.
745
746
747
748
749
750
751




752
753
754
755
756
757
758
SOURCE=..\..\..\..\lib\asyn-thread.c
# End Source File
# Begin Source File

SOURCE=..\..\..\..\lib\base64.c
# End Source File
# Begin Source File





SOURCE=..\..\..\..\lib\conncache.c
# End Source File
# Begin Source File

SOURCE=..\..\..\..\lib\connect.c
# End Source File







>
>
>
>







745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
SOURCE=..\..\..\..\lib\asyn-thread.c
# End Source File
# Begin Source File

SOURCE=..\..\..\..\lib\base64.c
# End Source File
# Begin Source File

SOURCE=..\..\..\..\lib\c-hyper.c
# End Source File
# Begin Source File

SOURCE=..\..\..\..\lib\conncache.c
# End Source File
# Begin Source File

SOURCE=..\..\..\..\lib\connect.c
# End Source File
937
938
939
940
941
942
943




944
945
946
947
948
949
950
SOURCE=..\..\..\..\lib\hsts.c
# End Source File
# Begin Source File

SOURCE=..\..\..\..\lib\http2.c
# End Source File
# Begin Source File





SOURCE=..\..\..\..\lib\http.c
# End Source File
# Begin Source File

SOURCE=..\..\..\..\lib\http_chunks.c
# End Source File







>
>
>
>







941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
SOURCE=..\..\..\..\lib\hsts.c
# End Source File
# Begin Source File

SOURCE=..\..\..\..\lib\http2.c
# End Source File
# Begin Source File

SOURCE=..\..\..\..\lib\http_aws_sigv4.c
# End Source File
# Begin Source File

SOURCE=..\..\..\..\lib\http.c
# End Source File
# Begin Source File

SOURCE=..\..\..\..\lib\http_chunks.c
# End Source File
1341
1342
1343
1344
1345
1346
1347




1348
1349
1350
1351
1352
1353
1354
SOURCE=..\..\..\..\lib\arpa_telnet.h
# End Source File
# Begin Source File

SOURCE=..\..\..\..\lib\asyn.h
# End Source File
# Begin Source File





SOURCE=..\..\..\..\lib\config-win32.h
# End Source File
# Begin Source File

SOURCE=..\..\..\..\lib\conncache.h
# End Source File







>
>
>
>







1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
SOURCE=..\..\..\..\lib\arpa_telnet.h
# End Source File
# Begin Source File

SOURCE=..\..\..\..\lib\asyn.h
# End Source File
# Begin Source File

SOURCE=..\..\..\..\lib\c-hyper.h
# End Source File
# Begin Source File

SOURCE=..\..\..\..\lib\config-win32.h
# End Source File
# Begin Source File

SOURCE=..\..\..\..\lib\conncache.h
# End Source File
1557
1558
1559
1560
1561
1562
1563




1564
1565
1566
1567
1568
1569
1570
SOURCE=..\..\..\..\lib\hsts.h
# End Source File
# Begin Source File

SOURCE=..\..\..\..\lib\http2.h
# End Source File
# Begin Source File





SOURCE=..\..\..\..\lib\http_chunks.h
# End Source File
# Begin Source File

SOURCE=..\..\..\..\lib\http_digest.h
# End Source File







>
>
>
>







1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
SOURCE=..\..\..\..\lib\hsts.h
# End Source File
# Begin Source File

SOURCE=..\..\..\..\lib\http2.h
# End Source File
# Begin Source File

SOURCE=..\..\..\..\lib\http_aws_sigv4.h
# End Source File
# Begin Source File

SOURCE=..\..\..\..\lib\http_chunks.h
# End Source File
# Begin Source File

SOURCE=..\..\..\..\lib\http_digest.h
# End Source File
Changes to jni/curl/projects/Windows/VC7.1/lib/libcurl.vcproj.
1266
1267
1268
1269
1270
1271
1272



1273
1274
1275
1276
1277
1278
1279
			</File>
			<File
				RelativePath="..\..\..\..\lib\asyn-thread.c">
			</File>
			<File
				RelativePath="..\..\..\..\lib\base64.c">
			</File>



			<File
				RelativePath="..\..\..\..\lib\conncache.c">
			</File>
			<File
				RelativePath="..\..\..\..\lib\connect.c">
			</File>
			<File







>
>
>







1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
			</File>
			<File
				RelativePath="..\..\..\..\lib\asyn-thread.c">
			</File>
			<File
				RelativePath="..\..\..\..\lib\base64.c">
			</File>
			<File
				RelativePath="..\..\..\..\lib\c-hyper.c">
			</File>
			<File
				RelativePath="..\..\..\..\lib\conncache.c">
			</File>
			<File
				RelativePath="..\..\..\..\lib\connect.c">
			</File>
			<File
1410
1411
1412
1413
1414
1415
1416



1417
1418
1419
1420
1421
1422
1423
			</File>
			<File
				RelativePath="..\..\..\..\lib\hsts.c">
			</File>
			<File
				RelativePath="..\..\..\..\lib\http2.c">
			</File>



			<File
				RelativePath="..\..\..\..\lib\http.c">
			</File>
			<File
				RelativePath="..\..\..\..\lib\http_chunks.c">
			</File>
			<File







>
>
>







1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
			</File>
			<File
				RelativePath="..\..\..\..\lib\hsts.c">
			</File>
			<File
				RelativePath="..\..\..\..\lib\http2.c">
			</File>
			<File
				RelativePath="..\..\..\..\lib\http_aws_sigv4.c">
			</File>
			<File
				RelativePath="..\..\..\..\lib\http.c">
			</File>
			<File
				RelativePath="..\..\..\..\lib\http_chunks.c">
			</File>
			<File
1618
1619
1620
1621
1622
1623
1624



1625
1626
1627
1628
1629
1630
1631
			</File>
			<File
				RelativePath="..\..\..\..\lib\arpa_telnet.h">
			</File>
			<File
				RelativePath="..\..\..\..\lib\asyn.h">
			</File>



			<File
				RelativePath="..\..\..\..\lib\config-win32.h">
			</File>
			<File
				RelativePath="..\..\..\..\lib\conncache.h">
			</File>
			<File







>
>
>







1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
			</File>
			<File
				RelativePath="..\..\..\..\lib\arpa_telnet.h">
			</File>
			<File
				RelativePath="..\..\..\..\lib\asyn.h">
			</File>
			<File
				RelativePath="..\..\..\..\lib\c-hyper.h">
			</File>
			<File
				RelativePath="..\..\..\..\lib\config-win32.h">
			</File>
			<File
				RelativePath="..\..\..\..\lib\conncache.h">
			</File>
			<File
1780
1781
1782
1783
1784
1785
1786



1787
1788
1789
1790
1791
1792
1793
			</File>
			<File
				RelativePath="..\..\..\..\lib\hsts.h">
			</File>
			<File
				RelativePath="..\..\..\..\lib\http2.h">
			</File>



			<File
				RelativePath="..\..\..\..\lib\http_chunks.h">
			</File>
			<File
				RelativePath="..\..\..\..\lib\http_digest.h">
			</File>
			<File







>
>
>







1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
			</File>
			<File
				RelativePath="..\..\..\..\lib\hsts.h">
			</File>
			<File
				RelativePath="..\..\..\..\lib\http2.h">
			</File>
			<File
				RelativePath="..\..\..\..\lib\http_aws_sigv4.h">
			</File>
			<File
				RelativePath="..\..\..\..\lib\http_chunks.h">
			</File>
			<File
				RelativePath="..\..\..\..\lib\http_digest.h">
			</File>
			<File
Changes to jni/curl/projects/Windows/VC7/lib/libcurl.vcproj.
1120
1121
1122
1123
1124
1125
1126



1127
1128
1129
1130
1131
1132
1133
			</File>
			<File
				RelativePath="..\..\..\..\lib\asyn-thread.c">
			</File>
			<File
				RelativePath="..\..\..\..\lib\base64.c">
			</File>



			<File
				RelativePath="..\..\..\..\lib\conncache.c">
			</File>
			<File
				RelativePath="..\..\..\..\lib\connect.c">
			</File>
			<File







>
>
>







1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
			</File>
			<File
				RelativePath="..\..\..\..\lib\asyn-thread.c">
			</File>
			<File
				RelativePath="..\..\..\..\lib\base64.c">
			</File>
			<File
				RelativePath="..\..\..\..\lib\c-hyper.c">
			</File>
			<File
				RelativePath="..\..\..\..\lib\conncache.c">
			</File>
			<File
				RelativePath="..\..\..\..\lib\connect.c">
			</File>
			<File
1264
1265
1266
1267
1268
1269
1270



1271
1272
1273
1274
1275
1276
1277
			</File>
			<File
				RelativePath="..\..\..\..\lib\hsts.c">
			</File>
			<File
				RelativePath="..\..\..\..\lib\http2.c">
			</File>



			<File
				RelativePath="..\..\..\..\lib\http.c">
			</File>
			<File
				RelativePath="..\..\..\..\lib\http_chunks.c">
			</File>
			<File







>
>
>







1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
			</File>
			<File
				RelativePath="..\..\..\..\lib\hsts.c">
			</File>
			<File
				RelativePath="..\..\..\..\lib\http2.c">
			</File>
			<File
				RelativePath="..\..\..\..\lib\http_aws_sigv4.c">
			</File>
			<File
				RelativePath="..\..\..\..\lib\http.c">
			</File>
			<File
				RelativePath="..\..\..\..\lib\http_chunks.c">
			</File>
			<File
1472
1473
1474
1475
1476
1477
1478



1479
1480
1481
1482
1483
1484
1485
			</File>
			<File
				RelativePath="..\..\..\..\lib\arpa_telnet.h">
			</File>
			<File
				RelativePath="..\..\..\..\lib\asyn.h">
			</File>



			<File
				RelativePath="..\..\..\..\lib\config-win32.h">
			</File>
			<File
				RelativePath="..\..\..\..\lib\conncache.h">
			</File>
			<File







>
>
>







1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
			</File>
			<File
				RelativePath="..\..\..\..\lib\arpa_telnet.h">
			</File>
			<File
				RelativePath="..\..\..\..\lib\asyn.h">
			</File>
			<File
				RelativePath="..\..\..\..\lib\c-hyper.h">
			</File>
			<File
				RelativePath="..\..\..\..\lib\config-win32.h">
			</File>
			<File
				RelativePath="..\..\..\..\lib\conncache.h">
			</File>
			<File
1634
1635
1636
1637
1638
1639
1640



1641
1642
1643
1644
1645
1646
1647
			</File>
			<File
				RelativePath="..\..\..\..\lib\hsts.h">
			</File>
			<File
				RelativePath="..\..\..\..\lib\http2.h">
			</File>



			<File
				RelativePath="..\..\..\..\lib\http_chunks.h">
			</File>
			<File
				RelativePath="..\..\..\..\lib\http_digest.h">
			</File>
			<File







>
>
>







1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
			</File>
			<File
				RelativePath="..\..\..\..\lib\hsts.h">
			</File>
			<File
				RelativePath="..\..\..\..\lib\http2.h">
			</File>
			<File
				RelativePath="..\..\..\..\lib\http_aws_sigv4.h">
			</File>
			<File
				RelativePath="..\..\..\..\lib\http_chunks.h">
			</File>
			<File
				RelativePath="..\..\..\..\lib\http_digest.h">
			</File>
			<File
Changes to jni/curl/projects/Windows/VC8/lib/libcurl.vcproj.
3631
3632
3633
3634
3635
3636
3637




3638
3639
3640
3641
3642
3643
3644
			<File
				RelativePath="..\..\..\..\lib\asyn-thread.c"
			>
			</File>
			<File
				RelativePath="..\..\..\..\lib\base64.c"
			>




			</File>
			<File
				RelativePath="..\..\..\..\lib\conncache.c"
			>
			</File>
			<File
				RelativePath="..\..\..\..\lib\connect.c"







>
>
>
>







3631
3632
3633
3634
3635
3636
3637
3638
3639
3640
3641
3642
3643
3644
3645
3646
3647
3648
			<File
				RelativePath="..\..\..\..\lib\asyn-thread.c"
			>
			</File>
			<File
				RelativePath="..\..\..\..\lib\base64.c"
			>
			</File>
			<File
				RelativePath="..\..\..\..\lib\c-hyper.c"
			>
			</File>
			<File
				RelativePath="..\..\..\..\lib\conncache.c"
			>
			</File>
			<File
				RelativePath="..\..\..\..\lib\connect.c"
3823
3824
3825
3826
3827
3828
3829




3830
3831
3832
3833
3834
3835
3836
			<File
				RelativePath="..\..\..\..\lib\hsts.c"
			>
			</File>
			<File
				RelativePath="..\..\..\..\lib\http2.c"
			>




			</File>
			<File
				RelativePath="..\..\..\..\lib\http.c"
			>
			</File>
			<File
				RelativePath="..\..\..\..\lib\http_chunks.c"







>
>
>
>







3827
3828
3829
3830
3831
3832
3833
3834
3835
3836
3837
3838
3839
3840
3841
3842
3843
3844
			<File
				RelativePath="..\..\..\..\lib\hsts.c"
			>
			</File>
			<File
				RelativePath="..\..\..\..\lib\http2.c"
			>
			</File>
			<File
				RelativePath="..\..\..\..\lib\http_aws_sigv4.c"
			>
			</File>
			<File
				RelativePath="..\..\..\..\lib\http.c"
			>
			</File>
			<File
				RelativePath="..\..\..\..\lib\http_chunks.c"
4099
4100
4101
4102
4103
4104
4105




4106
4107
4108
4109
4110
4111
4112
			<File
				RelativePath="..\..\..\..\lib\arpa_telnet.h"
			>
			</File>
			<File
				RelativePath="..\..\..\..\lib\asyn.h"
			>




			</File>
			<File
				RelativePath="..\..\..\..\lib\config-win32.h"
			>
			</File>
			<File
				RelativePath="..\..\..\..\lib\conncache.h"







>
>
>
>







4107
4108
4109
4110
4111
4112
4113
4114
4115
4116
4117
4118
4119
4120
4121
4122
4123
4124
			<File
				RelativePath="..\..\..\..\lib\arpa_telnet.h"
			>
			</File>
			<File
				RelativePath="..\..\..\..\lib\asyn.h"
			>
			</File>
			<File
				RelativePath="..\..\..\..\lib\c-hyper.h"
			>
			</File>
			<File
				RelativePath="..\..\..\..\lib\config-win32.h"
			>
			</File>
			<File
				RelativePath="..\..\..\..\lib\conncache.h"
4315
4316
4317
4318
4319
4320
4321




4322
4323
4324
4325
4326
4327
4328
			<File
				RelativePath="..\..\..\..\lib\hsts.h"
			>
			</File>
			<File
				RelativePath="..\..\..\..\lib\http2.h"
			>




			</File>
			<File
				RelativePath="..\..\..\..\lib\http_chunks.h"
			>
			</File>
			<File
				RelativePath="..\..\..\..\lib\http_digest.h"







>
>
>
>







4327
4328
4329
4330
4331
4332
4333
4334
4335
4336
4337
4338
4339
4340
4341
4342
4343
4344
			<File
				RelativePath="..\..\..\..\lib\hsts.h"
			>
			</File>
			<File
				RelativePath="..\..\..\..\lib\http2.h"
			>
			</File>
			<File
				RelativePath="..\..\..\..\lib\http_aws_sigv4.h"
			>
			</File>
			<File
				RelativePath="..\..\..\..\lib\http_chunks.h"
			>
			</File>
			<File
				RelativePath="..\..\..\..\lib\http_digest.h"
Changes to jni/curl/projects/Windows/VC9/lib/libcurl.vcproj.
3572
3573
3574
3575
3576
3577
3578




3579
3580
3581
3582
3583
3584
3585
			<File
				RelativePath="..\..\..\..\lib\asyn-thread.c"
			>
			</File>
			<File
				RelativePath="..\..\..\..\lib\base64.c"
			>




			</File>
			<File
				RelativePath="..\..\..\..\lib\conncache.c"
			>
			</File>
			<File
				RelativePath="..\..\..\..\lib\connect.c"







>
>
>
>







3572
3573
3574
3575
3576
3577
3578
3579
3580
3581
3582
3583
3584
3585
3586
3587
3588
3589
			<File
				RelativePath="..\..\..\..\lib\asyn-thread.c"
			>
			</File>
			<File
				RelativePath="..\..\..\..\lib\base64.c"
			>
			</File>
			<File
				RelativePath="..\..\..\..\lib\c-hyper.c"
			>
			</File>
			<File
				RelativePath="..\..\..\..\lib\conncache.c"
			>
			</File>
			<File
				RelativePath="..\..\..\..\lib\connect.c"
3764
3765
3766
3767
3768
3769
3770




3771
3772
3773
3774
3775
3776
3777
			<File
				RelativePath="..\..\..\..\lib\hsts.c"
			>
			</File>
			<File
				RelativePath="..\..\..\..\lib\http2.c"
			>




			</File>
			<File
				RelativePath="..\..\..\..\lib\http.c"
			>
			</File>
			<File
				RelativePath="..\..\..\..\lib\http_chunks.c"







>
>
>
>







3768
3769
3770
3771
3772
3773
3774
3775
3776
3777
3778
3779
3780
3781
3782
3783
3784
3785
			<File
				RelativePath="..\..\..\..\lib\hsts.c"
			>
			</File>
			<File
				RelativePath="..\..\..\..\lib\http2.c"
			>
			</File>
			<File
				RelativePath="..\..\..\..\lib\http_aws_sigv4.c"
			>
			</File>
			<File
				RelativePath="..\..\..\..\lib\http.c"
			>
			</File>
			<File
				RelativePath="..\..\..\..\lib\http_chunks.c"
4040
4041
4042
4043
4044
4045
4046




4047
4048
4049
4050
4051
4052
4053
			<File
				RelativePath="..\..\..\..\lib\arpa_telnet.h"
			>
			</File>
			<File
				RelativePath="..\..\..\..\lib\asyn.h"
			>




			</File>
			<File
				RelativePath="..\..\..\..\lib\config-win32.h"
			>
			</File>
			<File
				RelativePath="..\..\..\..\lib\conncache.h"







>
>
>
>







4048
4049
4050
4051
4052
4053
4054
4055
4056
4057
4058
4059
4060
4061
4062
4063
4064
4065
			<File
				RelativePath="..\..\..\..\lib\arpa_telnet.h"
			>
			</File>
			<File
				RelativePath="..\..\..\..\lib\asyn.h"
			>
			</File>
			<File
				RelativePath="..\..\..\..\lib\c-hyper.h"
			>
			</File>
			<File
				RelativePath="..\..\..\..\lib\config-win32.h"
			>
			</File>
			<File
				RelativePath="..\..\..\..\lib\conncache.h"
4256
4257
4258
4259
4260
4261
4262




4263
4264
4265
4266
4267
4268
4269
			<File
				RelativePath="..\..\..\..\lib\hsts.h"
			>
			</File>
			<File
				RelativePath="..\..\..\..\lib\http2.h"
			>




			</File>
			<File
				RelativePath="..\..\..\..\lib\http_chunks.h"
			>
			</File>
			<File
				RelativePath="..\..\..\..\lib\http_digest.h"







>
>
>
>







4268
4269
4270
4271
4272
4273
4274
4275
4276
4277
4278
4279
4280
4281
4282
4283
4284
4285
			<File
				RelativePath="..\..\..\..\lib\hsts.h"
			>
			</File>
			<File
				RelativePath="..\..\..\..\lib\http2.h"
			>
			</File>
			<File
				RelativePath="..\..\..\..\lib\http_aws_sigv4.h"
			>
			</File>
			<File
				RelativePath="..\..\..\..\lib\http_chunks.h"
			>
			</File>
			<File
				RelativePath="..\..\..\..\lib\http_digest.h"
Changes to jni/curl/projects/build-openssl.bat.
Changes to jni/curl/projects/build-wolfssl.bat.
Changes to jni/curl/projects/checksrc.bat.
Changes to jni/curl/projects/generate.bat.
Changes to jni/curl/scripts/Makefile.in.
263
264
265
266
267
268
269

270
271
272
273
274
275
276
STRIP = @STRIP@
SUPPORT_FEATURES = @SUPPORT_FEATURES@
SUPPORT_PROTOCOLS = @SUPPORT_PROTOCOLS@
USE_ARES = @USE_ARES@
USE_BEARSSL = @USE_BEARSSL@
USE_GNUTLS = @USE_GNUTLS@
USE_GNUTLS_NETTLE = @USE_GNUTLS_NETTLE@

USE_LIBRTMP = @USE_LIBRTMP@
USE_LIBSSH = @USE_LIBSSH@
USE_LIBSSH2 = @USE_LIBSSH2@
USE_MBEDTLS = @USE_MBEDTLS@
USE_MESALINK = @USE_MESALINK@
USE_NGHTTP2 = @USE_NGHTTP2@
USE_NGHTTP3 = @USE_NGHTTP3@







>







263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
STRIP = @STRIP@
SUPPORT_FEATURES = @SUPPORT_FEATURES@
SUPPORT_PROTOCOLS = @SUPPORT_PROTOCOLS@
USE_ARES = @USE_ARES@
USE_BEARSSL = @USE_BEARSSL@
USE_GNUTLS = @USE_GNUTLS@
USE_GNUTLS_NETTLE = @USE_GNUTLS_NETTLE@
USE_HYPER = @USE_HYPER@
USE_LIBRTMP = @USE_LIBRTMP@
USE_LIBSSH = @USE_LIBSSH@
USE_LIBSSH2 = @USE_LIBSSH2@
USE_MBEDTLS = @USE_MBEDTLS@
USE_MESALINK = @USE_MESALINK@
USE_NGHTTP2 = @USE_NGHTTP2@
USE_NGHTTP3 = @USE_NGHTTP3@
Changes to jni/curl/src/Makefile.in.
585
586
587
588
589
590
591

592
593
594
595
596
597
598
STRIP = @STRIP@
SUPPORT_FEATURES = @SUPPORT_FEATURES@
SUPPORT_PROTOCOLS = @SUPPORT_PROTOCOLS@
USE_ARES = @USE_ARES@
USE_BEARSSL = @USE_BEARSSL@
USE_GNUTLS = @USE_GNUTLS@
USE_GNUTLS_NETTLE = @USE_GNUTLS_NETTLE@

USE_LIBRTMP = @USE_LIBRTMP@
USE_LIBSSH = @USE_LIBSSH@
USE_LIBSSH2 = @USE_LIBSSH2@
USE_MBEDTLS = @USE_MBEDTLS@
USE_MESALINK = @USE_MESALINK@
USE_NGHTTP2 = @USE_NGHTTP2@
USE_NGHTTP3 = @USE_NGHTTP3@







>







585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
STRIP = @STRIP@
SUPPORT_FEATURES = @SUPPORT_FEATURES@
SUPPORT_PROTOCOLS = @SUPPORT_PROTOCOLS@
USE_ARES = @USE_ARES@
USE_BEARSSL = @USE_BEARSSL@
USE_GNUTLS = @USE_GNUTLS@
USE_GNUTLS_NETTLE = @USE_GNUTLS_NETTLE@
USE_HYPER = @USE_HYPER@
USE_LIBRTMP = @USE_LIBRTMP@
USE_LIBSSH = @USE_LIBSSH@
USE_LIBSSH2 = @USE_LIBSSH2@
USE_MBEDTLS = @USE_MBEDTLS@
USE_MESALINK = @USE_MESALINK@
USE_NGHTTP2 = @USE_NGHTTP2@
USE_NGHTTP3 = @USE_NGHTTP3@
Changes to jni/curl/src/makefile.dj.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#***************************************************************************
#                                  _   _ ____  _
#  Project                     ___| | | |  _ \| |
#                             / __| | | | |_) | |
#                            | (__| |_| |  _ <| |___
#                             \___|\___/|_| \_\_____|
#
# Copyright (C) 2003 - 2007, Gisle Vanem <gvanem@yahoo.no>.
# Copyright (C) 2003 - 2020, 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 https://curl.se/docs/copyright.html.
#
# You may opt to use, copy, modify, merge, publish, distribute and/or sell







|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#***************************************************************************
#                                  _   _ ____  _
#  Project                     ___| | | |  _ \| |
#                             / __| | | | |_) | |
#                            | (__| |_| |  _ <| |___
#                             \___|\___/|_| \_\_____|
#
# Copyright (C) 2003 - 2021, Gisle Vanem <gvanem@yahoo.no>.
# Copyright (C) 2003 - 2020, 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 https://curl.se/docs/copyright.html.
#
# You may opt to use, copy, modify, merge, publish, distribute and/or sell
24
25
26
27
28
29
30


31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66

67



68
69
70
71
72
73
74
75
76
77
#
#  Adapted for djgpp2 / Watt-32 / DOS
#

DEPEND_PREREQ = # tool_hugehelp.c

TOPDIR = ..



include ../packages/DOS/common.dj
include Makefile.inc

CSOURCES = $(CURL_CFILES)

ifeq ($(USE_SSL),1)
  EX_LIBS += $(OPENSSL_ROOT)/lib/libssl.a $(OPENSSL_ROOT)/lib/libcrypt.a
endif

ifeq ($(USE_ARES),1)
  EX_LIBS += $(ARES_ROOT)/libcares.a
endif

ifeq ($(USE_ZLIB),1)
  EX_LIBS += $(ZLIB_ROOT)/libz.a
  CFLAGS  += -DUSE_MANUAL
endif

ifeq ($(USE_IDNA),1)
  EX_LIBS += $(LIBIDN_ROOT)/lib/dj_obj/libidn.a -liconv
endif

EX_LIBS += $(WATT32_ROOT)/lib/libwatt.a

PROGRAM  = curl.exe
OBJECTS += $(addprefix $(OBJ_DIR)/, $(CSOURCES:.c=.o))

all: $(OBJ_DIR) $(PROGRAM)
	@echo Welcome to curl

$(PROGRAM): $(OBJECTS) ../lib/libcurl.a
	$(CC) -o $@ $^ $(LDFLAGS) $(EX_LIBS)

#
# groff 1.18+ requires "-P -c"

#



tool_hugehelp.c: ../docs/MANUAL ../docs/curl.1 mkhelp.pl
	groff -Tascii -man ../docs/curl.1 | \
	perl -w mkhelp.pl ../docs/MANUAL > $@

# clean generated files
#
genclean:
	- $(DELETE) tool_hugehelp.c

# clean object files and subdir







>
>




|

|
|

















|
|









>

>
>
>
|
|
|







24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
#
#  Adapted for djgpp2 / Watt-32 / DOS
#

DEPEND_PREREQ = # tool_hugehelp.c

TOPDIR = ..

vpath %.c ../lib

include ../packages/DOS/common.dj
include Makefile.inc

CSOURCES = $(CURL_CFILES) $(CURLX_CFILES)

ifeq ($(USE_OPENSSL),1)
  EX_LIBS += $(OPENSSL_LIBS)
endif

ifeq ($(USE_ARES),1)
  EX_LIBS += $(ARES_ROOT)/libcares.a
endif

ifeq ($(USE_ZLIB),1)
  EX_LIBS += $(ZLIB_ROOT)/libz.a
  CFLAGS  += -DUSE_MANUAL
endif

ifeq ($(USE_IDNA),1)
  EX_LIBS += $(LIBIDN_ROOT)/lib/dj_obj/libidn.a -liconv
endif

EX_LIBS += $(WATT32_ROOT)/lib/libwatt.a

PROGRAM = curl.exe
OBJECTS = $(addprefix $(OBJ_DIR)/, $(notdir $(CSOURCES:.c=.o)))

all: $(OBJ_DIR) $(PROGRAM)
	@echo Welcome to curl

$(PROGRAM): $(OBJECTS) ../lib/libcurl.a
	$(CC) -o $@ $^ $(LDFLAGS) $(EX_LIBS)

#
# groff 1.18+ requires "-P -c"
# If 'USE_ZLIB = 1', create a compressed help-file.
#
ifeq ($(USE_ZLIB),1)
  COMPRESS_OPT = -c
endif

tool_hugehelp.c: ../docs/curl.1 mkhelp.pl Makefile.dj
	groff -Tascii -man $< | perl -w mkhelp.pl $(COMPRESS_OPT) $< > $@

# clean generated files
#
genclean:
	- $(DELETE) tool_hugehelp.c

# clean object files and subdir
jni/curl/src/mkhelp.pl became executable.
Changes to jni/curl/src/tool_cb_rea.c.
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45

#include "memdebug.h" /* keep this as LAST include */

/*
** callback for CURLOPT_READFUNCTION
*/

size_t tool_read_cb(void *buffer, size_t sz, size_t nmemb, void *userdata)
{
  ssize_t rc;
  struct InStruct *in = userdata;

  rc = read(in->fd, buffer, sz*nmemb);
  if(rc < 0) {
    if(errno == EAGAIN) {







|







31
32
33
34
35
36
37
38
39
40
41
42
43
44
45

#include "memdebug.h" /* keep this as LAST include */

/*
** callback for CURLOPT_READFUNCTION
*/

size_t tool_read_cb(char *buffer, size_t sz, size_t nmemb, void *userdata)
{
  ssize_t rc;
  struct InStruct *in = userdata;

  rc = read(in->fd, buffer, sz*nmemb);
  if(rc < 0) {
    if(errno == EAGAIN) {
Changes to jni/curl/src/tool_cb_rea.h.
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
 ***************************************************************************/
#include "tool_setup.h"

/*
** callback for CURLOPT_READFUNCTION
*/

size_t tool_read_cb(void *buffer, size_t sz, size_t nmemb, void *userdata);

/*
** callback for CURLOPT_XFERINFOFUNCTION used to unpause busy reads
*/

int tool_readbusy_cb(void *clientp,
                     curl_off_t dltotal, curl_off_t dlnow,







|







23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
 ***************************************************************************/
#include "tool_setup.h"

/*
** callback for CURLOPT_READFUNCTION
*/

size_t tool_read_cb(char *buffer, size_t sz, size_t nmemb, void *userdata);

/*
** callback for CURLOPT_XFERINFOFUNCTION used to unpause busy reads
*/

int tool_readbusy_cb(void *clientp,
                     curl_off_t dltotal, curl_off_t dlnow,
Changes to jni/curl/src/tool_cfgable.c.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2020, 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 https://curl.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







|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2021, 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 https://curl.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
164
165
166
167
168
169
170


171
172
173
174
175
176
177

  Curl_safefree(config->preproxy);
  Curl_safefree(config->proxy_service_name);
  Curl_safefree(config->service_name);

  Curl_safefree(config->ftp_account);
  Curl_safefree(config->ftp_alternative_to_user);


}

void config_free(struct OperationConfig *config)
{
  struct OperationConfig *last = config;

  /* Free each of the structures in reverse order */







>
>







164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179

  Curl_safefree(config->preproxy);
  Curl_safefree(config->proxy_service_name);
  Curl_safefree(config->service_name);

  Curl_safefree(config->ftp_account);
  Curl_safefree(config->ftp_alternative_to_user);

  Curl_safefree(config->aws_sigv4);
}

void config_free(struct OperationConfig *config)
{
  struct OperationConfig *last = config;

  /* Free each of the structures in reverse order */
Changes to jni/curl/src/tool_cfgable.h.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#ifndef HEADER_CURL_TOOL_CFGABLE_H
#define HEADER_CURL_TOOL_CFGABLE_H
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2020, 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 https://curl.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









|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#ifndef HEADER_CURL_TOOL_CFGABLE_H
#define HEADER_CURL_TOOL_CFGABLE_H
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2021, 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 https://curl.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
189
190
191
192
193
194
195

196
197
198
199
200
201
202
  struct curl_slist *quote;
  struct curl_slist *postquote;
  struct curl_slist *prequote;
  long ssl_version;
  long ssl_version_max;
  long proxy_ssl_version;
  long ip_version;

  curl_TimeCond timecond;
  curl_off_t condtime;
  struct curl_slist *headers;
  struct curl_slist *proxyheaders;
  struct tool_mime *mimeroot;
  struct tool_mime *mimecurrent;
  curl_mime *mimepost;







>







189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
  struct curl_slist *quote;
  struct curl_slist *postquote;
  struct curl_slist *prequote;
  long ssl_version;
  long ssl_version_max;
  long proxy_ssl_version;
  long ip_version;
  long create_file_mode; /* CURLOPT_NEW_FILE_PERMS */
  curl_TimeCond timecond;
  curl_off_t condtime;
  struct curl_slist *headers;
  struct curl_slist *proxyheaders;
  struct tool_mime *mimeroot;
  struct tool_mime *mimecurrent;
  curl_mime *mimepost;
279
280
281
282
283
284
285

286
287
288
289
290
291
292
  curl_error synthetic_error;     /* if non-zero, it overrides any libcurl
                                     error */
  bool ssh_compression;           /* enable/disable SSH compression */
  long happy_eyeballs_timeout_ms; /* happy eyeballs timeout in milliseconds.
                                     0 is valid. default: CURL_HET_DEFAULT. */
  bool haproxy_protocol;          /* whether to send HAProxy protocol v1 */
  bool disallow_username_in_url;  /* disallow usernames in URLs */

  struct GlobalConfig *global;
  struct OperationConfig *prev;
  struct OperationConfig *next;   /* Always last in the struct */
  struct State state;             /* for create_transfer() */
};

struct GlobalConfig {







>







280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
  curl_error synthetic_error;     /* if non-zero, it overrides any libcurl
                                     error */
  bool ssh_compression;           /* enable/disable SSH compression */
  long happy_eyeballs_timeout_ms; /* happy eyeballs timeout in milliseconds.
                                     0 is valid. default: CURL_HET_DEFAULT. */
  bool haproxy_protocol;          /* whether to send HAProxy protocol v1 */
  bool disallow_username_in_url;  /* disallow usernames in URLs */
  char *aws_sigv4;
  struct GlobalConfig *global;
  struct OperationConfig *prev;
  struct OperationConfig *next;   /* Always last in the struct */
  struct State state;             /* for create_transfer() */
};

struct GlobalConfig {
Changes to jni/curl/src/tool_doswin.c.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2020, 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 https://curl.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







|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2021, 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 https://curl.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
24
25
26
27
28
29
30

31
32
33
34
35
36
37
#if defined(MSDOS) || defined(WIN32)

#if defined(HAVE_LIBGEN_H) && defined(HAVE_BASENAME)
#  include <libgen.h>
#endif

#ifdef WIN32

#  include <tlhelp32.h>
#  include "tool_cfgable.h"
#  include "tool_libinfo.h"
#endif

#include "tool_bname.h"
#include "tool_doswin.h"







>







24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
#if defined(MSDOS) || defined(WIN32)

#if defined(HAVE_LIBGEN_H) && defined(HAVE_BASENAME)
#  include <libgen.h>
#endif

#ifdef WIN32
#  include <stdlib.h>
#  include <tlhelp32.h>
#  include "tool_cfgable.h"
#  include "tool_libinfo.h"
#endif

#include "tool_bname.h"
#include "tool_doswin.h"
697
698
699
700
701
702
703


























































704
705
706
707
708
709
710
711
712
713
714
715
716



717
718
719
720
721
722
  curl_slist_free_all(slist);
  slist = NULL;
cleanup:
  if(hnd != INVALID_HANDLE_VALUE)
    CloseHandle(hnd);
  return slist;
}



























































LARGE_INTEGER tool_freq;
bool tool_isVistaOrGreater;

CURLcode win32_init(void)
{
  if(curlx_verify_windows_version(6, 0, PLATFORM_WINNT,
                                  VERSION_GREATER_THAN_EQUAL))
    tool_isVistaOrGreater = true;
  else
    tool_isVistaOrGreater = false;

  QueryPerformanceFrequency(&tool_freq);



  return CURLE_OK;
}

#endif /* WIN32 */

#endif /* MSDOS || WIN32 */







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>













>
>
>






698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
  curl_slist_free_all(slist);
  slist = NULL;
cleanup:
  if(hnd != INVALID_HANDLE_VALUE)
    CloseHandle(hnd);
  return slist;
}

/* The terminal settings to restore on exit */
static struct TerminalSettings {
  HANDLE hStdOut;
  DWORD dwOutputMode;
  LONG valid;
} TerminalSettings;

#ifndef ENABLE_VIRTUAL_TERMINAL_PROCESSING
#define ENABLE_VIRTUAL_TERMINAL_PROCESSING 0x0004
#endif

static void restore_terminal(void)
{
  if(InterlockedExchange(&TerminalSettings.valid, (LONG)FALSE))
    SetConsoleMode(TerminalSettings.hStdOut, TerminalSettings.dwOutputMode);
}

/* This is the console signal handler.
 * The system calls it in a separate thread.
 */
static BOOL WINAPI signal_handler(DWORD type)
{
  if(type == CTRL_C_EVENT || type == CTRL_BREAK_EVENT)
    restore_terminal();
  return FALSE;
}

static void init_terminal(void)
{
  TerminalSettings.hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
  /*
   * Enable VT (Virtual Terminal) output.
   * Note: VT mode flag can be set on any version of Windows, but VT
   * processing only performed on Win10 >= Creators Update)
   */
  if((TerminalSettings.hStdOut != INVALID_HANDLE_VALUE) &&
     GetConsoleMode(TerminalSettings.hStdOut,
                    &TerminalSettings.dwOutputMode) &&
     !(TerminalSettings.dwOutputMode &
       ENABLE_VIRTUAL_TERMINAL_PROCESSING)) {
    /* The signal handler is set before attempting to change the console mode
       because otherwise a signal would not be caught after the change but
       before the handler was installed. */
    (void)InterlockedExchange(&TerminalSettings.valid, (LONG)TRUE);
    if(SetConsoleCtrlHandler(signal_handler, TRUE)) {
      if(SetConsoleMode(TerminalSettings.hStdOut,
                        (TerminalSettings.dwOutputMode |
                         ENABLE_VIRTUAL_TERMINAL_PROCESSING))) {
        atexit(restore_terminal);
      }
      else {
        SetConsoleCtrlHandler(signal_handler, FALSE);
        (void)InterlockedExchange(&TerminalSettings.valid, (LONG)FALSE);
      }
    }
  }
}

LARGE_INTEGER tool_freq;
bool tool_isVistaOrGreater;

CURLcode win32_init(void)
{
  if(curlx_verify_windows_version(6, 0, PLATFORM_WINNT,
                                  VERSION_GREATER_THAN_EQUAL))
    tool_isVistaOrGreater = true;
  else
    tool_isVistaOrGreater = false;

  QueryPerformanceFrequency(&tool_freq);

  init_terminal();

  return CURLE_OK;
}

#endif /* WIN32 */

#endif /* MSDOS || WIN32 */
Changes to jni/curl/src/tool_filetime.c.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2020, 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 https://curl.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 "tool_filetime.h"


#include "curlx.h"

#ifdef HAVE_UTIME_H
#  include <utime.h>
#elif defined(HAVE_SYS_UTIME_H)
#  include <sys/utime.h>
#endif

#if defined(__GNUC__) && defined(__MINGW32__)
/* GCC 10 on mingw has issues with this, disable */
#pragma GCC diagnostic ignored "-Wformat"
#endif

curl_off_t getfiletime(const char *filename, FILE *error_stream)
{
  curl_off_t result = -1;

/* Windows stat() may attempt to adjust the unix GMT file time by a daylight
   saving time offset and since it's GMT that is bad behavior. When we have
   access to a 64-bit type we can bypass stat and get the times directly. */
#if defined(WIN32) && (SIZEOF_CURL_OFF_T >= 8)







|














|
>













|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2021, 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 https://curl.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 "tool_filetime.h"
#include "tool_cfgable.h"
#include "tool_msgs.h"
#include "curlx.h"

#ifdef HAVE_UTIME_H
#  include <utime.h>
#elif defined(HAVE_SYS_UTIME_H)
#  include <sys/utime.h>
#endif

#if defined(__GNUC__) && defined(__MINGW32__)
/* GCC 10 on mingw has issues with this, disable */
#pragma GCC diagnostic ignored "-Wformat"
#endif

curl_off_t getfiletime(const char *filename, struct GlobalConfig *global)
{
  curl_off_t result = -1;

/* Windows stat() may attempt to adjust the unix GMT file time by a daylight
   saving time offset and since it's GMT that is bad behavior. When we have
   access to a 64-bit type we can bypass stat and get the times directly. */
#if defined(WIN32) && (SIZEOF_CURL_OFF_T >= 8)
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
  if(hfile != INVALID_HANDLE_VALUE) {
    FILETIME ft;
    if(GetFileTime(hfile, NULL, NULL, &ft)) {
      curl_off_t converted = (curl_off_t)ft.dwLowDateTime
          | ((curl_off_t)ft.dwHighDateTime) << 32;

      if(converted < CURL_OFF_T_C(116444736000000000)) {
        fprintf(error_stream,
                "Failed to get filetime: underflow\n");
      }
      else {
        result = (converted - CURL_OFF_T_C(116444736000000000)) / 10000000;
      }
    }
    else {
      fprintf(error_stream,
              "Failed to get filetime: "
              "GetFileTime failed: GetLastError %u\n",
              (unsigned int)GetLastError());
    }
    CloseHandle(hfile);
  }
  else if(GetLastError() != ERROR_FILE_NOT_FOUND) {
    fprintf(error_stream,
            "Failed to get filetime: "
            "CreateFile failed: GetLastError %u\n",
            (unsigned int)GetLastError());
  }
#else
  struct_stat statbuf;
  if(-1 != stat(filename, &statbuf)) {
    result = (curl_off_t)statbuf.st_mtime;
  }
  else if(errno != ENOENT) {
    fprintf(error_stream,
            "Failed to get filetime: %s\n", strerror(errno));
  }
#endif
  return result;
}

#if defined(HAVE_UTIME) || defined(HAVE_UTIMES) || \
    (defined(WIN32) && (SIZEOF_CURL_OFF_T >= 8))
void setfiletime(curl_off_t filetime, const char *filename,
    FILE *error_stream)
{
  if(filetime >= 0) {
/* Windows utime() may attempt to adjust the unix GMT file time by a daylight
   saving time offset and since it's GMT that is bad behavior. When we have
   access to a 64-bit type we can bypass utime and set the times directly. */
#if defined(WIN32) && (SIZEOF_CURL_OFF_T >= 8)
    HANDLE hfile;
    TCHAR *tchar_filename = curlx_convert_UTF8_to_tchar((char *)filename);

    /* 910670515199 is the maximum unix filetime that can be used as a
       Windows FILETIME without overflow: 30827-12-31T23:59:59. */
    if(filetime > CURL_OFF_T_C(910670515199)) {
      fprintf(error_stream,
              "Failed to set filetime %" CURL_FORMAT_CURL_OFF_T
              " on outfile: overflow\n", filetime);
      curlx_unicodefree(tchar_filename);
      return;
    }

    hfile = CreateFile(tchar_filename, FILE_WRITE_ATTRIBUTES,
                        (FILE_SHARE_READ | FILE_SHARE_WRITE |
                         FILE_SHARE_DELETE),
                        NULL, OPEN_EXISTING, 0, NULL);
    curlx_unicodefree(tchar_filename);
    if(hfile != INVALID_HANDLE_VALUE) {
      curl_off_t converted = ((curl_off_t)filetime * 10000000) +
                             CURL_OFF_T_C(116444736000000000);
      FILETIME ft;
      ft.dwLowDateTime = (DWORD)(converted & 0xFFFFFFFF);
      ft.dwHighDateTime = (DWORD)(converted >> 32);
      if(!SetFileTime(hfile, NULL, &ft, &ft)) {
        fprintf(error_stream,
                "Failed to set filetime %" CURL_FORMAT_CURL_OFF_T
                " on outfile: SetFileTime failed: GetLastError %u\n",
                filetime, (unsigned int)GetLastError());
      }
      CloseHandle(hfile);
    }
    else {
      fprintf(error_stream,
              "Failed to set filetime %" CURL_FORMAT_CURL_OFF_T
              " on outfile: CreateFile failed: GetLastError %u\n",
              filetime, (unsigned int)GetLastError());
    }

#elif defined(HAVE_UTIMES)
    struct timeval times[2];
    times[0].tv_sec = times[1].tv_sec = (time_t)filetime;
    times[0].tv_usec = times[1].tv_usec = 0;
    if(utimes(filename, times)) {
      fprintf(error_stream,
              "Failed to set filetime %" CURL_FORMAT_CURL_OFF_T
              " on outfile: %s\n", filetime, strerror(errno));
    }

#elif defined(HAVE_UTIME)
    struct utimbuf times;
    times.actime = (time_t)filetime;
    times.modtime = (time_t)filetime;
    if(utime(filename, &times)) {
      fprintf(error_stream,
              "Failed to set filetime %" CURL_FORMAT_CURL_OFF_T
              " on outfile: %s\n", filetime, strerror(errno));
    }
#endif
  }
}
#endif /* defined(HAVE_UTIME) || defined(HAVE_UTIMES) || \
          (defined(WIN32) && (SIZEOF_CURL_OFF_T >= 8)) */







<
|






<
|
|
|




<
|
|
|







<
|





|
|

|












<
|
|





|
|
|



|




<
|
|
|




<
|
|
|







<
|
|







<
|
|






54
55
56
57
58
59
60

61
62
63
64
65
66
67

68
69
70
71
72
73
74

75
76
77
78
79
80
81
82
83
84

85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106

107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124

125
126
127
128
129
130
131

132
133
134
135
136
137
138
139
140
141

142
143
144
145
146
147
148
149
150

151
152
153
154
155
156
157
158
  if(hfile != INVALID_HANDLE_VALUE) {
    FILETIME ft;
    if(GetFileTime(hfile, NULL, NULL, &ft)) {
      curl_off_t converted = (curl_off_t)ft.dwLowDateTime
          | ((curl_off_t)ft.dwHighDateTime) << 32;

      if(converted < CURL_OFF_T_C(116444736000000000)) {

        warnf(global, "Failed to get filetime: underflow\n");
      }
      else {
        result = (converted - CURL_OFF_T_C(116444736000000000)) / 10000000;
      }
    }
    else {

      warnf(global, "Failed to get filetime: "
            "GetFileTime failed: GetLastError %u\n",
            (unsigned int)GetLastError());
    }
    CloseHandle(hfile);
  }
  else if(GetLastError() != ERROR_FILE_NOT_FOUND) {

    warnf(global, "Failed to get filetime: "
          "CreateFile failed: GetLastError %u\n",
          (unsigned int)GetLastError());
  }
#else
  struct_stat statbuf;
  if(-1 != stat(filename, &statbuf)) {
    result = (curl_off_t)statbuf.st_mtime;
  }
  else if(errno != ENOENT) {

    warnf(global, "Failed to get filetime: %s\n", strerror(errno));
  }
#endif
  return result;
}

#if defined(HAVE_UTIME) || defined(HAVE_UTIMES) ||      \
  (defined(WIN32) && (SIZEOF_CURL_OFF_T >= 8))
void setfiletime(curl_off_t filetime, const char *filename,
                 struct GlobalConfig *global)
{
  if(filetime >= 0) {
/* Windows utime() may attempt to adjust the unix GMT file time by a daylight
   saving time offset and since it's GMT that is bad behavior. When we have
   access to a 64-bit type we can bypass utime and set the times directly. */
#if defined(WIN32) && (SIZEOF_CURL_OFF_T >= 8)
    HANDLE hfile;
    TCHAR *tchar_filename = curlx_convert_UTF8_to_tchar((char *)filename);

    /* 910670515199 is the maximum unix filetime that can be used as a
       Windows FILETIME without overflow: 30827-12-31T23:59:59. */
    if(filetime > CURL_OFF_T_C(910670515199)) {

      warnf(global, "Failed to set filetime %" CURL_FORMAT_CURL_OFF_T
            " on outfile: overflow\n", filetime);
      curlx_unicodefree(tchar_filename);
      return;
    }

    hfile = CreateFile(tchar_filename, FILE_WRITE_ATTRIBUTES,
                       (FILE_SHARE_READ | FILE_SHARE_WRITE |
                        FILE_SHARE_DELETE),
                       NULL, OPEN_EXISTING, 0, NULL);
    curlx_unicodefree(tchar_filename);
    if(hfile != INVALID_HANDLE_VALUE) {
      curl_off_t converted = ((curl_off_t)filetime * 10000000) +
        CURL_OFF_T_C(116444736000000000);
      FILETIME ft;
      ft.dwLowDateTime = (DWORD)(converted & 0xFFFFFFFF);
      ft.dwHighDateTime = (DWORD)(converted >> 32);
      if(!SetFileTime(hfile, NULL, &ft, &ft)) {

        warnf(global, "Failed to set filetime %" CURL_FORMAT_CURL_OFF_T
              " on outfile: SetFileTime failed: GetLastError %u\n",
              filetime, (unsigned int)GetLastError());
      }
      CloseHandle(hfile);
    }
    else {

      warnf(global, "Failed to set filetime %" CURL_FORMAT_CURL_OFF_T
            " on outfile: CreateFile failed: GetLastError %u\n",
            filetime, (unsigned int)GetLastError());
    }

#elif defined(HAVE_UTIMES)
    struct timeval times[2];
    times[0].tv_sec = times[1].tv_sec = (time_t)filetime;
    times[0].tv_usec = times[1].tv_usec = 0;
    if(utimes(filename, times)) {

      warnf(global, "Failed to set filetime %" CURL_FORMAT_CURL_OFF_T
            " on '%s': %s\n", filetime, filename, strerror(errno));
    }

#elif defined(HAVE_UTIME)
    struct utimbuf times;
    times.actime = (time_t)filetime;
    times.modtime = (time_t)filetime;
    if(utime(filename, &times)) {

      warnf(global, "Failed to set filetime %" CURL_FORMAT_CURL_OFF_T
            " on '%s': %s\n", filetime, filename, strerror(errno));
    }
#endif
  }
}
#endif /* defined(HAVE_UTIME) || defined(HAVE_UTIMES) || \
          (defined(WIN32) && (SIZEOF_CURL_OFF_T >= 8)) */
Changes to jni/curl/src/tool_filetime.h.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25


26
27
28
29
30
31
32
33
34
35
36
37
#ifndef HEADER_CURL_TOOL_FILETIME_H
#define HEADER_CURL_TOOL_FILETIME_H
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2020, 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 https://curl.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 "tool_setup.h"



curl_off_t getfiletime(const char *filename, FILE *error_stream);

#if defined(HAVE_UTIME) || defined(HAVE_UTIMES) || \
    (defined(WIN32) && (SIZEOF_CURL_OFF_T >= 8))
void setfiletime(curl_off_t filetime, const char *filename,
    FILE *error_stream);
#else
#define setfiletime(a,b,c) Curl_nop_stmt
#endif /* defined(HAVE_UTIME) || defined(HAVE_UTIMES) || \
          (defined(WIN32) && (SIZEOF_CURL_OFF_T >= 8)) */

#endif /* HEADER_CURL_TOOL_FILETIME_H */









|















>
>
|

|
|

|


|



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
#ifndef HEADER_CURL_TOOL_FILETIME_H
#define HEADER_CURL_TOOL_FILETIME_H
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2021, 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 https://curl.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 "tool_setup.h"

struct GlobalConfig;

curl_off_t getfiletime(const char *filename, struct GlobalConfig *global);

#if defined(HAVE_UTIME) || defined(HAVE_UTIMES) ||      \
  (defined(WIN32) && (SIZEOF_CURL_OFF_T >= 8))
void setfiletime(curl_off_t filetime, const char *filename,
                 struct GlobalConfig *global);
#else
#define setfiletime(a,b,c) Curl_nop_stmt
#endif /* defined(HAVE_UTIME) || defined(HAVE_UTIMES) ||        \
          (defined(WIN32) && (SIZEOF_CURL_OFF_T >= 8)) */

#endif /* HEADER_CURL_TOOL_FILETIME_H */
Changes to jni/curl/src/tool_formparse.c.
716
717
718
719
720
721
722
723

724
725
726
727
728
729
730

731
732

733
734
735
736
737
738
739
740
741
742
 * If filename/path contains ',' or ';', it must be quoted by double-quotes,
 * else curl will fail to figure out the correct filename. if the filename
 * tobe quoted contains '"' or '\', '"' and '\' must be escaped by backslash.
 *
 ***************************************************************************/

/* Convenience macros for null pointer check. */
#define NULL_CHECK(ptr, init, retcode) {                                \

  (ptr) = (init);                                                       \
  if(!(ptr)) {                                                          \
    warnf(config->global, "out of memory!\n");                          \
    curl_slist_free_all(headers);                                       \
    Curl_safefree(contents);                                            \
    return retcode;                                                     \
  }                                                                     \

}
#define SET_TOOL_MIME_PTR(m, field, retcode) {                          \

  if(field)                                                             \
    NULL_CHECK((m)->field, strdup(field), retcode);                     \
}

int formparse(struct OperationConfig *config,
              const char *input,
              struct tool_mime **mimeroot,
              struct tool_mime **mimecurrent,
              bool literal_value)
{







|
>
|
|
|
|
|
|
|
>
|
|
>
|
|
|







716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
 * If filename/path contains ',' or ';', it must be quoted by double-quotes,
 * else curl will fail to figure out the correct filename. if the filename
 * tobe quoted contains '"' or '\', '"' and '\' must be escaped by backslash.
 *
 ***************************************************************************/

/* Convenience macros for null pointer check. */
#define NULL_CHECK(ptr, init, retcode)                                  \
  do {                                                                  \
    (ptr) = (init);                                                     \
    if(!(ptr)) {                                                        \
      warnf(config->global, "out of memory!\n");                        \
      curl_slist_free_all(headers);                                     \
      Curl_safefree(contents);                                          \
      return retcode;                                                   \
    }                                                                   \
  } while(0)

#define SET_TOOL_MIME_PTR(m, field, retcode)                            \
  do {                                                                  \
    if(field)                                                           \
      NULL_CHECK((m)->field, strdup(field), retcode);                   \
  } while(0)

int formparse(struct OperationConfig *config,
              const char *input,
              struct tool_mime **mimeroot,
              struct tool_mime **mimecurrent,
              bool literal_value)
{
Changes to jni/curl/src/tool_getparam.c.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2020, 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 https://curl.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







|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2021, 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 https://curl.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
104
105
106
107
108
109
110

111
112
113
114

115
116
117
118
119
120
121
  {"*n", "basic",                    ARG_BOOL},
  {"*o", "anyauth",                  ARG_BOOL},
#ifdef USE_WATT32
  {"*p", "wdebug",                   ARG_BOOL},
#endif
  {"*q", "ftp-create-dirs",          ARG_BOOL},
  {"*r", "create-dirs",              ARG_BOOL},

  {"*s", "max-redirs",               ARG_STRING},
  {"*t", "proxy-ntlm",               ARG_BOOL},
  {"*u", "crlf",                     ARG_BOOL},
  {"*v", "stderr",                   ARG_FILENAME},

  {"*w", "interface",                ARG_STRING},
  {"*x", "krb",                      ARG_STRING},
  {"*x", "krb4",                     ARG_STRING},
         /* 'krb4' is the previous name */
  {"*X", "haproxy-protocol",         ARG_BOOL},
  {"*y", "max-filesize",             ARG_STRING},
  {"*z", "disable-eprt",             ARG_BOOL},







>




>







104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
  {"*n", "basic",                    ARG_BOOL},
  {"*o", "anyauth",                  ARG_BOOL},
#ifdef USE_WATT32
  {"*p", "wdebug",                   ARG_BOOL},
#endif
  {"*q", "ftp-create-dirs",          ARG_BOOL},
  {"*r", "create-dirs",              ARG_BOOL},
  {"*R", "create-file-mode",         ARG_STRING},
  {"*s", "max-redirs",               ARG_STRING},
  {"*t", "proxy-ntlm",               ARG_BOOL},
  {"*u", "crlf",                     ARG_BOOL},
  {"*v", "stderr",                   ARG_FILENAME},
  {"*V", "aws-sigv4",                ARG_STRING},
  {"*w", "interface",                ARG_STRING},
  {"*x", "krb",                      ARG_STRING},
  {"*x", "krb4",                     ARG_STRING},
         /* 'krb4' is the previous name */
  {"*X", "haproxy-protocol",         ARG_BOOL},
  {"*y", "max-filesize",             ARG_STRING},
  {"*z", "disable-eprt",             ARG_BOOL},
769
770
771
772
773
774
775






776
777
778
779
780
781
782
      case 'q': /* --ftp-create-dirs */
        config->ftp_create_dirs = toggle;
        break;

      case 'r': /* --create-dirs */
        config->create_dirs = toggle;
        break;







      case 's': /* --max-redirs */
        /* specified max no of redirects (http(s)), this accepts -1 as a
           special condition */
        err = str2num(&config->maxredirs, nextarg);
        if(err)
          return err;







>
>
>
>
>
>







771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
      case 'q': /* --ftp-create-dirs */
        config->ftp_create_dirs = toggle;
        break;

      case 'r': /* --create-dirs */
        config->create_dirs = toggle;
        break;

      case 'R': /* --create-file-mode */
        err = oct2nummax(&config->create_file_mode, nextarg, 0777);
        if(err)
          return err;
        break;

      case 's': /* --max-redirs */
        /* specified max no of redirects (http(s)), this accepts -1 as a
           special condition */
        err = str2num(&config->maxredirs, nextarg);
        if(err)
          return err;
791
792
793
794
795
796
797





798
799
800
801
802
803
804
          return PARAM_LIBCURL_DOESNT_SUPPORT;
        break;

      case 'u': /* --crlf */
        /* LF -> CRLF conversion? */
        config->crlf = toggle;
        break;






      case 'v': /* --stderr */
        if(strcmp(nextarg, "-")) {
          FILE *newfile = fopen(nextarg, FOPEN_WRITETEXT);
          if(!newfile)
            warnf(global, "Failed to open %s!\n", nextarg);
          else {







>
>
>
>
>







799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
          return PARAM_LIBCURL_DOESNT_SUPPORT;
        break;

      case 'u': /* --crlf */
        /* LF -> CRLF conversion? */
        config->crlf = toggle;
        break;

      case 'V': /* --aws-sigv4 */
        config->authtype |= CURLAUTH_AWS_SIGV4;
        GetStr(&config->aws_sigv4, nextarg);
        break;

      case 'v': /* --stderr */
        if(strcmp(nextarg, "-")) {
          FILE *newfile = fopen(nextarg, FOPEN_WRITETEXT);
          if(!newfile)
            warnf(global, "Failed to open %s!\n", nextarg);
          else {
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
      url->flags |= GETOUT_OUTFILE;
    }
    break;
    case 'P':
      /* This makes the FTP sessions use PORT instead of PASV */
      /* use <eth0> or <192.168.10.10> style addresses. Anything except
         this will make us try to get the "default" address.
         NOTE: this is a changed behaviour since the released 4.1!
      */
      GetStr(&config->ftpport, nextarg);
      break;
    case 'p':
      /* proxy tunnel for non-http protocols */
      config->proxytunnel = toggle;
      break;







|







1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
      url->flags |= GETOUT_OUTFILE;
    }
    break;
    case 'P':
      /* This makes the FTP sessions use PORT instead of PASV */
      /* use <eth0> or <192.168.10.10> style addresses. Anything except
         this will make us try to get the "default" address.
         NOTE: this is a changed behavior since the released 4.1!
      */
      GetStr(&config->ftpport, nextarg);
      break;
    case 'p':
      /* proxy tunnel for non-http protocols */
      config->proxytunnel = toggle;
      break;
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
        nextarg++;
        break;
      }
      now = time(NULL);
      config->condtime = (curl_off_t)curl_getdate(nextarg, &now);
      if(-1 == config->condtime) {
        /* now let's see if it is a file name to get the time from instead! */
        curl_off_t filetime = getfiletime(nextarg, config->global->errors);
        if(filetime >= 0) {
          /* pull the time out from the file */
          config->condtime = filetime;
        }
        else {
          /* failed, remove time condition */
          config->timecond = CURL_TIMECOND_NONE;







|







2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
        nextarg++;
        break;
      }
      now = time(NULL);
      config->condtime = (curl_off_t)curl_getdate(nextarg, &now);
      if(-1 == config->condtime) {
        /* now let's see if it is a file name to get the time from instead! */
        curl_off_t filetime = getfiletime(nextarg, global);
        if(filetime >= 0) {
          /* pull the time out from the file */
          config->condtime = filetime;
        }
        else {
          /* failed, remove time condition */
          config->timecond = CURL_TIMECOND_NONE;
Changes to jni/curl/src/tool_help.c.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2020, 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 https://curl.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







|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2021, 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 https://curl.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
129
130
131
132
133
134
135



136
137
138
139
140
141
142
   CURLHELP_HTTP},
  {"    --anyauth",
   "Pick any authentication method",
   CURLHELP_HTTP | CURLHELP_PROXY | CURLHELP_AUTH},
  {"-a, --append",
   "Append to target file when uploading",
   CURLHELP_FTP | CURLHELP_SFTP},



  {"    --basic",
   "Use HTTP Basic Authentication",
   CURLHELP_AUTH},
  {"    --cacert <file>",
   "CA certificate to verify peer against",
   CURLHELP_TLS},
  {"    --capath <dir>",







>
>
>







129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
   CURLHELP_HTTP},
  {"    --anyauth",
   "Pick any authentication method",
   CURLHELP_HTTP | CURLHELP_PROXY | CURLHELP_AUTH},
  {"-a, --append",
   "Append to target file when uploading",
   CURLHELP_FTP | CURLHELP_SFTP},
  {"    --aws-sigv4 <provider1[:provider2[:region[:service]]]>",
   "Use AWS V4 signature authentication",
   CURLHELP_AUTH | CURLHELP_HTTP},
  {"    --basic",
   "Use HTTP Basic Authentication",
   CURLHELP_AUTH},
  {"    --cacert <file>",
   "CA certificate to verify peer against",
   CURLHELP_TLS},
  {"    --capath <dir>",
177
178
179
180
181
182
183



184
185
186
187
188
189
190
   CURLHELP_HTTP},
  {"-c, --cookie-jar <filename>",
   "Write cookies to <filename> after operation",
   CURLHELP_HTTP},
  {"    --create-dirs",
   "Create necessary local directory hierarchy",
   CURLHELP_CURL},



  {"    --crlf",
   "Convert LF to CRLF in upload",
   CURLHELP_FTP | CURLHELP_SMTP},
  {"    --crlfile <file>",
   "Get a CRL list in PEM format from the given file",
   CURLHELP_TLS},
  {"    --curves <algorithm list>",







>
>
>







180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
   CURLHELP_HTTP},
  {"-c, --cookie-jar <filename>",
   "Write cookies to <filename> after operation",
   CURLHELP_HTTP},
  {"    --create-dirs",
   "Create necessary local directory hierarchy",
   CURLHELP_CURL},
  {"    --create-file-mode",
   "File mode for created files",
   CURLHELP_SFTP | CURLHELP_SCP | CURLHELP_FILE | CURLHELP_UPLOAD},
  {"    --crlf",
   "Convert LF to CRLF in upload",
   CURLHELP_FTP | CURLHELP_SMTP},
  {"    --crlfile <file>",
   "Get a CRL list in PEM format from the given file",
   CURLHELP_TLS},
  {"    --curves <algorithm list>",
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
   CURLHELP_OUTPUT},
  {"-X, --request <command>",
   "Specify request command to use",
   CURLHELP_CONNECTION},
  {"    --request-target",
   "Specify the target for this request",
   CURLHELP_HTTP},
  {"    --resolve <host:port:addr[,addr]...>",
   "Resolve the host+port to this address",
   CURLHELP_CONNECTION},
  {"    --retry <num>",
   "Retry request if transient problems occur",
   CURLHELP_CURL},
  {"    --retry-all-errors",
   "Retry all errors (use with --retry)",







|







645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
   CURLHELP_OUTPUT},
  {"-X, --request <command>",
   "Specify request command to use",
   CURLHELP_CONNECTION},
  {"    --request-target",
   "Specify the target for this request",
   CURLHELP_HTTP},
  {"    --resolve <[+]host:port:addr[,addr]...>",
   "Resolve the host+port to this address",
   CURLHELP_CONNECTION},
  {"    --retry <num>",
   "Retry request if transient problems occur",
   CURLHELP_CURL},
  {"    --retry-all-errors",
   "Retry all errors (use with --retry)",
Changes to jni/curl/src/tool_hugehelp.c.

more than 10,000 changes

Changes to jni/curl/src/tool_libinfo.c.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2020, 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 https://curl.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







|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2021, 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 https://curl.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
51
52
53
54
55
56
57

58
59
60
61
62
63

64
65
66

67
68
69
70
71
72
73
    long        proto_pattern;
  } const possibly_built_in[] = {
    { "dict",   CURLPROTO_DICT   },
    { "file",   CURLPROTO_FILE   },
    { "ftp",    CURLPROTO_FTP    },
    { "ftps",   CURLPROTO_FTPS   },
    { "gopher", CURLPROTO_GOPHER },

    { "http",   CURLPROTO_HTTP   },
    { "https",  CURLPROTO_HTTPS  },
    { "imap",   CURLPROTO_IMAP   },
    { "imaps",  CURLPROTO_IMAPS  },
    { "ldap",   CURLPROTO_LDAP   },
    { "ldaps",  CURLPROTO_LDAPS  },

    { "pop3",   CURLPROTO_POP3   },
    { "pop3s",  CURLPROTO_POP3S  },
    { "rtmp",   CURLPROTO_RTMP   },

    { "rtsp",   CURLPROTO_RTSP   },
    { "scp",    CURLPROTO_SCP    },
    { "sftp",   CURLPROTO_SFTP   },
    { "smb",    CURLPROTO_SMB    },
    { "smbs",   CURLPROTO_SMBS   },
    { "smtp",   CURLPROTO_SMTP   },
    { "smtps",  CURLPROTO_SMTPS  },







>






>



>







51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
    long        proto_pattern;
  } const possibly_built_in[] = {
    { "dict",   CURLPROTO_DICT   },
    { "file",   CURLPROTO_FILE   },
    { "ftp",    CURLPROTO_FTP    },
    { "ftps",   CURLPROTO_FTPS   },
    { "gopher", CURLPROTO_GOPHER },
    { "gophers",CURLPROTO_GOPHERS},
    { "http",   CURLPROTO_HTTP   },
    { "https",  CURLPROTO_HTTPS  },
    { "imap",   CURLPROTO_IMAP   },
    { "imaps",  CURLPROTO_IMAPS  },
    { "ldap",   CURLPROTO_LDAP   },
    { "ldaps",  CURLPROTO_LDAPS  },
    { "mqtt",   CURLPROTO_MQTT   },
    { "pop3",   CURLPROTO_POP3   },
    { "pop3s",  CURLPROTO_POP3S  },
    { "rtmp",   CURLPROTO_RTMP   },
    { "rtmps",  CURLPROTO_RTMPS  },
    { "rtsp",   CURLPROTO_RTSP   },
    { "scp",    CURLPROTO_SCP    },
    { "sftp",   CURLPROTO_SFTP   },
    { "smb",    CURLPROTO_SMB    },
    { "smbs",   CURLPROTO_SMBS   },
    { "smtp",   CURLPROTO_SMTP   },
    { "smtps",  CURLPROTO_SMTPS  },
Changes to jni/curl/src/tool_main.c.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24




25
26
27
28
29
30
31
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2020, 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 https://curl.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 "tool_setup.h"

#include <sys/stat.h>





#ifdef HAVE_SIGNAL_H
#include <signal.h>
#endif

#ifdef USE_NSS
#include <nspr.h>







|
















>
>
>
>







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2021, 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 https://curl.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 "tool_setup.h"

#include <sys/stat.h>

#ifdef WIN32
#include <tchar.h>
#endif

#ifdef HAVE_SIGNAL_H
#include <signal.h>
#endif

#ifdef USE_NSS
#include <nspr.h>
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344

  /* Free the config structures */
  config_free(config->last);
  config->first = NULL;
  config->last = NULL;
}

#ifdef WIN32
/* TerminalSettings for Windows */
static struct TerminalSettings {
  HANDLE hStdOut;
  DWORD dwOutputMode;
} TerminalSettings;

static void configure_terminal(void)
{
  /*
   * If we're running Windows, enable VT output.
   * Note: VT mode flag can be set on any version of Windows, but VT
   * processing only performed on Win10 >= Creators Update)
   */

  /* Define the VT flags in case we're building with an older SDK */
#ifndef ENABLE_VIRTUAL_TERMINAL_PROCESSING
    #define ENABLE_VIRTUAL_TERMINAL_PROCESSING 0x0004
#endif

  memset(&TerminalSettings, 0, sizeof(TerminalSettings));

  /* Enable VT output */
  TerminalSettings.hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
  if((TerminalSettings.hStdOut != INVALID_HANDLE_VALUE)
    && (GetConsoleMode(TerminalSettings.hStdOut,
                       &TerminalSettings.dwOutputMode))) {
    SetConsoleMode(TerminalSettings.hStdOut,
                   TerminalSettings.dwOutputMode
                   | ENABLE_VIRTUAL_TERMINAL_PROCESSING);
  }
}
#else
#define configure_terminal()
#endif

static void restore_terminal(void)
{
#ifdef WIN32
  /* Restore Console output mode and codepage to whatever they were
   * when Curl started */
  SetConsoleMode(TerminalSettings.hStdOut, TerminalSettings.dwOutputMode);
#endif
}

/*
** curl tool main function.
*/
#ifdef _UNICODE
int wmain(int argc, wchar_t *argv[])
#else
int main(int argc, char *argv[])
#endif
{
  CURLcode result = CURLE_OK;
  struct GlobalConfig global;
  memset(&global, 0, sizeof(global));

#ifdef WIN32
#ifdef _tcscmp
  /* Undocumented diagnostic option to list the full paths of all loaded
     modules. This is purposely pre-init. */
  if(argc == 2 && !_tcscmp(argv[1], _T("--dump-module-paths"))) {
    struct curl_slist *item, *head = GetLoadedModulePaths();
    for(item = head; item; item = item->next)
      printf("%s\n", item->data);
    curl_slist_free_all(head);
    return head ? 0 : 1;
  }
#endif /* _tcscmp */
  /* win32_init must be called before other init routines. */
  result = win32_init();
  if(result) {
    fprintf(stderr, "curl: (%d) Windows-specific init failed.\n", result);
    return result;
  }
#endif

  /* Perform any platform-specific terminal configuration */
  configure_terminal();

  main_checkfds();

#if defined(HAVE_SIGNAL) && defined(SIGPIPE)
  (void)signal(SIGPIPE, SIG_IGN);
#endif

  /* Initialize memory tracking */
  memory_tracking_init();

  /* Initialize the curl library - do not call any libcurl functions before
     this point */
  result = main_init(&global);
  if(!result) {
    /* Start our curl operation */
    result = operate(&global, argc, argv);

    /* Perform the main cleanup */
    main_free(&global);
  }

  /* Return the terminal to its original state */
  restore_terminal();

#ifdef __NOVELL_LIBC__
  if(getenv("_IN_NETWARE_BASH_") == NULL)
    tool_pressanykey();
#endif

#ifdef __VMS
  vms_special_exit(result, vms_show);
#else
  return (int)result;
#endif
}

#endif /* ndef UNITTESTS */







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<














<









<








<
<
<




















<
<
<













225
226
227
228
229
230
231













































232
233
234
235
236
237
238
239
240
241
242
243
244
245

246
247
248
249
250
251
252
253
254

255
256
257
258
259
260
261
262



263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282



283
284
285
286
287
288
289
290
291
292
293
294
295

  /* Free the config structures */
  config_free(config->last);
  config->first = NULL;
  config->last = NULL;
}














































/*
** curl tool main function.
*/
#ifdef _UNICODE
int wmain(int argc, wchar_t *argv[])
#else
int main(int argc, char *argv[])
#endif
{
  CURLcode result = CURLE_OK;
  struct GlobalConfig global;
  memset(&global, 0, sizeof(global));

#ifdef WIN32

  /* Undocumented diagnostic option to list the full paths of all loaded
     modules. This is purposely pre-init. */
  if(argc == 2 && !_tcscmp(argv[1], _T("--dump-module-paths"))) {
    struct curl_slist *item, *head = GetLoadedModulePaths();
    for(item = head; item; item = item->next)
      printf("%s\n", item->data);
    curl_slist_free_all(head);
    return head ? 0 : 1;
  }

  /* win32_init must be called before other init routines. */
  result = win32_init();
  if(result) {
    fprintf(stderr, "curl: (%d) Windows-specific init failed.\n", result);
    return result;
  }
#endif




  main_checkfds();

#if defined(HAVE_SIGNAL) && defined(SIGPIPE)
  (void)signal(SIGPIPE, SIG_IGN);
#endif

  /* Initialize memory tracking */
  memory_tracking_init();

  /* Initialize the curl library - do not call any libcurl functions before
     this point */
  result = main_init(&global);
  if(!result) {
    /* Start our curl operation */
    result = operate(&global, argc, argv);

    /* Perform the main cleanup */
    main_free(&global);
  }




#ifdef __NOVELL_LIBC__
  if(getenv("_IN_NETWARE_BASH_") == NULL)
    tool_pressanykey();
#endif

#ifdef __VMS
  vms_special_exit(result, vms_show);
#else
  return (int)result;
#endif
}

#endif /* ndef UNITTESTS */
Changes to jni/curl/src/tool_operate.c.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2020, 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 https://curl.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







|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2021, 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 https://curl.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
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401

402
403
404
405
406
407
408
409
  if(is_vms_shell()) {
    /* VMS DCL shell behavior */
    if(!global->showerror)
      vms_show = VMSSTS_HIDE;
  }
  else
#endif
    if(config->synthetic_error) {
      ;
    }
    else if(result && global->showerror) {
      fprintf(global->errors, "curl: (%d) %s\n", result,
              (per->errorbuffer[0]) ? per->errorbuffer :
              curl_easy_strerror(result));
      if(result == CURLE_PEER_FAILED_VERIFICATION)
        fputs(CURL_CA_CERT_ERRORMSG, global->errors);
    }

  /* Set file extended attributes */
  if(!result && config->xattr && outs->fopened && outs->stream) {
    int rc = fwrite_xattr(curl, fileno(outs->stream));
    if(rc)
      warnf(config->global, "Error setting extended attributes: %s\n",
            strerror(errno));
  }

  if(!result && !outs->stream && !outs->bytes) {
    /* we have received no data despite the transfer was successful
       ==> force cration of an empty output file (if an output file
       was specified) */
    long cond_unmet = 0L;
    /* do not create (or even overwrite) the file in case we get no
       data because of unmet condition */
    curl_easy_getinfo(curl, CURLINFO_CONDITION_UNMET, &cond_unmet);
    if(!cond_unmet && !tool_create_output_file(outs, config))
      result = CURLE_WRITE_ERROR;
  }

  if(!outs->s_isreg && outs->stream) {
    /* Dump standard stream buffered data */
    int rc = fflush(outs->stream);
    if(!result && rc) {
      /* something went wrong in the writing process */
      result = CURLE_WRITE_ERROR;

      fprintf(global->errors, "(%d) Failed writing body\n", result);
    }
  }

#ifdef USE_METALINK
  if(per->metalink && !per->metalink_next_res)
    fprintf(global->errors, "Metalink: fetching (%s) from (%s) OK\n",
            per->mlfile->filename, per->this_url);







<
<
<
|











|
|




|















>
|







358
359
360
361
362
363
364



365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
  if(is_vms_shell()) {
    /* VMS DCL shell behavior */
    if(!global->showerror)
      vms_show = VMSSTS_HIDE;
  }
  else
#endif



    if(!config->synthetic_error && result && global->showerror) {
      fprintf(global->errors, "curl: (%d) %s\n", result,
              (per->errorbuffer[0]) ? per->errorbuffer :
              curl_easy_strerror(result));
      if(result == CURLE_PEER_FAILED_VERIFICATION)
        fputs(CURL_CA_CERT_ERRORMSG, global->errors);
    }

  /* Set file extended attributes */
  if(!result && config->xattr && outs->fopened && outs->stream) {
    int rc = fwrite_xattr(curl, fileno(outs->stream));
    if(rc)
      warnf(config->global, "Error setting extended attributes on '%s': %s\n",
            outs->filename, strerror(errno));
  }

  if(!result && !outs->stream && !outs->bytes) {
    /* we have received no data despite the transfer was successful
       ==> force creation of an empty output file (if an output file
       was specified) */
    long cond_unmet = 0L;
    /* do not create (or even overwrite) the file in case we get no
       data because of unmet condition */
    curl_easy_getinfo(curl, CURLINFO_CONDITION_UNMET, &cond_unmet);
    if(!cond_unmet && !tool_create_output_file(outs, config))
      result = CURLE_WRITE_ERROR;
  }

  if(!outs->s_isreg && outs->stream) {
    /* Dump standard stream buffered data */
    int rc = fflush(outs->stream);
    if(!result && rc) {
      /* something went wrong in the writing process */
      result = CURLE_WRITE_ERROR;
      if(global->showerror)
        fprintf(global->errors, "curl: (%d) Failed writing body\n", result);
    }
  }

#ifdef USE_METALINK
  if(per->metalink && !per->metalink_next_res)
    fprintf(global->errors, "Metalink: fetching (%s) from (%s) OK\n",
            per->mlfile->filename, per->this_url);
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
                  outs->bytes);
        fflush(outs->stream);
        /* truncate file at the position where we started appending */
#ifdef HAVE_FTRUNCATE
        if(ftruncate(fileno(outs->stream), outs->init)) {
          /* when truncate fails, we can't just append as then we'll
             create something strange, bail out */
          if(!global->mute)
            fprintf(global->errors,
                    "failed to truncate, exiting\n");
          return CURLE_WRITE_ERROR;
        }
        /* now seek to the end of the file, the position where we
           just truncated the file in a large file-safe way */
        rc = fseek(outs->stream, 0, SEEK_END);
#else
        /* ftruncate is not available, so just reposition the file
           to the location we would have truncated it. This won't
           work properly with large files on 32-bit systems, but
           most of those will have ftruncate. */
        rc = fseek(outs->stream, (long)outs->init, SEEK_SET);
#endif
        if(rc) {
          if(!global->mute)
            fprintf(global->errors,
                    "failed seeking to end of file, exiting\n");
          return CURLE_WRITE_ERROR;
        }
        outs->bytes = 0; /* clear for next round */
      }
      *retryp = TRUE;
      *delay = sleeptime;
      return CURLE_OK;







|

|













|

|







556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
                  outs->bytes);
        fflush(outs->stream);
        /* truncate file at the position where we started appending */
#ifdef HAVE_FTRUNCATE
        if(ftruncate(fileno(outs->stream), outs->init)) {
          /* when truncate fails, we can't just append as then we'll
             create something strange, bail out */
          if(global->showerror)
            fprintf(global->errors,
                    "curl: (23) Failed to truncate file\n");
          return CURLE_WRITE_ERROR;
        }
        /* now seek to the end of the file, the position where we
           just truncated the file in a large file-safe way */
        rc = fseek(outs->stream, 0, SEEK_END);
#else
        /* ftruncate is not available, so just reposition the file
           to the location we would have truncated it. This won't
           work properly with large files on 32-bit systems, but
           most of those will have ftruncate. */
        rc = fseek(outs->stream, (long)outs->init, SEEK_SET);
#endif
        if(rc) {
          if(global->showerror)
            fprintf(global->errors,
                    "curl: (23) Failed seeking to end of file\n");
          return CURLE_WRITE_ERROR;
        }
        outs->bytes = 0; /* clear for next round */
      }
      *retryp = TRUE;
      *delay = sleeptime;
      return CURLE_OK;
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638

639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
  if((global->progressmode == CURL_PROGRESS_BAR) &&
     per->progressbar.calls)
    /* if the custom progress bar has been displayed, we output a
       newline here */
    fputs("\n", per->progressbar.out);

  if(config->writeout)
    ourWriteOut(per->curl, per, config->writeout);

  /* Close the outs file */
  if(outs->fopened && outs->stream) {
    int rc = fclose(outs->stream);
    if(!result && rc) {
      /* something went wrong in the writing process */
      result = CURLE_WRITE_ERROR;

      fprintf(global->errors, "(%d) Failed writing body\n", result);
    }
  }

  /* File time can only be set _after_ the file has been closed */
  if(!result && config->remote_time && outs->s_isreg && outs->filename) {
    /* Ask libcurl if we got a remote file time */
    curl_off_t filetime = -1;
    curl_easy_getinfo(curl, CURLINFO_FILETIME_T, &filetime);
    setfiletime(filetime, outs->filename, config->global->errors);
  }

  /* Close function-local opened file descriptors */
  if(per->heads.fopened && per->heads.stream)
    fclose(per->heads.stream);

  if(per->heads.alloc_filename)







|







>
|








|







622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
  if((global->progressmode == CURL_PROGRESS_BAR) &&
     per->progressbar.calls)
    /* if the custom progress bar has been displayed, we output a
       newline here */
    fputs("\n", per->progressbar.out);

  if(config->writeout)
    ourWriteOut(per->curl, per, config->writeout, result);

  /* Close the outs file */
  if(outs->fopened && outs->stream) {
    int rc = fclose(outs->stream);
    if(!result && rc) {
      /* something went wrong in the writing process */
      result = CURLE_WRITE_ERROR;
      if(global->showerror)
        fprintf(global->errors, "curl: (%d) Failed writing body\n", result);
    }
  }

  /* File time can only be set _after_ the file has been closed */
  if(!result && config->remote_time && outs->s_isreg && outs->filename) {
    /* Ask libcurl if we got a remote file time */
    curl_off_t filetime = -1;
    curl_easy_getinfo(curl, CURLINFO_FILETIME_T, &filetime);
    setfiletime(filetime, outs->filename, global);
  }

  /* Close function-local opened file descriptors */
  if(per->heads.fopened && per->heads.stream)
    fclose(per->heads.stream);

  if(per->heads.alloc_filename)
869
870
871
872
873
874
875

876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
            result = CURLE_OUT_OF_MEMORY;
            break;
          }
        }
        *added = TRUE;
        per->config = config;
        per->curl = curl;


        /* default headers output stream is stdout */
        heads = &per->heads;
        heads->stream = stdout;

        /* Single header file for all URLs */
        if(config->headerfile) {
          /* open file for output: */
          if(strcmp(config->headerfile, "-")) {
            FILE *newfile;
            newfile = fopen(config->headerfile, per->prev == NULL?"wb":"ab");
            if(!newfile) {
              warnf(config->global, "Failed to open %s\n", config->headerfile);
              result = CURLE_WRITE_ERROR;
              break;
            }
            else {
              heads->filename = config->headerfile;
              heads->s_isreg = TRUE;
              heads->fopened = TRUE;







>












|







868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
            result = CURLE_OUT_OF_MEMORY;
            break;
          }
        }
        *added = TRUE;
        per->config = config;
        per->curl = curl;
        per->urlnum = urlnode->num;

        /* default headers output stream is stdout */
        heads = &per->heads;
        heads->stream = stdout;

        /* Single header file for all URLs */
        if(config->headerfile) {
          /* open file for output: */
          if(strcmp(config->headerfile, "-")) {
            FILE *newfile;
            newfile = fopen(config->headerfile, per->prev == NULL?"wb":"ab");
            if(!newfile) {
              warnf(global, "Failed to open %s\n", config->headerfile);
              result = CURLE_WRITE_ERROR;
              break;
            }
            else {
              heads->filename = config->headerfile;
              heads->s_isreg = TRUE;
              heads->fopened = TRUE;
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
        if(config->etag_compare_file) {
          char *etag_from_file = NULL;
          char *header = NULL;

          /* open file for reading: */
          FILE *file = fopen(config->etag_compare_file, FOPEN_READTEXT);
          if(!file && !config->etag_save_file) {
            errorf(config->global,
                   "Failed to open %s\n", config->etag_compare_file);
            result = CURLE_READ_ERROR;
            break;
          }

          if((PARAM_OK == file2string(&etag_from_file, file)) &&
             etag_from_file) {
            header = aprintf("If-None-Match: %s", etag_from_file);
            Curl_safefree(etag_from_file);
          }
          else
            header = aprintf("If-None-Match: \"\"");

          if(!header) {
            if(file)
              fclose(file);
            errorf(config->global,
                   "Failed to allocate memory for custom etag header\n");
            result = CURLE_OUT_OF_MEMORY;
            break;
          }

          /* add Etag from file to list of custom headers */
          add2list(&config->headers, header);







|
















|







918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
        if(config->etag_compare_file) {
          char *etag_from_file = NULL;
          char *header = NULL;

          /* open file for reading: */
          FILE *file = fopen(config->etag_compare_file, FOPEN_READTEXT);
          if(!file && !config->etag_save_file) {
            errorf(global,
                   "Failed to open %s\n", config->etag_compare_file);
            result = CURLE_READ_ERROR;
            break;
          }

          if((PARAM_OK == file2string(&etag_from_file, file)) &&
             etag_from_file) {
            header = aprintf("If-None-Match: %s", etag_from_file);
            Curl_safefree(etag_from_file);
          }
          else
            header = aprintf("If-None-Match: \"\"");

          if(!header) {
            if(file)
              fclose(file);
            errorf(global,
                   "Failed to allocate memory for custom etag header\n");
            result = CURLE_OUT_OF_MEMORY;
            break;
          }

          /* add Etag from file to list of custom headers */
          add2list(&config->headers, header);
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975

        if(config->etag_save_file) {
          /* open file for output: */
          if(strcmp(config->etag_save_file, "-")) {
            FILE *newfile = fopen(config->etag_save_file, "wb");
            if(!newfile) {
              warnf(
                config->global,
                "Failed to open %s\n", config->etag_save_file);

              result = CURLE_WRITE_ERROR;
              break;
            }
            else {
              etag_save->filename = config->etag_save_file;







|







961
962
963
964
965
966
967
968
969
970
971
972
973
974
975

        if(config->etag_save_file) {
          /* open file for output: */
          if(strcmp(config->etag_save_file, "-")) {
            FILE *newfile = fopen(config->etag_save_file, "wb");
            if(!newfile) {
              warnf(
                global,
                "Failed to open %s\n", config->etag_save_file);

              result = CURLE_WRITE_ERROR;
              break;
            }
            else {
              etag_save->filename = config->etag_save_file;
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
          else if(state->urls) {
            /* fill '#1' ... '#9' terms from URL pattern */
            char *storefile = per->outfile;
            result = glob_match_url(&per->outfile, storefile, state->urls);
            Curl_safefree(storefile);
            if(result) {
              /* bad globbing */
              warnf(config->global, "bad output glob!\n");
              break;
            }
          }

          if(config->output_dir) {
            char *d = aprintf("%s/%s", config->output_dir, per->outfile);
            if(!d) {







|







1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
          else if(state->urls) {
            /* fill '#1' ... '#9' terms from URL pattern */
            char *storefile = per->outfile;
            result = glob_match_url(&per->outfile, storefile, state->urls);
            Curl_safefree(storefile);
            if(result) {
              /* bad globbing */
              warnf(global, "bad output glob!\n");
              break;
            }
          }

          if(config->output_dir) {
            char *d = aprintf("%s/%s", config->output_dir, per->outfile);
            if(!d) {
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
          }

          /*
           * If the user has also selected --anyauth or --proxy-anyauth
           * we should warn him/her.
           */
          if(config->proxyanyauth || (authbits>1)) {
            warnf(config->global,
                  "Using --anyauth or --proxy-anyauth with upload from stdin"
                  " involves a big risk of it not working. Use a temporary"
                  " file or a fixed auth type instead!\n");
          }

          DEBUGASSERT(per->infdopen == FALSE);
          DEBUGASSERT(per->infd == STDIN_FILENO);

          set_binmode(stdin);
          if(!strcmp(per->uploadfile, ".")) {
            if(curlx_nonblock((curl_socket_t)per->infd, TRUE) < 0)
              warnf(config->global,
                    "fcntl failed on fd=%d: %s\n", per->infd, strerror(errno));
          }
        }

        if(per->uploadfile && config->resume_from_current)
          config->resume_from = -1; /* -1 will then force get-it-yourself */








|











|







1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
          }

          /*
           * If the user has also selected --anyauth or --proxy-anyauth
           * we should warn him/her.
           */
          if(config->proxyanyauth || (authbits>1)) {
            warnf(global,
                  "Using --anyauth or --proxy-anyauth with upload from stdin"
                  " involves a big risk of it not working. Use a temporary"
                  " file or a fixed auth type instead!\n");
          }

          DEBUGASSERT(per->infdopen == FALSE);
          DEBUGASSERT(per->infd == STDIN_FILENO);

          set_binmode(stdin);
          if(!strcmp(per->uploadfile, ".")) {
            if(curlx_nonblock((curl_socket_t)per->infd, TRUE) < 0)
              warnf(global,
                    "fcntl failed on fd=%d: %s\n", per->infd, strerror(errno));
          }
        }

        if(per->uploadfile && config->resume_from_current)
          config->resume_from = -1; /* -1 will then force get-it-yourself */

1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288

        /* for uploads */
        input->config = config;
        /* Note that if CURLOPT_READFUNCTION is fread (the default), then
         * lib/telnet.c will Curl_poll() on the input file descriptor
         * rather then calling the READFUNCTION at regular intervals.
         * The circumstances in which it is preferable to enable this
         * behaviour, by omitting to set the READFUNCTION & READDATA options,
         * have not been determined.
         */
        my_setopt(curl, CURLOPT_READDATA, input);
        /* what call to read */
        my_setopt(curl, CURLOPT_READFUNCTION, tool_read_cb);

        /* in 7.18.0, the CURLOPT_SEEKFUNCTION/DATA pair is taking over what







|







1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288

        /* for uploads */
        input->config = config;
        /* Note that if CURLOPT_READFUNCTION is fread (the default), then
         * lib/telnet.c will Curl_poll() on the input file descriptor
         * rather then calling the READFUNCTION at regular intervals.
         * The circumstances in which it is preferable to enable this
         * behavior, by omitting to set the READFUNCTION & READDATA options,
         * have not been determined.
         */
        my_setopt(curl, CURLOPT_READDATA, input);
        /* what call to read */
        my_setopt(curl, CURLOPT_READFUNCTION, tool_read_cb);

        /* in 7.18.0, the CURLOPT_SEEKFUNCTION/DATA pair is taking over what
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
          my_setopt_str(curl, CURLOPT_CAINFO, config->cacert);
        if(config->proxy_cacert)
          my_setopt_str(curl, CURLOPT_PROXY_CAINFO, config->proxy_cacert);

        if(config->capath) {
          result = res_setopt_str(curl, CURLOPT_CAPATH, config->capath);
          if(result == CURLE_NOT_BUILT_IN) {
            warnf(config->global, "ignoring %s, not supported by libcurl\n",
                  capath_from_env?
                  "SSL_CERT_DIR environment variable":"--capath");
          }
          else if(result)
            break;
        }
        /* For the time being if --proxy-capath is not set then we use the
           --capath value for it, if any. See #1257 */
        if((config->proxy_capath || config->capath) &&
           !tool_setopt_skip(CURLOPT_PROXY_CAPATH)) {
          result = res_setopt_str(curl, CURLOPT_PROXY_CAPATH,
                                  (config->proxy_capath ?
                                   config->proxy_capath :
                                   config->capath));
          if(result == CURLE_NOT_BUILT_IN) {
            if(config->proxy_capath) {
              warnf(config->global,
                    "ignoring --proxy-capath, not supported by libcurl\n");
            }
          }
          else if(result)
            break;
        }








|
















|







1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
          my_setopt_str(curl, CURLOPT_CAINFO, config->cacert);
        if(config->proxy_cacert)
          my_setopt_str(curl, CURLOPT_PROXY_CAINFO, config->proxy_cacert);

        if(config->capath) {
          result = res_setopt_str(curl, CURLOPT_CAPATH, config->capath);
          if(result == CURLE_NOT_BUILT_IN) {
            warnf(global, "ignoring %s, not supported by libcurl\n",
                  capath_from_env?
                  "SSL_CERT_DIR environment variable":"--capath");
          }
          else if(result)
            break;
        }
        /* For the time being if --proxy-capath is not set then we use the
           --capath value for it, if any. See #1257 */
        if((config->proxy_capath || config->capath) &&
           !tool_setopt_skip(CURLOPT_PROXY_CAPATH)) {
          result = res_setopt_str(curl, CURLOPT_PROXY_CAPATH,
                                  (config->proxy_capath ?
                                   config->proxy_capath :
                                   config->capath));
          if(result == CURLE_NOT_BUILT_IN) {
            if(config->proxy_capath) {
              warnf(global,
                    "ignoring --proxy-capath, not supported by libcurl\n");
            }
          }
          else if(result)
            break;
        }

1657
1658
1659
1660
1661
1662
1663


1664
1665
1666
1667
1668
1669
1670
          else
#endif
          my_setopt_str(curl, CURLOPT_SSLKEY, config->key);
          my_setopt_str(curl, CURLOPT_PROXY_SSLKEY, config->proxy_key);
          my_setopt_str(curl, CURLOPT_SSLKEYTYPE, config->key_type);
          my_setopt_str(curl, CURLOPT_PROXY_SSLKEYTYPE,
                        config->proxy_key_type);



          if(config->insecure_ok) {
            my_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
            my_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L);
          }
          else {
            my_setopt(curl, CURLOPT_SSL_VERIFYPEER, 1L);







>
>







1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
          else
#endif
          my_setopt_str(curl, CURLOPT_SSLKEY, config->key);
          my_setopt_str(curl, CURLOPT_PROXY_SSLKEY, config->proxy_key);
          my_setopt_str(curl, CURLOPT_SSLKEYTYPE, config->key_type);
          my_setopt_str(curl, CURLOPT_PROXY_SSLKEYTYPE,
                        config->proxy_key_type);
          my_setopt_str(curl, CURLOPT_AWS_SIGV4,
                        config->aws_sigv4);

          if(config->insecure_ok) {
            my_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
            my_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L);
          }
          else {
            my_setopt(curl, CURLOPT_SSL_VERIFYPEER, 1L);
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
#ifdef USE_METALINK
        if(!metalink && config->use_metalink) {
          outs->metalink_parser = metalink_parser_context_new();
          if(outs->metalink_parser == NULL) {
            result = CURLE_OUT_OF_MEMORY;
            break;
          }
          fprintf(config->global->errors,
                  "Metalink: parsing (%s) metalink/XML...\n", per->this_url);
        }
        else if(metalink)
          fprintf(config->global->errors,
                  "Metalink: fetching (%s) from (%s)...\n",
                  mlfile->filename, per->this_url);
#endif /* USE_METALINK */

        per->metalink = metalink;
        /* initialize retry vars for loop below */
        per->retry_sleep_default = (config->retry_delay) ?







|



|







2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
#ifdef USE_METALINK
        if(!metalink && config->use_metalink) {
          outs->metalink_parser = metalink_parser_context_new();
          if(outs->metalink_parser == NULL) {
            result = CURLE_OUT_OF_MEMORY;
            break;
          }
          fprintf(global->errors,
                  "Metalink: parsing (%s) metalink/XML...\n", per->this_url);
        }
        else if(metalink)
          fprintf(global->errors,
                  "Metalink: fetching (%s) from (%s)...\n",
                  mlfile->filename, per->this_url);
#endif /* USE_METALINK */

        per->metalink = metalink;
        /* initialize retry vars for loop below */
        per->retry_sleep_default = (config->retry_delay) ?
2535
2536
2537
2538
2539
2540
2541
2542
2543
2544
2545
2546
2547
2548
2549
  /* Setup proper locale from environment */
#ifdef HAVE_SETLOCALE
  setlocale(LC_ALL, "");
#endif

  /* Parse .curlrc if necessary */
  if((argc == 1) ||
     (!curl_strequal(first_arg, "-q") &&
      !curl_strequal(first_arg, "--disable"))) {
    parseconfig(NULL, global); /* ignore possible failure */

    /* If we had no arguments then make sure a url was specified in .curlrc */
    if((argc < 2) && (!global->first->url_list)) {
      helpf(global->errors, NULL);
      result = CURLE_FAILED_INIT;







|







2537
2538
2539
2540
2541
2542
2543
2544
2545
2546
2547
2548
2549
2550
2551
  /* Setup proper locale from environment */
#ifdef HAVE_SETLOCALE
  setlocale(LC_ALL, "");
#endif

  /* Parse .curlrc if necessary */
  if((argc == 1) ||
     (first_arg && strncmp(first_arg, "-q", 2) &&
      !curl_strequal(first_arg, "--disable"))) {
    parseconfig(NULL, global); /* ignore possible failure */

    /* If we had no arguments then make sure a url was specified in .curlrc */
    if((argc < 2) && (!global->first->url_list)) {
      helpf(global->errors, NULL);
      result = CURLE_FAILED_INIT;
Changes to jni/curl/src/tool_operate.h.
37
38
39
40
41
42
43

44
45
46
47
48
49
50
  long retry_sleep;
  struct timeval retrystart;
  bool metalink; /* nonzero for metalink download. */
  bool metalink_next_res;
  struct metalinkfile *mlfile;
  struct metalink_resource *mlres;
  char *this_url;

  char *outfile;
  bool infdopen; /* TRUE if infd needs closing */
  int infd;
  bool noprogress;
  struct ProgressData progressbar;
  struct OutStruct outs;
  struct OutStruct heads;







>







37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
  long retry_sleep;
  struct timeval retrystart;
  bool metalink; /* nonzero for metalink download. */
  bool metalink_next_res;
  struct metalinkfile *mlfile;
  struct metalink_resource *mlres;
  char *this_url;
  unsigned int urlnum; /* the index of the given URL */
  char *outfile;
  bool infdopen; /* TRUE if infd needs closing */
  int infd;
  bool noprogress;
  struct ProgressData progressbar;
  struct OutStruct outs;
  struct OutStruct heads;
Changes to jni/curl/src/tool_paramhlp.c.
36
37
38
39
40
41
42

43
44
45
46
47
48
49
50
51
52
53
54
55

56
57
58
59
60
61
62
#include "tool_version.h"
#include "dynbuf.h"

#include "memdebug.h" /* keep this as LAST include */

struct getout *new_getout(struct OperationConfig *config)
{

  struct getout *node = calloc(1, sizeof(struct getout));
  struct getout *last = config->url_last;
  if(node) {
    /* append this new node last in the list */
    if(last)
      last->next = node;
    else
      config->url_list = node; /* first node */

    /* move the last pointer */
    config->url_last = node;

    node->flags = config->default_node_flags;

  }
  return node;
}

#define MAX_FILE2STRING (256*1024*1024) /* big enough ? */

ParameterError file2string(char **bufp, FILE *file)







>













>







36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
#include "tool_version.h"
#include "dynbuf.h"

#include "memdebug.h" /* keep this as LAST include */

struct getout *new_getout(struct OperationConfig *config)
{
  static int outnum = 0;
  struct getout *node = calloc(1, sizeof(struct getout));
  struct getout *last = config->url_last;
  if(node) {
    /* append this new node last in the list */
    if(last)
      last->next = node;
    else
      config->url_list = node; /* first node */

    /* move the last pointer */
    config->url_last = node;

    node->flags = config->default_node_flags;
    node->num = outnum++;
  }
  return node;
}

#define MAX_FILE2STRING (256*1024*1024) /* big enough ? */

ParameterError file2string(char **bufp, FILE *file)
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148


















149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
 * Parse the string and write the long in the given address. Return PARAM_OK
 * on success, otherwise a parameter specific error enum.
 *
 * Since this function gets called with the 'nextarg' pointer from within the
 * getparameter a lot, we must check it for NULL before accessing the str
 * data.
 */

ParameterError str2num(long *val, const char *str)
{
  if(str) {
    char *endptr = NULL;
    long num;
    errno = 0;
    num = strtol(str, &endptr, 10);
    if(errno == ERANGE)
      return PARAM_NUMBER_TOO_LARGE;
    if((endptr != str) && (endptr == str + strlen(str))) {
      *val = num;
      return PARAM_OK;  /* Ok */
    }
  }
  return PARAM_BAD_NUMERIC; /* badness */
}



















/*
 * Parse the string and write the long in the given address. Return PARAM_OK
 * on success, otherwise a parameter error enum. ONLY ACCEPTS POSITIVE NUMBERS!
 *
 * Since this function gets called with the 'nextarg' pointer from within the
 * getparameter a lot, we must check it for NULL before accessing the str
 * data.
 */

ParameterError str2unum(long *val, const char *str)
{
  ParameterError result = str2num(val, str);
  if(result != PARAM_OK)
    return result;
  if(*val < 0)
    return PARAM_NEGATIVE_NUMERIC;

  return PARAM_OK;
}







<
|





|









>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>












|







127
128
129
130
131
132
133

134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
 * Parse the string and write the long in the given address. Return PARAM_OK
 * on success, otherwise a parameter specific error enum.
 *
 * Since this function gets called with the 'nextarg' pointer from within the
 * getparameter a lot, we must check it for NULL before accessing the str
 * data.
 */

static ParameterError getnum(long *val, const char *str, int base)
{
  if(str) {
    char *endptr = NULL;
    long num;
    errno = 0;
    num = strtol(str, &endptr, base);
    if(errno == ERANGE)
      return PARAM_NUMBER_TOO_LARGE;
    if((endptr != str) && (endptr == str + strlen(str))) {
      *val = num;
      return PARAM_OK;  /* Ok */
    }
  }
  return PARAM_BAD_NUMERIC; /* badness */
}

ParameterError str2num(long *val, const char *str)
{
  return getnum(val, str, 10);
}

ParameterError oct2nummax(long *val, const char *str, long max)
{
  ParameterError result = getnum(val, str, 8);
  if(result != PARAM_OK)
    return result;
  else if(*val > max)
    return PARAM_NUMBER_TOO_LARGE;
  else if(*val < 0)
    return PARAM_NEGATIVE_NUMERIC;

  return PARAM_OK;
}

/*
 * Parse the string and write the long in the given address. Return PARAM_OK
 * on success, otherwise a parameter error enum. ONLY ACCEPTS POSITIVE NUMBERS!
 *
 * Since this function gets called with the 'nextarg' pointer from within the
 * getparameter a lot, we must check it for NULL before accessing the str
 * data.
 */

ParameterError str2unum(long *val, const char *str)
{
  ParameterError result = getnum(val, str, 10);
  if(result != PARAM_OK)
    return result;
  if(*val < 0)
    return PARAM_NEGATIVE_NUMERIC;

  return PARAM_OK;
}
Changes to jni/curl/src/tool_paramhlp.h.
29
30
31
32
33
34
35

36
37
38
39
40
41
42

ParameterError file2memory(char **bufp, size_t *size, FILE *file);

void cleanarg(char *str);

ParameterError str2num(long *val, const char *str);
ParameterError str2unum(long *val, const char *str);

ParameterError str2unummax(long *val, const char *str, long max);
ParameterError str2udouble(double *val, const char *str, long max);

long proto2num(struct OperationConfig *config, long *val, const char *str);

int check_protocol(const char *str);








>







29
30
31
32
33
34
35
36
37
38
39
40
41
42
43

ParameterError file2memory(char **bufp, size_t *size, FILE *file);

void cleanarg(char *str);

ParameterError str2num(long *val, const char *str);
ParameterError str2unum(long *val, const char *str);
ParameterError oct2nummax(long *val, const char *str, long max);
ParameterError str2unummax(long *val, const char *str, long max);
ParameterError str2udouble(double *val, const char *str, long max);

long proto2num(struct OperationConfig *config, long *val, const char *str);

int check_protocol(const char *str);

Changes to jni/curl/src/tool_sdecls.h.
101
102
103
104
105
106
107

108
109
110
111
112
113
114

struct getout {
  struct getout *next;      /* next one */
  char          *url;       /* the URL we deal with */
  char          *outfile;   /* where to store the output */
  char          *infile;    /* file to upload, if GETOUT_UPLOAD is set */
  int            flags;     /* options - composed of GETOUT_* bits */

};

#define GETOUT_OUTFILE    (1<<0)  /* set when outfile is deemed done */
#define GETOUT_URL        (1<<1)  /* set when URL is deemed done */
#define GETOUT_USEREMOTE  (1<<2)  /* use remote file name locally */
#define GETOUT_UPLOAD     (1<<3)  /* if set, -T has been used */
#define GETOUT_NOUPLOAD   (1<<4)  /* if set, -T "" has been used */







>







101
102
103
104
105
106
107
108
109
110
111
112
113
114
115

struct getout {
  struct getout *next;      /* next one */
  char          *url;       /* the URL we deal with */
  char          *outfile;   /* where to store the output */
  char          *infile;    /* file to upload, if GETOUT_UPLOAD is set */
  int            flags;     /* options - composed of GETOUT_* bits */
  int            num;       /* which URL number in an invocation */
};

#define GETOUT_OUTFILE    (1<<0)  /* set when outfile is deemed done */
#define GETOUT_URL        (1<<1)  /* set when URL is deemed done */
#define GETOUT_USEREMOTE  (1<<2)  /* use remote file name locally */
#define GETOUT_UPLOAD     (1<<3)  /* if set, -T has been used */
#define GETOUT_NOUPLOAD   (1<<4)  /* if set, -T "" has been used */
Changes to jni/curl/src/tool_setopt.c.
27
28
29
30
31
32
33

34
35
36
37
38
39
40
/* use our own printf() functions */
#include "curlx.h"

#include "tool_cfgable.h"
#include "tool_easysrc.h"
#include "tool_setopt.h"
#include "tool_convert.h"


#include "memdebug.h" /* keep this as LAST include */

/* Lookup tables for converting setopt values back to symbols */
/* For enums, values may be in any order. */
/* For bit masks, put combinations first, then single bits, */
/* and finally any "NONE" value. */







>







27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
/* use our own printf() functions */
#include "curlx.h"

#include "tool_cfgable.h"
#include "tool_easysrc.h"
#include "tool_setopt.h"
#include "tool_convert.h"
#include "tool_msgs.h"

#include "memdebug.h" /* keep this as LAST include */

/* Lookup tables for converting setopt values back to symbols */
/* For enums, values may be in any order. */
/* For bit masks, put combinations first, then single bits, */
/* and finally any "NONE" value. */
311
312
313
314
315
316
317




318
319
320
321
322
323
324
325
      CODE2("curl_easy_setopt(hnd, %s, %ldL);", name, lval);
    }
    else {
      CODE2("curl_easy_setopt(hnd, %s, (long)%s);", name, nv->name);
    }
  }





 nomem:
  return ret;
}

/* setopt wrapper for flags */
CURLcode tool_setopt_flags(CURL *curl, struct GlobalConfig *config,
                           const char *name, CURLoption tag,
                           const struct NameValue *nvlist, long lval)







>
>
>
>
|







312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
      CODE2("curl_easy_setopt(hnd, %s, %ldL);", name, lval);
    }
    else {
      CODE2("curl_easy_setopt(hnd, %s, (long)%s);", name, nv->name);
    }
  }

#ifdef DEBUGBUILD
  if(ret)
    warnf(config, "option %s returned error (%d)\n", name, (int)ret);
#endif
  nomem:
  return ret;
}

/* setopt wrapper for flags */
CURLcode tool_setopt_flags(CURL *curl, struct GlobalConfig *config,
                           const char *name, CURLoption tag,
                           const struct NameValue *nvlist, long lval)
Changes to jni/curl/src/tool_version.h.
21
22
23
24
25
26
27
28
29
30
31
32
33
34
 * KIND, either express or implied.
 *
 ***************************************************************************/
#include <curl/curlver.h>

#define CURL_NAME "curl"
#define CURL_COPYRIGHT LIBCURL_COPYRIGHT
#define CURL_VERSION "7.74.0"
#define CURL_VERSION_MAJOR LIBCURL_VERSION_MAJOR
#define CURL_VERSION_MINOR LIBCURL_VERSION_MINOR
#define CURL_VERSION_PATCH LIBCURL_VERSION_PATCH
#define CURL_ID CURL_NAME " " CURL_VERSION " (" OS ") "

#endif /* HEADER_CURL_TOOL_VERSION_H */







|






21
22
23
24
25
26
27
28
29
30
31
32
33
34
 * KIND, either express or implied.
 *
 ***************************************************************************/
#include <curl/curlver.h>

#define CURL_NAME "curl"
#define CURL_COPYRIGHT LIBCURL_COPYRIGHT
#define CURL_VERSION "7.75.0"
#define CURL_VERSION_MAJOR LIBCURL_VERSION_MAJOR
#define CURL_VERSION_MINOR LIBCURL_VERSION_MINOR
#define CURL_VERSION_PATCH LIBCURL_VERSION_PATCH
#define CURL_ID CURL_NAME " " CURL_VERSION " (" OS ") "

#endif /* HEADER_CURL_TOOL_VERSION_H */
Changes to jni/curl/src/tool_writeout.c.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2020, 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 https://curl.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







|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2021, 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 https://curl.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
26
27
28
29
30
31
32

33

34
35
36
37

38
39


40


41



42



43










44
45
46
47
48
49
50
51
52
53
54

55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108








109

110
111
112
113
114
115

116
117
118
119
120
121
122
123
124
#include "tool_cfgable.h"
#include "tool_writeout.h"
#include "tool_writeout_json.h"

#include "memdebug.h" /* keep this as LAST include */

static const struct writeoutvar variables[] = {

  {"url_effective", VAR_EFFECTIVE_URL, 0,

   CURLINFO_EFFECTIVE_URL, JSON_STRING},
  {"method", VAR_EFFECTIVE_METHOD, 0,
   CURLINFO_EFFECTIVE_METHOD, JSON_STRING},
  {"http_code", VAR_HTTP_CODE, 0,

   CURLINFO_RESPONSE_CODE, JSON_LONG},
  {"response_code", VAR_HTTP_CODE, 0,


   CURLINFO_RESPONSE_CODE, JSON_LONG},


  {"num_headers", VAR_NUM_HEADERS, 0,



   0, JSON_LONG},



  {"http_connect", VAR_HTTP_CODE_PROXY, 0,










   CURLINFO_HTTP_CONNECTCODE, JSON_LONG},
  {"time_total", VAR_TOTAL_TIME, 0,
   CURLINFO_TOTAL_TIME_T, JSON_TIME},
  {"time_namelookup", VAR_NAMELOOKUP_TIME, 0,
   CURLINFO_NAMELOOKUP_TIME_T, JSON_TIME},
  {"time_connect", VAR_CONNECT_TIME, 0,
   CURLINFO_CONNECT_TIME_T, JSON_TIME},
  {"time_appconnect", VAR_APPCONNECT_TIME, 0,
   CURLINFO_APPCONNECT_TIME_T, JSON_TIME},
  {"time_pretransfer", VAR_PRETRANSFER_TIME, 0,
   CURLINFO_PRETRANSFER_TIME_T, JSON_TIME},

  {"time_starttransfer", VAR_STARTTRANSFER_TIME, 0,
   CURLINFO_STARTTRANSFER_TIME_T, JSON_TIME},
  {"size_header", VAR_HEADER_SIZE, 0,
   CURLINFO_HEADER_SIZE, JSON_LONG},
  {"size_request", VAR_REQUEST_SIZE, 0,
   CURLINFO_REQUEST_SIZE, JSON_LONG},
  {"size_download", VAR_SIZE_DOWNLOAD, 0,
   CURLINFO_SIZE_DOWNLOAD_T, JSON_OFFSET},
  {"size_upload", VAR_SIZE_UPLOAD, 0,
   CURLINFO_SIZE_UPLOAD_T, JSON_OFFSET},
  {"speed_download", VAR_SPEED_DOWNLOAD, 0,
   CURLINFO_SPEED_DOWNLOAD_T, JSON_OFFSET},
  {"speed_upload", VAR_SPEED_UPLOAD, 0,
   CURLINFO_SPEED_UPLOAD_T, JSON_OFFSET},
  {"content_type", VAR_CONTENT_TYPE, 0,
   CURLINFO_CONTENT_TYPE, JSON_STRING},
  {"num_connects", VAR_NUM_CONNECTS, 0,
   CURLINFO_NUM_CONNECTS, JSON_LONG},
  {"time_redirect", VAR_REDIRECT_TIME, 0,
   CURLINFO_REDIRECT_TIME_T, JSON_TIME},
  {"num_redirects", VAR_REDIRECT_COUNT, 0,
   CURLINFO_REDIRECT_COUNT, JSON_LONG},
  {"ftp_entry_path", VAR_FTP_ENTRY_PATH, 0,
   CURLINFO_FTP_ENTRY_PATH, JSON_STRING},
  {"redirect_url", VAR_REDIRECT_URL, 0,
   CURLINFO_REDIRECT_URL, JSON_STRING},
  {"ssl_verify_result", VAR_SSL_VERIFY_RESULT, 0,
   CURLINFO_SSL_VERIFYRESULT, JSON_LONG},
  {"proxy_ssl_verify_result", VAR_PROXY_SSL_VERIFY_RESULT, 0,
   CURLINFO_PROXY_SSL_VERIFYRESULT, JSON_LONG},
  {"filename_effective", VAR_EFFECTIVE_FILENAME, 0,
   0, JSON_FILENAME},
  {"remote_ip", VAR_PRIMARY_IP, 0,
   CURLINFO_PRIMARY_IP, JSON_STRING},
  {"remote_port", VAR_PRIMARY_PORT, 0,
   CURLINFO_PRIMARY_PORT, JSON_LONG},
  {"local_ip", VAR_LOCAL_IP, 0,
   CURLINFO_LOCAL_IP, JSON_STRING},
  {"local_port", VAR_LOCAL_PORT, 0,
   CURLINFO_LOCAL_PORT, JSON_LONG},
  {"http_version", VAR_HTTP_VERSION, 0,
   CURLINFO_HTTP_VERSION, JSON_VERSION},
  {"scheme", VAR_SCHEME, 0,
   CURLINFO_SCHEME, JSON_STRING},
  {"stdout", VAR_STDOUT, 1,
   0, JSON_NONE},
  {"stderr", VAR_STDERR, 1,
   0, JSON_NONE},
  {"json", VAR_JSON, 1,
   0, JSON_NONE},
  {NULL, VAR_NONE, 1,
   0, JSON_NONE}
};









void ourWriteOut(CURL *curl, struct per_transfer *per, const char *writeinfo)

{
  FILE *stream = stdout;
  const char *ptr = writeinfo;
  char *stringp = NULL;
  long longinfo;
  curl_off_t offinfo;


  while(ptr && *ptr) {
    if('%' == *ptr && ptr[1]) {
      if('%' == ptr[1]) {
        /* an escaped %-letter */
        fputc('%', stream);
        ptr += 2;
      }
      else {







>
|
>
|
|
|
|
>
|
|
>
>
|
>
>
|
>
>
>
|
>
>
>
|
>
>
>
>
>
>
>
>
>
>
|
|
|
|
|
|
|
<
|
|
|
>


<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
<
<
<
<
<
|
<
<
<
<
|
<
<
<
<
<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
|
<


>
>
>
>
>
>
>
>
|
>






>

|







26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73

74
75
76
77
78
79

















80





81




82








83










84

85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
#include "tool_cfgable.h"
#include "tool_writeout.h"
#include "tool_writeout_json.h"

#include "memdebug.h" /* keep this as LAST include */

static const struct writeoutvar variables[] = {
  {"content_type", VAR_CONTENT_TYPE, 0, CURLINFO_CONTENT_TYPE, JSON_STRING},
  {"filename_effective", VAR_EFFECTIVE_FILENAME, 0, 0, JSON_FILENAME},
  {"exitcode", VAR_EXITCODE, 0, 0, JSON_LONG},
  {"errormsg", VAR_ERRORMSG, 0, 0, JSON_STRING},
  {"ftp_entry_path", VAR_FTP_ENTRY_PATH, 0, CURLINFO_FTP_ENTRY_PATH,
   JSON_STRING},
  {"http_code", VAR_HTTP_CODE, 0, CURLINFO_RESPONSE_CODE, JSON_LONG},
  {"http_connect", VAR_HTTP_CODE_PROXY, 0, CURLINFO_HTTP_CONNECTCODE,
   JSON_LONG},
  {"http_version", VAR_HTTP_VERSION, 0, CURLINFO_HTTP_VERSION, JSON_VERSION},
  {"json", VAR_JSON, 1, 0, JSON_NONE},
  {"local_ip", VAR_LOCAL_IP, 0, CURLINFO_LOCAL_IP, JSON_STRING},
  {"local_port", VAR_LOCAL_PORT, 0, CURLINFO_LOCAL_PORT, JSON_LONG},
  {"method", VAR_EFFECTIVE_METHOD, 0, CURLINFO_EFFECTIVE_METHOD, JSON_STRING},
  {"num_connects", VAR_NUM_CONNECTS, 0, CURLINFO_NUM_CONNECTS, JSON_LONG},
  {"num_headers", VAR_NUM_HEADERS, 0, 0, JSON_LONG},
  {"num_redirects", VAR_REDIRECT_COUNT, 0, CURLINFO_REDIRECT_COUNT, JSON_LONG},
  {"onerror", VAR_ONERROR, 1, 0, JSON_NONE},
  {"proxy_ssl_verify_result", VAR_PROXY_SSL_VERIFY_RESULT, 0,
   CURLINFO_PROXY_SSL_VERIFYRESULT, JSON_LONG},
  {"redirect_url", VAR_REDIRECT_URL, 0, CURLINFO_REDIRECT_URL, JSON_STRING},
  {"remote_ip", VAR_PRIMARY_IP, 0, CURLINFO_PRIMARY_IP, JSON_STRING},
  {"remote_port", VAR_PRIMARY_PORT, 0, CURLINFO_PRIMARY_PORT, JSON_LONG},
  {"response_code", VAR_HTTP_CODE, 0, CURLINFO_RESPONSE_CODE, JSON_LONG},
  {"scheme", VAR_SCHEME, 0, CURLINFO_SCHEME, JSON_STRING},
  {"size_download", VAR_SIZE_DOWNLOAD, 0, CURLINFO_SIZE_DOWNLOAD_T,
   JSON_OFFSET},
  {"size_header", VAR_HEADER_SIZE, 0, CURLINFO_HEADER_SIZE, JSON_LONG},
  {"size_request", VAR_REQUEST_SIZE, 0, CURLINFO_REQUEST_SIZE, JSON_LONG},
  {"size_upload", VAR_SIZE_UPLOAD, 0, CURLINFO_SIZE_UPLOAD_T, JSON_OFFSET},
  {"speed_download", VAR_SPEED_DOWNLOAD, 0, CURLINFO_SPEED_DOWNLOAD_T,
   JSON_OFFSET},
  {"speed_upload", VAR_SPEED_UPLOAD, 0, CURLINFO_SPEED_UPLOAD_T, JSON_OFFSET},
  {"ssl_verify_result", VAR_SSL_VERIFY_RESULT, 0, CURLINFO_SSL_VERIFYRESULT,
   JSON_LONG},
  {"stderr", VAR_STDERR, 1, 0, JSON_NONE},
  {"stdout", VAR_STDOUT, 1, 0, JSON_NONE},
  {"time_appconnect", VAR_APPCONNECT_TIME, 0, CURLINFO_APPCONNECT_TIME_T,
   JSON_TIME},
  {"time_connect", VAR_CONNECT_TIME, 0, CURLINFO_CONNECT_TIME_T, JSON_TIME},
  {"time_namelookup", VAR_NAMELOOKUP_TIME, 0, CURLINFO_NAMELOOKUP_TIME_T,

   JSON_TIME},
  {"time_pretransfer", VAR_PRETRANSFER_TIME, 0, CURLINFO_PRETRANSFER_TIME_T,
   JSON_TIME},
  {"time_redirect", VAR_REDIRECT_TIME, 0, CURLINFO_REDIRECT_TIME_T, JSON_TIME},
  {"time_starttransfer", VAR_STARTTRANSFER_TIME, 0,
   CURLINFO_STARTTRANSFER_TIME_T, JSON_TIME},

















  {"time_total", VAR_TOTAL_TIME, 0, CURLINFO_TOTAL_TIME_T, JSON_TIME},





  {"url", VAR_INPUT_URL, 0, 0, JSON_STRING},




  {"url_effective", VAR_EFFECTIVE_URL, 0, CURLINFO_EFFECTIVE_URL, JSON_STRING},








  {"urlnum", VAR_URLNUM, 0, 0, JSON_LONG},










  {NULL, VAR_NONE, 1, 0, JSON_NONE}

};

static void us2sec(FILE *stream, curl_off_t us)
{
  curl_off_t secs = us / 1000000;
  us %= 1000000;
  fprintf(stream, "%" CURL_FORMAT_CURL_OFF_TU ".%06" CURL_FORMAT_CURL_OFF_TU,
          secs, us);
}

void ourWriteOut(CURL *curl, struct per_transfer *per, const char *writeinfo,
                 CURLcode result)
{
  FILE *stream = stdout;
  const char *ptr = writeinfo;
  char *stringp = NULL;
  long longinfo;
  curl_off_t offinfo;
  bool done = FALSE;

  while(ptr && *ptr && !done) {
    if('%' == *ptr && ptr[1]) {
      if('%' == ptr[1]) {
        /* an escaped %-letter */
        fputc('%', stream);
        ptr += 2;
      }
      else {
136
137
138
139
140
141
142




















143
144
145
146
147
148
149
          }
          keepit = *end;
          *end = 0; /* null-terminate */
          for(i = 0; variables[i].name; i++) {
            if(curl_strequal(ptr, variables[i].name)) {
              match = TRUE;
              switch(variables[i].id) {




















              case VAR_EFFECTIVE_URL:
                if((CURLE_OK ==
                    curl_easy_getinfo(curl, CURLINFO_EFFECTIVE_URL, &stringp))
                   && stringp)
                  fputs(stringp, stream);
                break;
              case VAR_EFFECTIVE_METHOD:







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
          }
          keepit = *end;
          *end = 0; /* null-terminate */
          for(i = 0; variables[i].name; i++) {
            if(curl_strequal(ptr, variables[i].name)) {
              match = TRUE;
              switch(variables[i].id) {
              case VAR_ONERROR:
                if(result == CURLE_OK)
                  /* this isn't error so skip the rest */
                  done = TRUE;
                break;
              case VAR_EXITCODE:
                fprintf(stream, "%d", (int)result);
                break;
              case VAR_ERRORMSG:
                if(result)
                  fputs(per->errorbuffer[0] ? per->errorbuffer :
                        curl_easy_strerror(result), stream);
                break;
              case VAR_INPUT_URL:
                if(per->this_url)
                  fputs(per->this_url, stream);
                break;
              case VAR_URLNUM:
                fprintf(stream, "%u", per->urlnum);
                break;
              case VAR_EFFECTIVE_URL:
                if((CURLE_OK ==
                    curl_easy_getinfo(curl, CURLINFO_EFFECTIVE_URL, &stringp))
                   && stringp)
                  fputs(stringp, stream);
                break;
              case VAR_EFFECTIVE_METHOD:
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
                if(CURLE_OK ==
                   curl_easy_getinfo(curl, CURLINFO_REDIRECT_COUNT, &longinfo))
                  fprintf(stream, "%ld", longinfo);
                break;
              case VAR_REDIRECT_TIME:
                if(CURLE_OK ==
                   curl_easy_getinfo(curl, CURLINFO_REDIRECT_TIME_T, &offinfo))
                  fprintf(stream, "%" CURL_FORMAT_CURL_OFF_TU, offinfo);
                break;
              case VAR_TOTAL_TIME:
                if(CURLE_OK ==
                   curl_easy_getinfo(curl, CURLINFO_TOTAL_TIME_T, &offinfo))
                  fprintf(stream, "%" CURL_FORMAT_CURL_OFF_TU, offinfo);
                break;
              case VAR_NAMELOOKUP_TIME:
                if(CURLE_OK ==
                   curl_easy_getinfo(curl, CURLINFO_NAMELOOKUP_TIME_T,
                                     &offinfo))
                  fprintf(stream, "%" CURL_FORMAT_CURL_OFF_TU, offinfo);
                break;
              case VAR_CONNECT_TIME:
                if(CURLE_OK ==
                   curl_easy_getinfo(curl, CURLINFO_CONNECT_TIME_T, &offinfo))
                  fprintf(stream, "%" CURL_FORMAT_CURL_OFF_TU, offinfo);
                break;
              case VAR_APPCONNECT_TIME:
                if(CURLE_OK ==
                   curl_easy_getinfo(curl, CURLINFO_APPCONNECT_TIME_T,
                                     &offinfo))
                  fprintf(stream, "%" CURL_FORMAT_CURL_OFF_TU, offinfo);
                break;
              case VAR_PRETRANSFER_TIME:
                if(CURLE_OK ==
                   curl_easy_getinfo(curl, CURLINFO_PRETRANSFER_TIME_T,
                                     &offinfo))
                  fprintf(stream, "%" CURL_FORMAT_CURL_OFF_TU, offinfo);
                break;
              case VAR_STARTTRANSFER_TIME:
                if(CURLE_OK ==
                   curl_easy_getinfo(curl, CURLINFO_STARTTRANSFER_TIME_T,
                                     &offinfo))
                  fprintf(stream, "%" CURL_FORMAT_CURL_OFF_TU, offinfo);
                break;
              case VAR_SIZE_UPLOAD:
                if(CURLE_OK ==
                   curl_easy_getinfo(curl, CURLINFO_SIZE_UPLOAD_T, &offinfo))
                  fprintf(stream, "%" CURL_FORMAT_CURL_OFF_TU, offinfo);
                break;
              case VAR_SIZE_DOWNLOAD:







|




|





|




|





|





|





|







194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
                if(CURLE_OK ==
                   curl_easy_getinfo(curl, CURLINFO_REDIRECT_COUNT, &longinfo))
                  fprintf(stream, "%ld", longinfo);
                break;
              case VAR_REDIRECT_TIME:
                if(CURLE_OK ==
                   curl_easy_getinfo(curl, CURLINFO_REDIRECT_TIME_T, &offinfo))
                  us2sec(stream, offinfo);
                break;
              case VAR_TOTAL_TIME:
                if(CURLE_OK ==
                   curl_easy_getinfo(curl, CURLINFO_TOTAL_TIME_T, &offinfo))
                  us2sec(stream, offinfo);
                break;
              case VAR_NAMELOOKUP_TIME:
                if(CURLE_OK ==
                   curl_easy_getinfo(curl, CURLINFO_NAMELOOKUP_TIME_T,
                                     &offinfo))
                  us2sec(stream, offinfo);
                break;
              case VAR_CONNECT_TIME:
                if(CURLE_OK ==
                   curl_easy_getinfo(curl, CURLINFO_CONNECT_TIME_T, &offinfo))
                  us2sec(stream, offinfo);
                break;
              case VAR_APPCONNECT_TIME:
                if(CURLE_OK ==
                   curl_easy_getinfo(curl, CURLINFO_APPCONNECT_TIME_T,
                                     &offinfo))
                  us2sec(stream, offinfo);
                break;
              case VAR_PRETRANSFER_TIME:
                if(CURLE_OK ==
                   curl_easy_getinfo(curl, CURLINFO_PRETRANSFER_TIME_T,
                                     &offinfo))
                  us2sec(stream, offinfo);
                break;
              case VAR_STARTTRANSFER_TIME:
                if(CURLE_OK ==
                   curl_easy_getinfo(curl, CURLINFO_STARTTRANSFER_TIME_T,
                                     &offinfo))
                  us2sec(stream, offinfo);
                break;
              case VAR_SIZE_UPLOAD:
                if(CURLE_OK ==
                   curl_easy_getinfo(curl, CURLINFO_SIZE_UPLOAD_T, &offinfo))
                  fprintf(stream, "%" CURL_FORMAT_CURL_OFF_TU, offinfo);
                break;
              case VAR_SIZE_DOWNLOAD:
380
381
382
383
384
385
386
387
388
      ptr += 2;
    }
    else {
      fputc(*ptr, stream);
      ptr++;
    }
  }

}







|
<
388
389
390
391
392
393
394
395

      ptr += 2;
    }
    else {
      fputc(*ptr, stream);
      ptr++;
    }
  }
}

Changes to jni/curl/src/tool_writeout.h.
22
23
24
25
26
27
28














29


30
31

32
33







34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
 *
 ***************************************************************************/
#include "tool_setup.h"
#include "tool_operate.h"

typedef enum {
  VAR_NONE,       /* must be the first */














  VAR_TOTAL_TIME,


  VAR_NAMELOOKUP_TIME,
  VAR_CONNECT_TIME,

  VAR_APPCONNECT_TIME,
  VAR_PRETRANSFER_TIME,







  VAR_STARTTRANSFER_TIME,
  VAR_SIZE_DOWNLOAD,
  VAR_SIZE_UPLOAD,
  VAR_SPEED_DOWNLOAD,
  VAR_SPEED_UPLOAD,
  VAR_HTTP_CODE,
  VAR_HTTP_CODE_PROXY,
  VAR_HEADER_SIZE,
  VAR_NUM_HEADERS,
  VAR_REQUEST_SIZE,
  VAR_EFFECTIVE_METHOD,
  VAR_EFFECTIVE_URL,
  VAR_CONTENT_TYPE,
  VAR_NUM_CONNECTS,
  VAR_REDIRECT_TIME,
  VAR_REDIRECT_COUNT,
  VAR_FTP_ENTRY_PATH,
  VAR_REDIRECT_URL,
  VAR_SSL_VERIFY_RESULT,
  VAR_PROXY_SSL_VERIFY_RESULT,
  VAR_EFFECTIVE_FILENAME,
  VAR_PRIMARY_IP,
  VAR_PRIMARY_PORT,
  VAR_LOCAL_IP,
  VAR_LOCAL_PORT,
  VAR_HTTP_VERSION,
  VAR_SCHEME,
  VAR_STDOUT,
  VAR_STDERR,
  VAR_JSON,
  VAR_NUM_OF_VARS /* must be the last */
} writeoutid;

typedef enum {
  JSON_NONE,
  JSON_STRING,
  JSON_LONG,







>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>

|
>
|

>
>
>
>
>
>
>
|




<
<
<
<
<
<
<
<
<
<
<
<
<

<
<
<
<
|
<
<
|

|
|







22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62













63




64


65
66
67
68
69
70
71
72
73
74
75
 *
 ***************************************************************************/
#include "tool_setup.h"
#include "tool_operate.h"

typedef enum {
  VAR_NONE,       /* must be the first */
  VAR_APPCONNECT_TIME,
  VAR_CONNECT_TIME,
  VAR_CONTENT_TYPE,
  VAR_EFFECTIVE_FILENAME,
  VAR_EFFECTIVE_METHOD,
  VAR_EFFECTIVE_URL,
  VAR_ERRORMSG,
  VAR_EXITCODE,
  VAR_FTP_ENTRY_PATH,
  VAR_HEADER_SIZE,
  VAR_HTTP_CODE,
  VAR_HTTP_CODE_PROXY,
  VAR_HTTP_VERSION,
  VAR_INPUT_URL,
  VAR_JSON,
  VAR_LOCAL_IP,
  VAR_LOCAL_PORT,
  VAR_NAMELOOKUP_TIME,
  VAR_NUM_CONNECTS,
  VAR_NUM_HEADERS,
  VAR_ONERROR,
  VAR_PRETRANSFER_TIME,
  VAR_PRIMARY_IP,
  VAR_PRIMARY_PORT,
  VAR_PROXY_SSL_VERIFY_RESULT,
  VAR_REDIRECT_COUNT,
  VAR_REDIRECT_TIME,
  VAR_REDIRECT_URL,
  VAR_REQUEST_SIZE,
  VAR_SCHEME,
  VAR_SIZE_DOWNLOAD,
  VAR_SIZE_UPLOAD,
  VAR_SPEED_DOWNLOAD,
  VAR_SPEED_UPLOAD,













  VAR_SSL_VERIFY_RESULT,




  VAR_STARTTRANSFER_TIME,


  VAR_STDERR,
  VAR_STDOUT,
  VAR_TOTAL_TIME,
  VAR_URLNUM,
  VAR_NUM_OF_VARS /* must be the last */
} writeoutid;

typedef enum {
  JSON_NONE,
  JSON_STRING,
  JSON_LONG,
78
79
80
81
82
83
84
85

86
87
  const char *name;
  writeoutid id;
  int is_ctrl;
  CURLINFO cinfo;
  jsontype jsontype;
};

void ourWriteOut(CURL *curl, struct per_transfer *per, const char *writeinfo);


#endif /* HEADER_CURL_TOOL_WRITEOUT_H */







|
>


83
84
85
86
87
88
89
90
91
92
93
  const char *name;
  writeoutid id;
  int is_ctrl;
  CURLINFO cinfo;
  jsontype jsontype;
};

void ourWriteOut(CURL *curl, struct per_transfer *per, const char *writeinfo,
                 CURLcode exitcode);

#endif /* HEADER_CURL_TOOL_WRITEOUT_H */
Changes to jni/curl/src/tool_writeout_json.c.
70
71
72
73
74
75
76
77

78
79
80
81
82
83
84
      if (*i < 32) {
        fprintf(stream, "u%04x", *i);
      }
      else {
        fputc(*i, stream);
      }
      break;
    };

  }
}

static int writeTime(FILE *str, CURL *curl, const char *key, CURLINFO ci)
{
  curl_off_t val = 0;
  if(CURLE_OK == curl_easy_getinfo(curl, ci, &val)) {







<
>







70
71
72
73
74
75
76

77
78
79
80
81
82
83
84
      if (*i < 32) {
        fprintf(stream, "u%04x", *i);
      }
      else {
        fputc(*i, stream);
      }
      break;

    }
  }
}

static int writeTime(FILE *str, CURL *curl, const char *key, CURLINFO ci)
{
  curl_off_t val = 0;
  if(CURLE_OK == curl_easy_getinfo(curl, ci, &val)) {
Changes to jni/curl/tests/FILEFORMAT.md.
64
65
66
67
68
69
70






























71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89

90
91
92
93
94
95
96

    %repeat[<number> x <string>]%

For example, to insert the word hello a 100 times:

    %repeat[100 x hello]%































# Variables

When the test is preprocessed, a range of "variables" in the test file will be
replaced by their content at that time.

Available substitute variables include:

- `%CLIENT6IP` - IPv6 address of the client running curl
- `%CLIENTIP` - IPv4 address of the client running curl
- `%CURL` - Path to the curl executable
- `%FILE_PWD` - Current directory, on windows prefixed with a slash
- `%FTP6PORT` - IPv6 port number of the FTP server
- `%FTPPORT` - Port number of the FTP server
- `%FTPSPORT` - Port number of the FTPS server
- `%FTPTIME2` - Timeout in seconds that should be just sufficient to receive a
  response from the test FTP server
- `%FTPTIME3` - Even longer than %FTPTIME2
- `%GOPHER6PORT` - IPv6 port number of the Gopher server
- `%GOPHERPORT` - Port number of the Gopher server

- `%HOST6IP` - IPv6 address of the host running this test
- `%HOSTIP` - IPv4 address of the host running this test
- `%HTTP6PORT` - IPv6 port number of the HTTP server
- `%HTTPPORT` - Port number of the HTTP server
- `%HTTP2PORT` - Port number of the HTTP/2 server
- `%HTTPSPORT` - Port number of the HTTPS server
- `%HTTPSPROXYPORT` - Port number of the HTTPS-proxy







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>



















>







64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127

    %repeat[<number> x <string>]%

For example, to insert the word hello a 100 times:

    %repeat[100 x hello]%

## Conditional lines

Lines in the test file can be made to appear conditionally on a specific
feature (see the "features" section below) being set or not set. If the
specific feature is present, the following lines will be output, otherwise it
outputs nothing, until a following else or endif clause. Like this:

    %if brotli
    Accept-Encoding
    %endif

It can also check for the inversed condition, so if the feature us *not* set by
the use of an exclamation mark:

    %if !brotli
    Accept-Encoding: not-brotli
    %endif

You can also make an "else" clause to get output for the opposite condition,
like:

    %if brotli
    Accept-Encoding: brotli
    %else
    Accept-Encoding: nothing
    %endif

**Note** that there can be no nested conditions. You can only do one
conditional at a time and you can only check for a single feature in it.

# Variables

When the test is preprocessed, a range of "variables" in the test file will be
replaced by their content at that time.

Available substitute variables include:

- `%CLIENT6IP` - IPv6 address of the client running curl
- `%CLIENTIP` - IPv4 address of the client running curl
- `%CURL` - Path to the curl executable
- `%FILE_PWD` - Current directory, on windows prefixed with a slash
- `%FTP6PORT` - IPv6 port number of the FTP server
- `%FTPPORT` - Port number of the FTP server
- `%FTPSPORT` - Port number of the FTPS server
- `%FTPTIME2` - Timeout in seconds that should be just sufficient to receive a
  response from the test FTP server
- `%FTPTIME3` - Even longer than %FTPTIME2
- `%GOPHER6PORT` - IPv6 port number of the Gopher server
- `%GOPHERPORT` - Port number of the Gopher server
- `%GOPHERSPORT` - Port number of the Gophers server
- `%HOST6IP` - IPv6 address of the host running this test
- `%HOSTIP` - IPv4 address of the host running this test
- `%HTTP6PORT` - IPv6 port number of the HTTP server
- `%HTTPPORT` - Port number of the HTTP server
- `%HTTP2PORT` - Port number of the HTTP/2 server
- `%HTTPSPORT` - Port number of the HTTPS server
- `%HTTPSPROXYPORT` - Port number of the HTTPS-proxy
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179

If the data contains `swsbounce` anywhere within the start and end tag, the
HTTP server will detect if this is a second request using the same test and
part number and will then increase the part number with one. This is useful
for auth tests and similar.

`sendzero=yes` means that the (FTP) server will "send" the data even if the
size is zero bytes. Used to verify curl's behaviour on zero bytes transfers.

`base64=yes` means that the data provided in the test-file is a chunk of data
encoded with base64. It is the only way a test case can contain binary
data. (This attribute can in fact be used on any section, but it doesn't make
much sense for other sections than "data").

`hex=yes` means that the data is a sequence of hex pairs. It will get decoded







|







196
197
198
199
200
201
202
203
204
205
206
207
208
209
210

If the data contains `swsbounce` anywhere within the start and end tag, the
HTTP server will detect if this is a second request using the same test and
part number and will then increase the part number with one. This is useful
for auth tests and similar.

`sendzero=yes` means that the (FTP) server will "send" the data even if the
size is zero bytes. Used to verify curl's behavior on zero bytes transfers.

`base64=yes` means that the data provided in the test-file is a chunk of data
encoded with base64. It is the only way a test case can contain binary
data. (This attribute can in fact be used on any section, but it doesn't make
much sense for other sections than "data").

`hex=yes` means that the data is a sequence of hex pairs. It will get decoded
295
296
297
298
299
300
301


302
303
304
305
306
307
308
### `<server>`
What server(s) this test case requires/uses. Available servers:

- `file`
- `ftp-ipv6`
- `ftp`
- `ftps`


- `http-ipv6`
- `http-proxy`
- `http-unix`
- `http/2`
- `http`
- `https`
- `httptls+srp-ipv6`







>
>







326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
### `<server>`
What server(s) this test case requires/uses. Available servers:

- `file`
- `ftp-ipv6`
- `ftp`
- `ftps`
- `gopher`
- `gophers`
- `http-ipv6`
- `http-proxy`
- `http-unix`
- `http/2`
- `http`
- `https`
- `httptls+srp-ipv6`
340
341
342
343
344
345
346

347
348
349
350
351
352
353
- `DoH`
- `getrlimit`
- `GnuTLS`
- `GSS-API`
- `HSTS`
- `HTTP-auth`
- `http/2`

- `idn`
- `ipv6`
- `Kerberos`
- `large_file`
- `ld_preload`
- `libz`
- `manual`







>







373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
- `DoH`
- `getrlimit`
- `GnuTLS`
- `GSS-API`
- `HSTS`
- `HTTP-auth`
- `http/2`
- `hyper`
- `idn`
- `ipv6`
- `Kerberos`
- `large_file`
- `ld_preload`
- `libz`
- `manual`
370
371
372
373
374
375
376

377
378
379
380
381
382
383
- `threaded-resolver`
- `TLS-SRP`
- `TrackMemory`
- `typecheck`
- `unittest`
- `unix-sockets`
- `verbose-strings`

- `win32`

as well as each protocol that curl supports.  A protocol only needs to be
specified if it is different from the server (useful when the server
is `none`).

### `<killserver>`







>







404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
- `threaded-resolver`
- `TLS-SRP`
- `TrackMemory`
- `typecheck`
- `unittest`
- `unix-sockets`
- `verbose-strings`
- `wakeup`
- `win32`

as well as each protocol that curl supports.  A protocol only needs to be
specified if it is different from the server (useful when the server
is `none`).

### `<killserver>`
Changes to jni/curl/tests/Makefile.in.
344
345
346
347
348
349
350

351
352
353
354
355
356
357
STRIP = @STRIP@
SUPPORT_FEATURES = @SUPPORT_FEATURES@
SUPPORT_PROTOCOLS = @SUPPORT_PROTOCOLS@
USE_ARES = @USE_ARES@
USE_BEARSSL = @USE_BEARSSL@
USE_GNUTLS = @USE_GNUTLS@
USE_GNUTLS_NETTLE = @USE_GNUTLS_NETTLE@

USE_LIBRTMP = @USE_LIBRTMP@
USE_LIBSSH = @USE_LIBSSH@
USE_LIBSSH2 = @USE_LIBSSH2@
USE_MBEDTLS = @USE_MBEDTLS@
USE_MESALINK = @USE_MESALINK@
USE_NGHTTP2 = @USE_NGHTTP2@
USE_NGHTTP3 = @USE_NGHTTP3@







>







344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
STRIP = @STRIP@
SUPPORT_FEATURES = @SUPPORT_FEATURES@
SUPPORT_PROTOCOLS = @SUPPORT_PROTOCOLS@
USE_ARES = @USE_ARES@
USE_BEARSSL = @USE_BEARSSL@
USE_GNUTLS = @USE_GNUTLS@
USE_GNUTLS_NETTLE = @USE_GNUTLS_NETTLE@
USE_HYPER = @USE_HYPER@
USE_LIBRTMP = @USE_LIBRTMP@
USE_LIBSSH = @USE_LIBSSH@
USE_LIBSSH2 = @USE_LIBSSH2@
USE_MBEDTLS = @USE_MBEDTLS@
USE_MESALINK = @USE_MESALINK@
USE_NGHTTP2 = @USE_NGHTTP2@
USE_NGHTTP3 = @USE_NGHTTP3@
Changes to jni/curl/tests/README.md.
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119

  Tests which use the ssh test server, SCP/SFTP/SOCKS tests, might be badly
  influenced by the output of system wide or user specific shell startup
  scripts, .bashrc, .profile, /etc/csh.cshrc, .login, /etc/bashrc, etc. which
  output text messages or escape sequences on user login.  When these shell
  startup messages or escape sequences are output they might corrupt the
  expected stream of data which flows to the sftp-server or from the ssh
  client which can result in bad test behaviour or even prevent the test
  server from running.

  If the test suite ssh or sftp server fails to start up and logs the message
  'Received message too long' then you are certainly suffering the unwanted
  output of a shell startup script.  Locate, cleanup or adjust the shell
  script.








|







105
106
107
108
109
110
111
112
113
114
115
116
117
118
119

  Tests which use the ssh test server, SCP/SFTP/SOCKS tests, might be badly
  influenced by the output of system wide or user specific shell startup
  scripts, .bashrc, .profile, /etc/csh.cshrc, .login, /etc/bashrc, etc. which
  output text messages or escape sequences on user login.  When these shell
  startup messages or escape sequences are output they might corrupt the
  expected stream of data which flows to the sftp-server or from the ssh
  client which can result in bad test behavior or even prevent the test
  server from running.

  If the test suite ssh or sftp server fails to start up and logs the message
  'Received message too long' then you are certainly suffering the unwanted
  output of a shell startup script.  Locate, cleanup or adjust the shell
  script.

Changes to jni/curl/tests/badsymbols.pl.
40
41
42
43
44
45
46








47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69

70
71
72
73
74
75
76
77
78
79
80
81
82
83



84
85
86
87
88
89
90
91
92





93
94
95
96
97
98
99
100
101
102
103
104

105





106
107
108
109
110
111
112
    1;
};
# Set default values if configure has not generated a configurehelp.pm file.
# This is the case with cmake.
if (!$rc) {
    $Cpreprocessor = 'cpp';
}









# we may get the dir root pointed out
my $root=$ARGV[0] || ".";

# need an include directory when building out-of-tree
my $i = ($ARGV[1]) ? "-I$ARGV[1] " : '';

my $incdir = "$root/include/curl";

my $verbose=0;
my $summary=0;
my $misses=0;

my @syms;
my %doc;
my %rem;

sub scanenums {
    my ($file)=@_;
    my $skipit = 0;

    open H_IN, "-|", "$Cpreprocessor $i$file" || die "Cannot preprocess $file";
    while ( <H_IN> ) {

        if( /^#(line|) (\d+) \"(.*)\"/) {
            # if the included file isn't in our incdir, then we skip this section
            # until next #line
            #
            if($3 !~ /^$incdir/) {
                $skipit = 1;
                next;
            }
            # parse this!
            $skipit = 0;
            next;
        }
        if($skipit) {
            next;



        }
        if ( /enum\s+(\S+\s+)?{/ .. /}/ ) {
            s/^\s+//;
            chomp;
            s/[,\s].*//;
            if(($_ !~ /\}(;|)/) &&
               ($_ ne "typedef") &&
               ($_ ne "enum") &&
               ($_ !~ /^[ \t]*$/)) {





                push @syms, $_;
            }
        }
    }
    close H_IN || die "Error preprocessing $file";
}

sub scanheader {
    my ($f)=@_;
    scanenums($f);
    open H, "<$f";
    while(<H>) {

        if (/^#define +([^ \n]*)/) {





            push @syms, $1;
        }
    }
    close H;
}









>
>
>
>
>
>
>
>









<













>














>
>
>









>
>
>
>
>












>

>
>
>
>
>







40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63

64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
    1;
};
# Set default values if configure has not generated a configurehelp.pm file.
# This is the case with cmake.
if (!$rc) {
    $Cpreprocessor = 'cpp';
}

my $verbose=0;

# verbose mode when -v is the first argument
if($ARGV[0] eq "-v") {
    $verbose=1;
    shift;
}

# we may get the dir root pointed out
my $root=$ARGV[0] || ".";

# need an include directory when building out-of-tree
my $i = ($ARGV[1]) ? "-I$ARGV[1] " : '';

my $incdir = "$root/include/curl";


my $summary=0;
my $misses=0;

my @syms;
my %doc;
my %rem;

sub scanenums {
    my ($file)=@_;
    my $skipit = 0;

    open H_IN, "-|", "$Cpreprocessor $i$file" || die "Cannot preprocess $file";
    while ( <H_IN> ) {
        my ($line, $linenum) = ($_, $.);
        if( /^#(line|) (\d+) \"(.*)\"/) {
            # if the included file isn't in our incdir, then we skip this section
            # until next #line
            #
            if($3 !~ /^$incdir/) {
                $skipit = 1;
                next;
            }
            # parse this!
            $skipit = 0;
            next;
        }
        if($skipit) {
            next;
        }
        if (/^#/) {
            next;
        }
        if ( /enum\s+(\S+\s+)?{/ .. /}/ ) {
            s/^\s+//;
            chomp;
            s/[,\s].*//;
            if(($_ !~ /\}(;|)/) &&
               ($_ ne "typedef") &&
               ($_ ne "enum") &&
               ($_ !~ /^[ \t]*$/)) {
                if($verbose) {
                    print "Source: $Cpreprocessor $i$file\n";
                    print "Symbol: $_\n";
                    print "Line #$linenum: $line\n\n";
                }
                push @syms, $_;
            }
        }
    }
    close H_IN || die "Error preprocessing $file";
}

sub scanheader {
    my ($f)=@_;
    scanenums($f);
    open H, "<$f";
    while(<H>) {
        my ($line, $linenum) = ($_, $.);
        if (/^#define +([^ \n]*)/) {
            if($verbose) {
                print "Source: $f\n";
                print "Symbol: $1\n";
                print "Line #$linenum: $line\n\n";
            }
            push @syms, $1;
        }
    }
    close H;
}


Changes to jni/curl/tests/certs/Makefile.in.
323
324
325
326
327
328
329

330
331
332
333
334
335
336
STRIP = @STRIP@
SUPPORT_FEATURES = @SUPPORT_FEATURES@
SUPPORT_PROTOCOLS = @SUPPORT_PROTOCOLS@
USE_ARES = @USE_ARES@
USE_BEARSSL = @USE_BEARSSL@
USE_GNUTLS = @USE_GNUTLS@
USE_GNUTLS_NETTLE = @USE_GNUTLS_NETTLE@

USE_LIBRTMP = @USE_LIBRTMP@
USE_LIBSSH = @USE_LIBSSH@
USE_LIBSSH2 = @USE_LIBSSH2@
USE_MBEDTLS = @USE_MBEDTLS@
USE_MESALINK = @USE_MESALINK@
USE_NGHTTP2 = @USE_NGHTTP2@
USE_NGHTTP3 = @USE_NGHTTP3@







>







323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
STRIP = @STRIP@
SUPPORT_FEATURES = @SUPPORT_FEATURES@
SUPPORT_PROTOCOLS = @SUPPORT_PROTOCOLS@
USE_ARES = @USE_ARES@
USE_BEARSSL = @USE_BEARSSL@
USE_GNUTLS = @USE_GNUTLS@
USE_GNUTLS_NETTLE = @USE_GNUTLS_NETTLE@
USE_HYPER = @USE_HYPER@
USE_LIBRTMP = @USE_LIBRTMP@
USE_LIBSSH = @USE_LIBSSH@
USE_LIBSSH2 = @USE_LIBSSH2@
USE_MBEDTLS = @USE_MBEDTLS@
USE_MESALINK = @USE_MESALINK@
USE_NGHTTP2 = @USE_NGHTTP2@
USE_NGHTTP3 = @USE_NGHTTP3@
Changes to jni/curl/tests/certs/scripts/Makefile.in.
263
264
265
266
267
268
269

270
271
272
273
274
275
276
STRIP = @STRIP@
SUPPORT_FEATURES = @SUPPORT_FEATURES@
SUPPORT_PROTOCOLS = @SUPPORT_PROTOCOLS@
USE_ARES = @USE_ARES@
USE_BEARSSL = @USE_BEARSSL@
USE_GNUTLS = @USE_GNUTLS@
USE_GNUTLS_NETTLE = @USE_GNUTLS_NETTLE@

USE_LIBRTMP = @USE_LIBRTMP@
USE_LIBSSH = @USE_LIBSSH@
USE_LIBSSH2 = @USE_LIBSSH2@
USE_MBEDTLS = @USE_MBEDTLS@
USE_MESALINK = @USE_MESALINK@
USE_NGHTTP2 = @USE_NGHTTP2@
USE_NGHTTP3 = @USE_NGHTTP3@







>







263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
STRIP = @STRIP@
SUPPORT_FEATURES = @SUPPORT_FEATURES@
SUPPORT_PROTOCOLS = @SUPPORT_PROTOCOLS@
USE_ARES = @USE_ARES@
USE_BEARSSL = @USE_BEARSSL@
USE_GNUTLS = @USE_GNUTLS@
USE_GNUTLS_NETTLE = @USE_GNUTLS_NETTLE@
USE_HYPER = @USE_HYPER@
USE_LIBRTMP = @USE_LIBRTMP@
USE_LIBSSH = @USE_LIBSSH@
USE_LIBSSH2 = @USE_LIBSSH2@
USE_MBEDTLS = @USE_MBEDTLS@
USE_MESALINK = @USE_MESALINK@
USE_NGHTTP2 = @USE_NGHTTP2@
USE_NGHTTP3 = @USE_NGHTTP3@
Changes to jni/curl/tests/data/Makefile.in.
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#***************************************************************************
#                                  _   _ ____  _
#  Project                     ___| | | |  _ \| |
#                             / __| | | | |_) | |
#                            | (__| |_| |  _ <| |___
#                             \___|\___/|_| \_\_____|
#
# Copyright (C) 1998 - 2020, 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 https://curl.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







|







17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#***************************************************************************
#                                  _   _ ____  _
#  Project                     ___| | | |  _ \| |
#                             / __| | | | |_) | |
#                            | (__| |_| |  _ <| |___
#                             \___|\___/|_| \_\_____|
#
# Copyright (C) 1998 - 2021, 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 https://curl.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
285
286
287
288
289
290
291

292
293
294
295
296
297
298
STRIP = @STRIP@
SUPPORT_FEATURES = @SUPPORT_FEATURES@
SUPPORT_PROTOCOLS = @SUPPORT_PROTOCOLS@
USE_ARES = @USE_ARES@
USE_BEARSSL = @USE_BEARSSL@
USE_GNUTLS = @USE_GNUTLS@
USE_GNUTLS_NETTLE = @USE_GNUTLS_NETTLE@

USE_LIBRTMP = @USE_LIBRTMP@
USE_LIBSSH = @USE_LIBSSH@
USE_LIBSSH2 = @USE_LIBSSH2@
USE_MBEDTLS = @USE_MBEDTLS@
USE_MESALINK = @USE_MESALINK@
USE_NGHTTP2 = @USE_NGHTTP2@
USE_NGHTTP3 = @USE_NGHTTP3@







>







285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
STRIP = @STRIP@
SUPPORT_FEATURES = @SUPPORT_FEATURES@
SUPPORT_PROTOCOLS = @SUPPORT_PROTOCOLS@
USE_ARES = @USE_ARES@
USE_BEARSSL = @USE_BEARSSL@
USE_GNUTLS = @USE_GNUTLS@
USE_GNUTLS_NETTLE = @USE_GNUTLS_NETTLE@
USE_HYPER = @USE_HYPER@
USE_LIBRTMP = @USE_LIBRTMP@
USE_LIBSSH = @USE_LIBSSH@
USE_LIBSSH2 = @USE_LIBSSH2@
USE_MBEDTLS = @USE_MBEDTLS@
USE_MESALINK = @USE_MESALINK@
USE_NGHTTP2 = @USE_NGHTTP2@
USE_NGHTTP3 = @USE_NGHTTP3@
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
test334 test335 test336 test337 test338 test339 test340 test341 test342 \
test343 test344 test345 test346 test347 test348 \
test350 test351 test352 test353 test354 test355 test356 test357 test358 \
test359 \
test393 test394 test395 test396 test397 \
\
test400 test401 test402 test403 test404 test405 test406 test407 test408 \
test409 \
\
test430 test431 test432 test433 test434 \
\
test490 test491 test492 test493 \
\
test500 test501 test502 test503 test504 test505 test506 test507 test508 \
test509 test510 test511 test512 test513 test514 test515 test516 test517 \
test518 test519 test520 test521 test522 test523 test524 test525 test526 \
test527 test528 test529         test531 test532 test533 test534 test535 \
        test537 test538 test539 test540 test541 test542 test543 test544 \
test545 test546 test547 test548 test549 test550 test551 test552 test553 \
test554 test555 test556 test557 test558 test559 test560 test561 test562 \
test563 test564 test565 test566 test567 test568 test569 test570 test571 \
test572 test573 test574 test575 test576 test577 test578 test579 test580 \
test581 test582 test583         test585 test586 test587 test588 test589 \
test590 test591 test592 test593 test594 test595 test596 test597 test598 \
test599 test600 test601 test602 test603 test604 test605 test606 test607 \
test608 test609 test610 test611 test612 test613 test614 test615 test616 \
test617 test618 test619 test620 test621 test622 test623 test624 test625 \
test626 test627 test628 test629 test630 test631 test632 test633 test634 \
test635 test636 test637 test638 test639 test640 test641 test642 \
test643 test644 test645 test646 test647 test648 test649 test650 test651 \







|














|







409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
test334 test335 test336 test337 test338 test339 test340 test341 test342 \
test343 test344 test345 test346 test347 test348 \
test350 test351 test352 test353 test354 test355 test356 test357 test358 \
test359 \
test393 test394 test395 test396 test397 \
\
test400 test401 test402 test403 test404 test405 test406 test407 test408 \
test409 test410 \
\
test430 test431 test432 test433 test434 \
\
test490 test491 test492 test493 \
\
test500 test501 test502 test503 test504 test505 test506 test507 test508 \
test509 test510 test511 test512 test513 test514 test515 test516 test517 \
test518 test519 test520 test521 test522 test523 test524 test525 test526 \
test527 test528 test529         test531 test532 test533 test534 test535 \
        test537 test538 test539 test540 test541 test542 test543 test544 \
test545 test546 test547 test548 test549 test550 test551 test552 test553 \
test554 test555 test556 test557 test558 test559 test560 test561 test562 \
test563 test564 test565 test566 test567 test568 test569 test570 test571 \
test572 test573 test574 test575 test576 test577 test578 test579 test580 \
test581 test582 test583 test584 test585 test586 test587 test588 test589 \
test590 test591 test592 test593 test594 test595 test596 test597 test598 \
test599 test600 test601 test602 test603 test604 test605 test606 test607 \
test608 test609 test610 test611 test612 test613 test614 test615 test616 \
test617 test618 test619 test620 test621 test622 test623 test624 test625 \
test626 test627 test628 test629 test630 test631 test632 test633 test634 \
test635 test636 test637 test638 test639 test640 test641 test642 \
test643 test644 test645 test646 test647 test648 test649 test650 test651 \
481
482
483
484
485
486
487
488
489
490
491


492
493
494
495
496
497
498
499
500
501

502
503
504
505
506
507
508
test1120 test1121 test1122 test1123 test1124 test1125 test1126 test1127 \
test1128 test1129 test1130 test1131 test1132 test1133 test1134 test1135 \
test1136 test1137 test1138 test1139 test1140 test1141 test1142 test1143 \
test1144 test1145 test1146 test1147 test1148 test1149 test1150 test1151 \
test1152 test1153 test1154 test1155 test1156 test1157 test1158 test1159 \
test1160 test1161 test1162 test1163 test1164 test1165 test1166 test1167 \
test1168          test1170 test1171 test1172 test1173 test1174 test1175 \
test1176 test1177 test1178 test1179 \
\
test1190 test1191 test1192 test1193 test1194 test1195 test1196 test1197 \
\


test1200 test1201 test1202 test1203 test1204 test1205 test1206 test1207 \
test1208 test1209 test1210 test1211 test1212 test1213 test1214 test1215 \
test1216 test1217 test1218 test1219 test1220                   test1223 \
test1224 test1225 test1226 test1227 test1228 test1229 test1230 test1231 \
test1232 test1233 test1234 test1235 test1236 test1237 test1238 test1239 \
test1240 test1241 test1242 test1243 test1244 test1245 test1246 test1247 \
test1248 test1249 test1250 test1251 test1252 test1253 test1254 test1255 \
test1256 test1257 test1258 test1259 test1260 test1261 test1262 test1263 \
test1264 test1265 test1266 test1267 test1268 test1269 test1270 test1271 \
\

test1280 test1281 test1282 test1283 test1284 test1285 test1286 test1287 \
test1288 test1289 test1290 test1291 test1292 test1293 test1294 test1295 \
test1296 test1297 test1298 test1299 test1300 test1301 test1302 test1303 \
test1304 test1305 test1306 test1307 test1308 test1309 test1310 test1311 \
test1312 test1313 test1314 test1315 test1316 test1317 test1318 test1319 \
test1320 test1321 test1322 test1323 test1324 test1325 test1326 test1327 \
test1328 test1329 test1330 test1331 test1332 test1333 test1334 test1335 \







|

|

>
>









<
>







482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503

504
505
506
507
508
509
510
511
test1120 test1121 test1122 test1123 test1124 test1125 test1126 test1127 \
test1128 test1129 test1130 test1131 test1132 test1133 test1134 test1135 \
test1136 test1137 test1138 test1139 test1140 test1141 test1142 test1143 \
test1144 test1145 test1146 test1147 test1148 test1149 test1150 test1151 \
test1152 test1153 test1154 test1155 test1156 test1157 test1158 test1159 \
test1160 test1161 test1162 test1163 test1164 test1165 test1166 test1167 \
test1168          test1170 test1171 test1172 test1173 test1174 test1175 \
test1176 test1177 test1178 test1179 test1180 test1181 \
\
test1188 \
\
test1190 test1191 test1192 test1193 test1194 test1195 test1196 test1197 \
test1198 test1199 \
test1200 test1201 test1202 test1203 test1204 test1205 test1206 test1207 \
test1208 test1209 test1210 test1211 test1212 test1213 test1214 test1215 \
test1216 test1217 test1218 test1219 test1220                   test1223 \
test1224 test1225 test1226 test1227 test1228 test1229 test1230 test1231 \
test1232 test1233 test1234 test1235 test1236 test1237 test1238 test1239 \
test1240 test1241 test1242 test1243 test1244 test1245 test1246 test1247 \
test1248 test1249 test1250 test1251 test1252 test1253 test1254 test1255 \
test1256 test1257 test1258 test1259 test1260 test1261 test1262 test1263 \
test1264 test1265 test1266 test1267 test1268 test1269 test1270 test1271 \

test1272 \
test1280 test1281 test1282 test1283 test1284 test1285 test1286 test1287 \
test1288 test1289 test1290 test1291 test1292 test1293 test1294 test1295 \
test1296 test1297 test1298 test1299 test1300 test1301 test1302 test1303 \
test1304 test1305 test1306 test1307 test1308 test1309 test1310 test1311 \
test1312 test1313 test1314 test1315 test1316 test1317 test1318 test1319 \
test1320 test1321 test1322 test1323 test1324 test1325 test1326 test1327 \
test1328 test1329 test1330 test1331 test1332 test1333 test1334 test1335 \
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555



556
557
558
559
560
561
562
test1516 test1517 test1518 test1519 test1520 test1521 test1522 test1523 \
test1524 test1525 test1526 test1527 test1528 test1529 test1530 test1531 \
test1532 test1533 test1534 test1535 test1536 test1537 test1538 test1539 \
test1540 \
\
test1550 test1551 test1552 test1553 test1554 test1555 test1556 test1557 \
test1558 test1559 test1560 test1561 test1562 test1563 test1564 test1565 \
test1566 test1567 \
\
test1590 test1591 test1592 test1593 test1594 test1595 test1596 \
\
test1600 test1601 test1602 test1603 test1604 test1605 test1606 test1607 \
test1608 test1609 test1610 test1611 test1612 \
\
test1620 test1621 \
\
test1630 test1631 test1632 test1633 \
\
test1650 test1651 test1652 test1653 test1654 test1655 \
test1660 \
\
test1700 test1701 test1702 \
\
test1800 test1801 \
\
                                    test1904 test1905 test1906 test1907 \
test1908 test1909 test1910 test1911 test1912 test1913 test1914 test1915 \



\
test2000 test2001 test2002 test2003 test2004 test2005 test2006 test2007 \
test2008 test2009 test2010 test2011 test2012 test2013 test2014 test2015 \
test2016 test2017 test2018 test2019 test2020 test2021 test2022 test2023 \
test2024 test2025 test2026 test2027 test2028 test2029 test2030 test2031 \
test2032          test2034 test2035 test2036 test2037 test2038 test2039 \
test2040 test2041 test2042 test2043 test2044 test2045 test2046 test2047 \







|




|



|










>
>
>







532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
test1516 test1517 test1518 test1519 test1520 test1521 test1522 test1523 \
test1524 test1525 test1526 test1527 test1528 test1529 test1530 test1531 \
test1532 test1533 test1534 test1535 test1536 test1537 test1538 test1539 \
test1540 \
\
test1550 test1551 test1552 test1553 test1554 test1555 test1556 test1557 \
test1558 test1559 test1560 test1561 test1562 test1563 test1564 test1565 \
test1566 test1567 test1568 \
\
test1590 test1591 test1592 test1593 test1594 test1595 test1596 \
\
test1600 test1601 test1602 test1603 test1604 test1605 test1606 test1607 \
test1608 test1609 test1610 test1611 test1612 test1613 \
\
test1620 test1621 \
\
test1630 test1631 test1632 test1633 test1634 \
\
test1650 test1651 test1652 test1653 test1654 test1655 \
test1660 \
\
test1700 test1701 test1702 \
\
test1800 test1801 \
\
                                    test1904 test1905 test1906 test1907 \
test1908 test1909 test1910 test1911 test1912 test1913 test1914 test1915 \
test1916 test1917 test1918 \
\
test1933 test1934 test1935 test1936 \
\
test2000 test2001 test2002 test2003 test2004 test2005 test2006 test2007 \
test2008 test2009 test2010 test2011 test2012 test2013 test2014 test2015 \
test2016 test2017 test2018 test2019 test2020 test2021 test2022 test2023 \
test2024 test2025 test2026 test2027 test2028 test2029 test2030 test2031 \
test2032          test2034 test2035 test2036 test2037 test2038 test2039 \
test2040 test2041 test2042 test2043 test2044 test2045 test2046 test2047 \
Changes to jni/curl/tests/data/Makefile.inc.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#***************************************************************************
#                                  _   _ ____  _
#  Project                     ___| | | |  _ \| |
#                             / __| | | | |_) | |
#                            | (__| |_| |  _ <| |___
#                             \___|\___/|_| \_\_____|
#
# Copyright (C) 1998 - 2020, 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 https://curl.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







|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#***************************************************************************
#                                  _   _ ____  _
#  Project                     ___| | | |  _ \| |
#                             / __| | | | |_) | |
#                            | (__| |_| |  _ <| |___
#                             \___|\___/|_| \_\_____|
#
# Copyright (C) 1998 - 2021, 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 https://curl.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
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
test334 test335 test336 test337 test338 test339 test340 test341 test342 \
test343 test344 test345 test346 test347 test348 \
test350 test351 test352 test353 test354 test355 test356 test357 test358 \
test359 \
test393 test394 test395 test396 test397 \
\
test400 test401 test402 test403 test404 test405 test406 test407 test408 \
test409 \
\
test430 test431 test432 test433 test434 \
\
test490 test491 test492 test493 \
\
test500 test501 test502 test503 test504 test505 test506 test507 test508 \
test509 test510 test511 test512 test513 test514 test515 test516 test517 \
test518 test519 test520 test521 test522 test523 test524 test525 test526 \
test527 test528 test529         test531 test532 test533 test534 test535 \
        test537 test538 test539 test540 test541 test542 test543 test544 \
test545 test546 test547 test548 test549 test550 test551 test552 test553 \
test554 test555 test556 test557 test558 test559 test560 test561 test562 \
test563 test564 test565 test566 test567 test568 test569 test570 test571 \
test572 test573 test574 test575 test576 test577 test578 test579 test580 \
test581 test582 test583         test585 test586 test587 test588 test589 \
test590 test591 test592 test593 test594 test595 test596 test597 test598 \
test599 test600 test601 test602 test603 test604 test605 test606 test607 \
test608 test609 test610 test611 test612 test613 test614 test615 test616 \
test617 test618 test619 test620 test621 test622 test623 test624 test625 \
test626 test627 test628 test629 test630 test631 test632 test633 test634 \
test635 test636 test637 test638 test639 test640 test641 test642 \
test643 test644 test645 test646 test647 test648 test649 test650 test651 \







|














|







60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
test334 test335 test336 test337 test338 test339 test340 test341 test342 \
test343 test344 test345 test346 test347 test348 \
test350 test351 test352 test353 test354 test355 test356 test357 test358 \
test359 \
test393 test394 test395 test396 test397 \
\
test400 test401 test402 test403 test404 test405 test406 test407 test408 \
test409 test410 \
\
test430 test431 test432 test433 test434 \
\
test490 test491 test492 test493 \
\
test500 test501 test502 test503 test504 test505 test506 test507 test508 \
test509 test510 test511 test512 test513 test514 test515 test516 test517 \
test518 test519 test520 test521 test522 test523 test524 test525 test526 \
test527 test528 test529         test531 test532 test533 test534 test535 \
        test537 test538 test539 test540 test541 test542 test543 test544 \
test545 test546 test547 test548 test549 test550 test551 test552 test553 \
test554 test555 test556 test557 test558 test559 test560 test561 test562 \
test563 test564 test565 test566 test567 test568 test569 test570 test571 \
test572 test573 test574 test575 test576 test577 test578 test579 test580 \
test581 test582 test583 test584 test585 test586 test587 test588 test589 \
test590 test591 test592 test593 test594 test595 test596 test597 test598 \
test599 test600 test601 test602 test603 test604 test605 test606 test607 \
test608 test609 test610 test611 test612 test613 test614 test615 test616 \
test617 test618 test619 test620 test621 test622 test623 test624 test625 \
test626 test627 test628 test629 test630 test631 test632 test633 test634 \
test635 test636 test637 test638 test639 test640 test641 test642 \
test643 test644 test645 test646 test647 test648 test649 test650 test651 \
133
134
135
136
137
138
139
140
141
142
143


144
145
146
147
148
149
150
151
152
153

154
155
156
157
158
159
160
test1120 test1121 test1122 test1123 test1124 test1125 test1126 test1127 \
test1128 test1129 test1130 test1131 test1132 test1133 test1134 test1135 \
test1136 test1137 test1138 test1139 test1140 test1141 test1142 test1143 \
test1144 test1145 test1146 test1147 test1148 test1149 test1150 test1151 \
test1152 test1153 test1154 test1155 test1156 test1157 test1158 test1159 \
test1160 test1161 test1162 test1163 test1164 test1165 test1166 test1167 \
test1168          test1170 test1171 test1172 test1173 test1174 test1175 \
test1176 test1177 test1178 test1179 \
\
test1190 test1191 test1192 test1193 test1194 test1195 test1196 test1197 \
\


test1200 test1201 test1202 test1203 test1204 test1205 test1206 test1207 \
test1208 test1209 test1210 test1211 test1212 test1213 test1214 test1215 \
test1216 test1217 test1218 test1219 test1220                   test1223 \
test1224 test1225 test1226 test1227 test1228 test1229 test1230 test1231 \
test1232 test1233 test1234 test1235 test1236 test1237 test1238 test1239 \
test1240 test1241 test1242 test1243 test1244 test1245 test1246 test1247 \
test1248 test1249 test1250 test1251 test1252 test1253 test1254 test1255 \
test1256 test1257 test1258 test1259 test1260 test1261 test1262 test1263 \
test1264 test1265 test1266 test1267 test1268 test1269 test1270 test1271 \
\

test1280 test1281 test1282 test1283 test1284 test1285 test1286 test1287 \
test1288 test1289 test1290 test1291 test1292 test1293 test1294 test1295 \
test1296 test1297 test1298 test1299 test1300 test1301 test1302 test1303 \
test1304 test1305 test1306 test1307 test1308 test1309 test1310 test1311 \
test1312 test1313 test1314 test1315 test1316 test1317 test1318 test1319 \
test1320 test1321 test1322 test1323 test1324 test1325 test1326 test1327 \
test1328 test1329 test1330 test1331 test1332 test1333 test1334 test1335 \







|

|

>
>









<
>







133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154

155
156
157
158
159
160
161
162
test1120 test1121 test1122 test1123 test1124 test1125 test1126 test1127 \
test1128 test1129 test1130 test1131 test1132 test1133 test1134 test1135 \
test1136 test1137 test1138 test1139 test1140 test1141 test1142 test1143 \
test1144 test1145 test1146 test1147 test1148 test1149 test1150 test1151 \
test1152 test1153 test1154 test1155 test1156 test1157 test1158 test1159 \
test1160 test1161 test1162 test1163 test1164 test1165 test1166 test1167 \
test1168          test1170 test1171 test1172 test1173 test1174 test1175 \
test1176 test1177 test1178 test1179 test1180 test1181 \
\
test1188 \
\
test1190 test1191 test1192 test1193 test1194 test1195 test1196 test1197 \
test1198 test1199 \
test1200 test1201 test1202 test1203 test1204 test1205 test1206 test1207 \
test1208 test1209 test1210 test1211 test1212 test1213 test1214 test1215 \
test1216 test1217 test1218 test1219 test1220                   test1223 \
test1224 test1225 test1226 test1227 test1228 test1229 test1230 test1231 \
test1232 test1233 test1234 test1235 test1236 test1237 test1238 test1239 \
test1240 test1241 test1242 test1243 test1244 test1245 test1246 test1247 \
test1248 test1249 test1250 test1251 test1252 test1253 test1254 test1255 \
test1256 test1257 test1258 test1259 test1260 test1261 test1262 test1263 \
test1264 test1265 test1266 test1267 test1268 test1269 test1270 test1271 \

test1272 \
test1280 test1281 test1282 test1283 test1284 test1285 test1286 test1287 \
test1288 test1289 test1290 test1291 test1292 test1293 test1294 test1295 \
test1296 test1297 test1298 test1299 test1300 test1301 test1302 test1303 \
test1304 test1305 test1306 test1307 test1308 test1309 test1310 test1311 \
test1312 test1313 test1314 test1315 test1316 test1317 test1318 test1319 \
test1320 test1321 test1322 test1323 test1324 test1325 test1326 test1327 \
test1328 test1329 test1330 test1331 test1332 test1333 test1334 test1335 \
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207



208
209
210
211
212
213
214
test1516 test1517 test1518 test1519 test1520 test1521 test1522 test1523 \
test1524 test1525 test1526 test1527 test1528 test1529 test1530 test1531 \
test1532 test1533 test1534 test1535 test1536 test1537 test1538 test1539 \
test1540 \
\
test1550 test1551 test1552 test1553 test1554 test1555 test1556 test1557 \
test1558 test1559 test1560 test1561 test1562 test1563 test1564 test1565 \
test1566 test1567 \
\
test1590 test1591 test1592 test1593 test1594 test1595 test1596 \
\
test1600 test1601 test1602 test1603 test1604 test1605 test1606 test1607 \
test1608 test1609 test1610 test1611 test1612 \
\
test1620 test1621 \
\
test1630 test1631 test1632 test1633 \
\
test1650 test1651 test1652 test1653 test1654 test1655 \
test1660 \
\
test1700 test1701 test1702 \
\
test1800 test1801 \
\
                                    test1904 test1905 test1906 test1907 \
test1908 test1909 test1910 test1911 test1912 test1913 test1914 test1915 \



\
test2000 test2001 test2002 test2003 test2004 test2005 test2006 test2007 \
test2008 test2009 test2010 test2011 test2012 test2013 test2014 test2015 \
test2016 test2017 test2018 test2019 test2020 test2021 test2022 test2023 \
test2024 test2025 test2026 test2027 test2028 test2029 test2030 test2031 \
test2032          test2034 test2035 test2036 test2037 test2038 test2039 \
test2040 test2041 test2042 test2043 test2044 test2045 test2046 test2047 \







|




|



|










>
>
>







183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
test1516 test1517 test1518 test1519 test1520 test1521 test1522 test1523 \
test1524 test1525 test1526 test1527 test1528 test1529 test1530 test1531 \
test1532 test1533 test1534 test1535 test1536 test1537 test1538 test1539 \
test1540 \
\
test1550 test1551 test1552 test1553 test1554 test1555 test1556 test1557 \
test1558 test1559 test1560 test1561 test1562 test1563 test1564 test1565 \
test1566 test1567 test1568 \
\
test1590 test1591 test1592 test1593 test1594 test1595 test1596 \
\
test1600 test1601 test1602 test1603 test1604 test1605 test1606 test1607 \
test1608 test1609 test1610 test1611 test1612 test1613 \
\
test1620 test1621 \
\
test1630 test1631 test1632 test1633 test1634 \
\
test1650 test1651 test1652 test1653 test1654 test1655 \
test1660 \
\
test1700 test1701 test1702 \
\
test1800 test1801 \
\
                                    test1904 test1905 test1906 test1907 \
test1908 test1909 test1910 test1911 test1912 test1913 test1914 test1915 \
test1916 test1917 test1918 \
\
test1933 test1934 test1935 test1936 \
\
test2000 test2001 test2002 test2003 test2004 test2005 test2006 test2007 \
test2008 test2009 test2010 test2011 test2012 test2013 test2014 test2015 \
test2016 test2017 test2018 test2019 test2020 test2021 test2022 test2023 \
test2024 test2025 test2026 test2027 test2028 test2029 test2030 test2031 \
test2032          test2034 test2035 test2036 test2037 test2038 test2039 \
test2040 test2041 test2042 test2043 test2044 test2045 test2046 test2047 \
Changes to jni/curl/tests/data/test1029.
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
<server>
http
</server>
 <name>
HTTP Location: and 'redirect_url' check
 </name>
<command>
http://%HOSTIP:%HTTPPORT/we/want/our/1029 -w '%{redirect_url}\n'
</command>
</client>

# Verify data after the test has been "shot"
<verify>
<protocol>
GET /we/want/our/1029 HTTP/1.1
Host: %HOSTIP:%HTTPPORT
User-Agent: curl/%VERSION
Accept: */*

</protocol>
<stdout>
HTTP/1.1 301 This is a weirdo text message swsclose
Location: data/10290002.txt?coolsite=yes
Content-Length: 62
Connection: close

This server reply is for testing a simple Location: following
http://%HOSTIP:%HTTPPORT/we/want/our/data/10290002.txt?coolsite=yes
</stdout>
</verify>
</testcase>







|



















|



26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
<server>
http
</server>
 <name>
HTTP Location: and 'redirect_url' check
 </name>
<command>
http://%HOSTIP:%HTTPPORT/we/want/our/1029 -w '%{redirect_url} %{url} %{exitcode} %{errormsg}\n'
</command>
</client>

# Verify data after the test has been "shot"
<verify>
<protocol>
GET /we/want/our/1029 HTTP/1.1
Host: %HOSTIP:%HTTPPORT
User-Agent: curl/%VERSION
Accept: */*

</protocol>
<stdout>
HTTP/1.1 301 This is a weirdo text message swsclose
Location: data/10290002.txt?coolsite=yes
Content-Length: 62
Connection: close

This server reply is for testing a simple Location: following
http://%HOSTIP:%HTTPPORT/we/want/our/data/10290002.txt?coolsite=yes http://%HOSTIP:%HTTPPORT/we/want/our/1029 0 
</stdout>
</verify>
</testcase>
Changes to jni/curl/tests/data/test1082.
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
<server>
http
</server>
 <name>
HTTP GET with localhost --interface
 </name>
 <command>
http://%HOSTIP:%HTTPPORT/1082 --interface localhost
</command>
<precheck>
perl -e "print 'Test requires default test client host address' if ( '%CLIENTIP' ne '127.0.0.1' );"
</precheck>
</client>

#







|







28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
<server>
http
</server>
 <name>
HTTP GET with localhost --interface
 </name>
 <command>
http://%HOSTIP:%HTTPPORT/1082 -4 --interface localhost
</command>
<precheck>
perl -e "print 'Test requires default test client host address' if ( '%CLIENTIP' ne '127.0.0.1' );"
</precheck>
</client>

#
Added jni/curl/tests/data/test1180.
































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
<testcase>
<info>
<keywords>
HTTP
HTTP proxy
</keywords>
</info>

# Server-side
<reply>
<data>
HTTP/1.1 200 OK
Server: Blafasel/5.0
Date: Sat, 16 Jan 2021 14:48:30 GMT
Content-Length: 12

Bla bla bla
</data>

</reply>

# Client-side
<client>
<server>
http
</server>
<features>
proxy
</features>
 <name>
HTTP GET request with proxy and -H "Proxy-Connection: keep-alive"
 </name>
 <command>
--proxy http://%HOSTIP:%HTTPPORT -H "Proxy-Connection: Keep-Alive" http://%HOSTIP:%HTTPPORT/1180
</command>
</client>

<verify>
<protocol>
GET http://%HOSTIP:%HTTPPORT/1180 HTTP/1.1
Host: %HOSTIP:%HTTPPORT
User-Agent: curl/%VERSION
Accept: */*
Proxy-Connection: Keep-Alive

</protocol>
</verify>
</testcase>
Added jni/curl/tests/data/test1181.
































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
<testcase>
<info>
<keywords>
HTTP
HTTP proxy
</keywords>
</info>

# Server-side
<reply>
<data>
HTTP/1.1 200 OK
Server: Blafasel/5.0
Date: Sat, 16 Jan 2021 14:48:30 GMT
Content-Length: 12

Bla bla bla
</data>

</reply>

# Client-side
<client>
<server>
http
</server>
<features>
proxy
</features>
 <name>
HTTP GET request with proxy and --proxy-header "Proxy-Connection: Keep-Alive"
 </name>
 <command>
--proxy http://%HOSTIP:%HTTPPORT --proxy-header "Proxy-Connection: Keep-Alive" http://%HOSTIP:%HTTPPORT/1181
</command>
</client>

<verify>
<protocol>
GET http://%HOSTIP:%HTTPPORT/1181 HTTP/1.1
Host: %HOSTIP:%HTTPPORT
User-Agent: curl/%VERSION
Accept: */*
Proxy-Connection: Keep-Alive

</protocol>
</verify>
</testcase>
Added jni/curl/tests/data/test1188.






























































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
<testcase>
<info>
<keywords>
HTTP
HTTP GET
--write-out
</keywords>
</info>

# Server-side
<reply>
<data nocheck="yes">
HTTP/1.1 200 OK
Content-Length: 3
Connection: close

hi
</data>
</reply>

# Client-side
<client>
<server>
http
</server>
 <name>
--write-out with %{onerror} and %{urlnum} to stderr
 </name>
<command>
http://%HOSTIP:%NOLISTENPORT/we/want/our/1188 http://%HOSTIP:%HTTPPORT/we/want/our/1188 -w '%{onerror}%{stderr}%{urlnum} says %{exitcode} %{errormsg}\n' -s
</command>
</client>

# Verify data after the test has been "shot"
<verify>
<protocol>
GET /we/want/our/1188 HTTP/1.1
Host: %HOSTIP:%HTTPPORT
User-Agent: curl/%VERSION
Accept: */*

</protocol>
<stderr mode="text">
0 says 7 Failed to connect to %HOSTIP port %NOLISTENPORT: Connection refused
</stderr>
</verify>
</testcase>
Added jni/curl/tests/data/test1198.












































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
<testcase>
<info>
<keywords>
MQTT
MQTT SUBSCRIBE
</keywords>
</info>

#
# Server-side
<reply>
<data nocheck="yes">
hello
</data>
<datacheck hex="yes">
00 04 31 31 39 30   68 65 6c 6c 6f 5b 4c 46 5d 0a
</datacheck>
</reply>

#
# Client-side
<client>
<features>
mqtt
</features>
<server>
mqtt
</server>
<name>
MQTT PUBLISH empty payload, single space topic
</name>
<command option="binary-trace">
mqtt://%HOSTIP:%MQTTPORT/%20 -d ""
</command>
</client>

#
# Verify data after the test has been "shot"
<verify>
# These are hexadecimal protocol dumps from the client
#
# Strip out the random part of the client id from the CONNECT message
# before comparison
<strippart>
s/^(.* 00044d5154540402003c000c6375726c).*/$1/
</strippart>
<protocol>
client CONNECT 18 00044d5154540402003c000c6375726c
server CONNACK 2 20020000
client PUBLISH 3 000120
client DISCONNECT 0 e000
</protocol>
</verify>
</testcase>
Added jni/curl/tests/data/test1199.














































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
<testcase>
<info>
<keywords>
MQTT
MQTT SUBSCRIBE
</keywords>
</info>

#
# Server-side
<reply>
<data nocheck="yes">
hello
</data>
<datacheck hex="yes">
00 04 31 31 39 30   68 65 6c 6c 6f 5b 4c 46 5d 0a
</datacheck>
</reply>

#
# Client-side
<client>
<features>
mqtt
</features>
<server>
mqtt
</server>
<name>
MQTT PUBLISH empty payload, no topic
</name>
<command option="binary-trace">
mqtt://%HOSTIP:%MQTTPORT -d ""
</command>
</client>

#
# Verify data after the test has been "shot"
<verify>
# These are hexadecimal protocol dumps from the client
#
# Strip out the random part of the client id from the CONNECT message
# before comparison
<strippart>
s/^(.* 00044d5154540402003c000c6375726c).*/$1/
</strippart>
<protocol>
client CONNECT 18 00044d5154540402003c000c6375726c
server CONNACK 2 20020000
</protocol>
<errorcode>
3
</errorcode>
</verify>
</testcase>
Added jni/curl/tests/data/test1272.
















































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
<testcase>
<info>
<keywords>
GOPHER
GOPHERS
INDEX
</keywords>
</info>

#
# Server-side
<reply>
<data>
iMenu results		error.host	1
0Selector 	/bar	bar.foo.invalid	70
.
</data>
</reply>

# Client-side
<client>
<server>
gophers
</server>
 <name>
Gophers index
 </name>
 <command>
-k gophers://%HOSTIP:%GOPHERSPORT/1/1272
</command>
</client>

#
# Verify data after the test has been "shot"
<verify>
<protocol>
/1272
</protocol>
</verify>
</testcase>
Changes to jni/curl/tests/data/test1295.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<testcase>
<info>
<keywords>
HTTP
HTTP POST
</keywords>
</info>

#
# Server-side
<reply>
<data>
HTTP/1.1 200 OK
Date: Thu, 09 Nov 2010 14:49:00 GMT
Server: test-server/fake
Last-Modified: Tue, 13 Jun 2000 12:10:00 GMT
ETag: "21025-dc7-39462498"
Accept-Ranges: bytes
Content-Length: 6











|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<testcase>
<info>
<keywords>
HTTP
HTTP POST
</keywords>
</info>

#
# Server-side
<reply>
<data nocheck="yes">
HTTP/1.1 200 OK
Date: Thu, 09 Nov 2010 14:49:00 GMT
Server: test-server/fake
Last-Modified: Tue, 13 Jun 2000 12:10:00 GMT
ETag: "21025-dc7-39462498"
Accept-Ranges: bytes
Content-Length: 6
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64















65
66
<setenv>
# The Hound of the Baskervilles
#
# make the first send cut off after this amount of data
CURL_SMALLREQSEND=100
</setenv>
<command>
http://%HOSTIP:%HTTPPORT/012345679012345679012345679012345679012345679012345679012345679012345679012345679012345679012345679012345679012345679012345679012345679012345679012345679012345679012345679012345679012345679012345679012345679012345679012345679012345679012345679012345679012345679012345679/1295 -H "012345679012345679012345679012345679012345679012345679012345679012345679012345679012345679012345679012345679012345679012345679012345679012345679012345679012345679012345679012345679012345679012345679012345679012345679012345679012345679012345679012345679012345679012345679: 300" -d "Mr. Sherlock Holmes, who was usually very late in the mornings, save upon those not infrequent occasions when he was up all night, was seated at the breakfast table."
</command>
</client>

#
# Verify data after the test has been "shot"
<verify>
<protocol nonewline="yes">
POST /012345679012345679012345679012345679012345679012345679012345679012345679012345679012345679012345679012345679012345679012345679012345679012345679012345679012345679012345679012345679012345679012345679012345679012345679012345679012345679012345679012345679012345679012345679/1295 HTTP/1.1
Host: %HOSTIP:%HTTPPORT
User-Agent: curl/%VERSION
Accept: */*
012345679012345679012345679012345679012345679012345679012345679012345679012345679012345679012345679012345679012345679012345679012345679012345679012345679012345679012345679012345679012345679012345679012345679012345679012345679012345679012345679012345679012345679012345679: 300
Content-Length: 165
Content-Type: application/x-www-form-urlencoded

Mr. Sherlock Holmes, who was usually very late in the mornings, save upon those not infrequent occasions when he was up all night, was seated at the breakfast table.
</protocol>















</verify>
</testcase>







|

















>
>
>
>
>
>
>
>
>
>
>
>
>
>
>


40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
<setenv>
# The Hound of the Baskervilles
#
# make the first send cut off after this amount of data
CURL_SMALLREQSEND=100
</setenv>
<command>
http://%HOSTIP:%HTTPPORT/012345679012345679012345679012345679012345679012345679012345679012345679012345679012345679012345679012345679012345679012345679012345679012345679012345679012345679012345679012345679012345679012345679012345679012345679012345679012345679012345679012345679012345679012345679/1295 -H "012345679012345679012345679012345679012345679012345679012345679012345679012345679012345679012345679012345679012345679012345679012345679012345679012345679012345679012345679012345679012345679012345679012345679012345679012345679012345679012345679012345679012345679012345679: 300" -d "Mr. Sherlock Holmes, who was usually very late in the mornings, save upon those not infrequent occasions when he was up all night, was seated at the breakfast table." -w '%{size_upload}\n'
</command>
</client>

#
# Verify data after the test has been "shot"
<verify>
<protocol nonewline="yes">
POST /012345679012345679012345679012345679012345679012345679012345679012345679012345679012345679012345679012345679012345679012345679012345679012345679012345679012345679012345679012345679012345679012345679012345679012345679012345679012345679012345679012345679012345679012345679/1295 HTTP/1.1
Host: %HOSTIP:%HTTPPORT
User-Agent: curl/%VERSION
Accept: */*
012345679012345679012345679012345679012345679012345679012345679012345679012345679012345679012345679012345679012345679012345679012345679012345679012345679012345679012345679012345679012345679012345679012345679012345679012345679012345679012345679012345679012345679012345679: 300
Content-Length: 165
Content-Type: application/x-www-form-urlencoded

Mr. Sherlock Holmes, who was usually very late in the mornings, save upon those not infrequent occasions when he was up all night, was seated at the breakfast table.
</protocol>
<stdout>
HTTP/1.1 200 OK
Date: Thu, 09 Nov 2010 14:49:00 GMT
Server: test-server/fake
Last-Modified: Tue, 13 Jun 2000 12:10:00 GMT
ETag: "21025-dc7-39462498"
Accept-Ranges: bytes
Content-Length: 6
Connection: close
Content-Type: text/html
Funny-head: yesyes

-foo-
165
</stdout>
</verify>
</testcase>
Changes to jni/curl/tests/data/test1400.
69
70
71
72
73
74
75

76

77
78
79
80
81
82
83

  hnd = curl_easy_init();
  curl_easy_setopt(hnd, CURLOPT_BUFFERSIZE, 102400L);
  curl_easy_setopt(hnd, CURLOPT_URL, "http://%HOSTIP:%HTTPPORT/we/want/1400");
  curl_easy_setopt(hnd, CURLOPT_USERAGENT, "stripped");
  curl_easy_setopt(hnd, CURLOPT_MAXREDIRS, 50L);
  curl_easy_setopt(hnd, CURLOPT_VERBOSE, 1L);

  curl_easy_setopt(hnd, CURLOPT_FTP_SKIP_PASV_IP, 1L);

  curl_easy_setopt(hnd, CURLOPT_TCP_KEEPALIVE, 1L);

  /* Here is a list of options the curl code used that cannot get generated
     as source easily. You may select to either not use them or implement
     them yourself.

  CURLOPT_WRITEDATA set to a objectpointer







>

>







69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85

  hnd = curl_easy_init();
  curl_easy_setopt(hnd, CURLOPT_BUFFERSIZE, 102400L);
  curl_easy_setopt(hnd, CURLOPT_URL, "http://%HOSTIP:%HTTPPORT/we/want/1400");
  curl_easy_setopt(hnd, CURLOPT_USERAGENT, "stripped");
  curl_easy_setopt(hnd, CURLOPT_MAXREDIRS, 50L);
  curl_easy_setopt(hnd, CURLOPT_VERBOSE, 1L);
%if ftp
  curl_easy_setopt(hnd, CURLOPT_FTP_SKIP_PASV_IP, 1L);
%endif
  curl_easy_setopt(hnd, CURLOPT_TCP_KEEPALIVE, 1L);

  /* Here is a list of options the curl code used that cannot get generated
     as source easily. You may select to either not use them or implement
     them yourself.

  CURLOPT_WRITEDATA set to a objectpointer
Changes to jni/curl/tests/data/test1401.
83
84
85
86
87
88
89

90

91
92
93
94
95
96
97
  curl_easy_setopt(hnd, CURLOPT_USERPWD, "fake:user");
  curl_easy_setopt(hnd, CURLOPT_HTTPAUTH, (long)CURLAUTH_BASIC);
  curl_easy_setopt(hnd, CURLOPT_HTTPHEADER, slist1);
  curl_easy_setopt(hnd, CURLOPT_USERAGENT, "MyUA");
  curl_easy_setopt(hnd, CURLOPT_MAXREDIRS, 50L);
  curl_easy_setopt(hnd, CURLOPT_COOKIE, "chocolate=chip");
  curl_easy_setopt(hnd, CURLOPT_VERBOSE, 1L);

  curl_easy_setopt(hnd, CURLOPT_FTP_SKIP_PASV_IP, 1L);

  curl_easy_setopt(hnd, CURLOPT_TCP_KEEPALIVE, 1L);
  curl_easy_setopt(hnd, CURLOPT_PROTOCOLS, (long)CURLPROTO_FILE |
                                           (long)CURLPROTO_FTP |
                                           (long)CURLPROTO_HTTP);

  /* Here is a list of options the curl code used that cannot get generated
     as source easily. You may select to either not use them or implement







>

>







83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
  curl_easy_setopt(hnd, CURLOPT_USERPWD, "fake:user");
  curl_easy_setopt(hnd, CURLOPT_HTTPAUTH, (long)CURLAUTH_BASIC);
  curl_easy_setopt(hnd, CURLOPT_HTTPHEADER, slist1);
  curl_easy_setopt(hnd, CURLOPT_USERAGENT, "MyUA");
  curl_easy_setopt(hnd, CURLOPT_MAXREDIRS, 50L);
  curl_easy_setopt(hnd, CURLOPT_COOKIE, "chocolate=chip");
  curl_easy_setopt(hnd, CURLOPT_VERBOSE, 1L);
%if ftp
  curl_easy_setopt(hnd, CURLOPT_FTP_SKIP_PASV_IP, 1L);
%endif
  curl_easy_setopt(hnd, CURLOPT_TCP_KEEPALIVE, 1L);
  curl_easy_setopt(hnd, CURLOPT_PROTOCOLS, (long)CURLPROTO_FILE |
                                           (long)CURLPROTO_FTP |
                                           (long)CURLPROTO_HTTP);

  /* Here is a list of options the curl code used that cannot get generated
     as source easily. You may select to either not use them or implement
Changes to jni/curl/tests/data/test1402.
74
75
76
77
78
79
80

81

82
83
84
85
86
87
88
  curl_easy_setopt(hnd, CURLOPT_BUFFERSIZE, 102400L);
  curl_easy_setopt(hnd, CURLOPT_URL, "http://%HOSTIP:%HTTPPORT/we/want/1402");
  curl_easy_setopt(hnd, CURLOPT_POSTFIELDS, "foo=bar&baz=quux");
  curl_easy_setopt(hnd, CURLOPT_POSTFIELDSIZE_LARGE, (curl_off_t)16);
  curl_easy_setopt(hnd, CURLOPT_USERAGENT, "stripped");
  curl_easy_setopt(hnd, CURLOPT_MAXREDIRS, 50L);
  curl_easy_setopt(hnd, CURLOPT_VERBOSE, 1L);

  curl_easy_setopt(hnd, CURLOPT_FTP_SKIP_PASV_IP, 1L);

  curl_easy_setopt(hnd, CURLOPT_TCP_KEEPALIVE, 1L);

  /* Here is a list of options the curl code used that cannot get generated
     as source easily. You may select to either not use them or implement
     them yourself.

  CURLOPT_WRITEDATA set to a objectpointer







>

>







74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
  curl_easy_setopt(hnd, CURLOPT_BUFFERSIZE, 102400L);
  curl_easy_setopt(hnd, CURLOPT_URL, "http://%HOSTIP:%HTTPPORT/we/want/1402");
  curl_easy_setopt(hnd, CURLOPT_POSTFIELDS, "foo=bar&baz=quux");
  curl_easy_setopt(hnd, CURLOPT_POSTFIELDSIZE_LARGE, (curl_off_t)16);
  curl_easy_setopt(hnd, CURLOPT_USERAGENT, "stripped");
  curl_easy_setopt(hnd, CURLOPT_MAXREDIRS, 50L);
  curl_easy_setopt(hnd, CURLOPT_VERBOSE, 1L);
%if ftp
  curl_easy_setopt(hnd, CURLOPT_FTP_SKIP_PASV_IP, 1L);
%endif
  curl_easy_setopt(hnd, CURLOPT_TCP_KEEPALIVE, 1L);

  /* Here is a list of options the curl code used that cannot get generated
     as source easily. You may select to either not use them or implement
     them yourself.

  CURLOPT_WRITEDATA set to a objectpointer
Changes to jni/curl/tests/data/test1403.
69
70
71
72
73
74
75

76

77
78
79
80
81
82
83

  hnd = curl_easy_init();
  curl_easy_setopt(hnd, CURLOPT_BUFFERSIZE, 102400L);
  curl_easy_setopt(hnd, CURLOPT_URL, "http://%HOSTIP:%HTTPPORT/we/want/1403?foo=bar&baz=quux");
  curl_easy_setopt(hnd, CURLOPT_USERAGENT, "stripped");
  curl_easy_setopt(hnd, CURLOPT_MAXREDIRS, 50L);
  curl_easy_setopt(hnd, CURLOPT_VERBOSE, 1L);

  curl_easy_setopt(hnd, CURLOPT_FTP_SKIP_PASV_IP, 1L);

  curl_easy_setopt(hnd, CURLOPT_TCP_KEEPALIVE, 1L);

  /* Here is a list of options the curl code used that cannot get generated
     as source easily. You may select to either not use them or implement
     them yourself.

  CURLOPT_WRITEDATA set to a objectpointer







>

>







69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85

  hnd = curl_easy_init();
  curl_easy_setopt(hnd, CURLOPT_BUFFERSIZE, 102400L);
  curl_easy_setopt(hnd, CURLOPT_URL, "http://%HOSTIP:%HTTPPORT/we/want/1403?foo=bar&baz=quux");
  curl_easy_setopt(hnd, CURLOPT_USERAGENT, "stripped");
  curl_easy_setopt(hnd, CURLOPT_MAXREDIRS, 50L);
  curl_easy_setopt(hnd, CURLOPT_VERBOSE, 1L);
%if ftp
  curl_easy_setopt(hnd, CURLOPT_FTP_SKIP_PASV_IP, 1L);
%endif
  curl_easy_setopt(hnd, CURLOPT_TCP_KEEPALIVE, 1L);

  /* Here is a list of options the curl code used that cannot get generated
     as source easily. You may select to either not use them or implement
     them yourself.

  CURLOPT_WRITEDATA set to a objectpointer
Changes to jni/curl/tests/data/test1404.
143
144
145
146
147
148
149

150

151
152
153
154
155
156
157
  curl_mime_subparts(part1, mime2);
  mime2 = NULL;
  curl_mime_name(part1, "file");
  curl_easy_setopt(hnd, CURLOPT_MIMEPOST, mime1);
  curl_easy_setopt(hnd, CURLOPT_USERAGENT, "stripped");
  curl_easy_setopt(hnd, CURLOPT_MAXREDIRS, 50L);
  curl_easy_setopt(hnd, CURLOPT_VERBOSE, 1L);

  curl_easy_setopt(hnd, CURLOPT_FTP_SKIP_PASV_IP, 1L);

  curl_easy_setopt(hnd, CURLOPT_TCP_KEEPALIVE, 1L);

  /* Here is a list of options the curl code used that cannot get generated
     as source easily. You may select to either not use them or implement
     them yourself.

  CURLOPT_WRITEDATA set to a objectpointer







>

>







143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
  curl_mime_subparts(part1, mime2);
  mime2 = NULL;
  curl_mime_name(part1, "file");
  curl_easy_setopt(hnd, CURLOPT_MIMEPOST, mime1);
  curl_easy_setopt(hnd, CURLOPT_USERAGENT, "stripped");
  curl_easy_setopt(hnd, CURLOPT_MAXREDIRS, 50L);
  curl_easy_setopt(hnd, CURLOPT_VERBOSE, 1L);
%if ftp
  curl_easy_setopt(hnd, CURLOPT_FTP_SKIP_PASV_IP, 1L);
%endif
  curl_easy_setopt(hnd, CURLOPT_TCP_KEEPALIVE, 1L);

  /* Here is a list of options the curl code used that cannot get generated
     as source easily. You may select to either not use them or implement
     them yourself.

  CURLOPT_WRITEDATA set to a objectpointer
Changes to jni/curl/tests/data/test1463.
33
34
35
36
37
38
39

40
41
42
43
44
<verify>
<errorcode>
0
</errorcode>
<stdout mode="text">
Usage: curl [options...] <url>
file: FILE protocol options

 -I, --head          Show document info only
 -r, --range <range> Retrieve only the bytes within RANGE
</stdout>
</verify>
</testcase>







>





33
34
35
36
37
38
39
40
41
42
43
44
45
<verify>
<errorcode>
0
</errorcode>
<stdout mode="text">
Usage: curl [options...] <url>
file: FILE protocol options
     --create-file-mode File mode for created files
 -I, --head          Show document info only
 -r, --range <range> Retrieve only the bytes within RANGE
</stdout>
</verify>
</testcase>
Changes to jni/curl/tests/data/test1464.
33
34
35
36
37
38
39

40
41
42
43
44
<verify>
<errorcode>
0
</errorcode>
<stdout mode="text">
Usage: curl [options...] <url>
file: FILE protocol options

 -I, --head          Show document info only
 -r, --range <range> Retrieve only the bytes within RANGE
</stdout>
</verify>
</testcase>







>





33
34
35
36
37
38
39
40
41
42
43
44
45
<verify>
<errorcode>
0
</errorcode>
<stdout mode="text">
Usage: curl [options...] <url>
file: FILE protocol options
     --create-file-mode File mode for created files
 -I, --head          Show document info only
 -r, --range <range> Retrieve only the bytes within RANGE
</stdout>
</verify>
</testcase>
Changes to jni/curl/tests/data/test1465.

cannot compute difference between binary files

Changes to jni/curl/tests/data/test15.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<testcase>
<info>
<keywords>
HTTP
HTTP GET
--write-out
</keywords>
</info>
# Server-side
<reply>
<data nocheck="yes">
HTTP/1.4 200 OK
Fake: yes
Fake: yes
Fake: yes
Content-Length: 26

Repeated nonsense-headers
</data>











|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<testcase>
<info>
<keywords>
HTTP
HTTP GET
--write-out
</keywords>
</info>
# Server-side
<reply>
<data nocheck="yes">
HTTP/1.1 200 OK
Fake: yes
Fake: yes
Fake: yes
Content-Length: 26

Repeated nonsense-headers
</data>
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
http://%HOSTIP:%HTTPPORT/want/15 --write-out "%{url_effective} %{http_code} %{size_download}\n"
</command>
</client>

# Verify data after the test has been "shot"
<verify>
<stdout>
HTTP/1.4 200 OK
Fake: yes
Fake: yes
Fake: yes
Content-Length: 26

Repeated nonsense-headers
http://%HOSTIP:%HTTPPORT/want/15 200 26







|







31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
http://%HOSTIP:%HTTPPORT/want/15 --write-out "%{url_effective} %{http_code} %{size_download}\n"
</command>
</client>

# Verify data after the test has been "shot"
<verify>
<stdout>
HTTP/1.1 200 OK
Fake: yes
Fake: yes
Fake: yes
Content-Length: 26

Repeated nonsense-headers
http://%HOSTIP:%HTTPPORT/want/15 200 26
Changes to jni/curl/tests/data/test1564.
8
9
10
11
12
13
14



15
16
17
18
19
20
21

# Server-side
<reply>
</reply>

# Client-side
<client>



<server>
none
</server>
<tool>
lib1564
</tool>
<name>







>
>
>







8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

# Server-side
<reply>
</reply>

# Client-side
<client>
<features>
wakeup
</features>
<server>
none
</server>
<tool>
lib1564
</tool>
<name>
Changes to jni/curl/tests/data/test1565.
17
18
19
20
21
22
23



24
25
26
27
28
29
30

OK
</data>
</reply>

# Client-side
<client>



<server>
http
</server>
<tool>
lib1565
</tool>
<name>







>
>
>







17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33

OK
</data>
</reply>

# Client-side
<client>
<features>
wakeup
</features>
<server>
http
</server>
<tool>
lib1565
</tool>
<name>
Added jni/curl/tests/data/test1568.














































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
<testcase>
# based on test 64

<info>
<keywords>
HTTP
HTTP GET
HTTP Digest auth
</keywords>
</info>

<reply>
<data>
HTTP/1.1 401 Authorization Required swsclose
Server: Apache/1.3.27 (Darwin) PHP/4.1.2
WWW-Authenticate: Digest realm="testrealm", nonce="1053604145"
Content-Type: text/html; charset=iso-8859-1
Content-Length: 26

This is not the real page
</data>

# This is supposed to be returned when the server gets a
# Authorization: Digest line passed-in from the client
<data1000>
HTTP/1.1 200 OK swsclose
Server: Apache/1.3.27 (Darwin) PHP/4.1.2
Content-Type: text/html; charset=iso-8859-1
Content-Length: 23

This IS the real page!
</data1000>

<datacheck>
HTTP/1.1 401 Authorization Required swsclose
Server: Apache/1.3.27 (Darwin) PHP/4.1.2
WWW-Authenticate: Digest realm="testrealm", nonce="1053604145"
Content-Type: text/html; charset=iso-8859-1
Content-Length: 26

HTTP/1.1 200 OK swsclose
Server: Apache/1.3.27 (Darwin) PHP/4.1.2
Content-Type: text/html; charset=iso-8859-1
Content-Length: 23

This IS the real page!
</datacheck>

</reply>

# Client-side
<client>
<server>
http
</server>
<features>
!SSPI
crypto
</features>
<name>
HTTP with Digest authorization on custom CURLOPT_PORT
</name>
<tool>
lib1568
</tool>
<command>
http://%HOSTIP/1568 %HTTPPORT
</command>
</client>

# Verify data after the test has been "shot"
<verify>
<protocol>
GET /1568 HTTP/1.1
Host: %HOSTIP:%HTTPPORT
User-Agent: lib1568
Accept: */*

GET /1568 HTTP/1.1
Host: %HOSTIP:%HTTPPORT
Authorization: Digest username="testuser", realm="testrealm", nonce="1053604145", uri="/1568", response="9cbbd857a37e45f2bcad5c7d088191df"
User-Agent: lib1568
Accept: */*

</protocol>
</verify>
</testcase>
Added jni/curl/tests/data/test1613.










































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
<testcase>
<info>
<keywords>
HTTP
HTTP proxy
--request-target
</keywords>
</info>

#
# Server-side
<reply>
<data>
HTTP/1.1 200 OK
Date: Sat, 29 Feb 2020 16:10:44 GMT
Server: Blafasel/1.1
Last-Modified: Sat, 29 Feb 2020 16:10:44 GMT
Content-Length: 0
Connection: close
Content-Type: text/html

</data>
</reply>

#
# Client-side
<client>
<server>
http
</server>
<name>
Send "OPTIONS *" with --request-target to a proxy
</name>
<features>
proxy
</features>
<command>
--request-target '*' -X OPTIONS --proxy http://%HOSTIP:%HTTPPORT/ -H "Testno: 1613" http://www.example.org/
</command>
</client>

<verify>
<protocol>
OPTIONS * HTTP/1.1
Host: www.example.org
User-Agent: curl/%VERSION
Accept: */*
Proxy-Connection: Keep-Alive
Testno: 1613

</protocol>
</verify>
</testcase>
Changes to jni/curl/tests/data/test1633.
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70

#
# Client-side
<client>
<server>
http
</server>
 <name>
HTTP GET
 </name>
 <command>
http://%HOSTIP:%HTTPPORT/1633 -d moo --retry 1 -L
</command>
</client>

#
# Verify data after the test has been "shot"
<verify>







|
|
|
|







53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70

#
# Client-side
<client>
<server>
http
</server>
<name>
--retry with a 429 response and Retry-After:
</name>
<command>
http://%HOSTIP:%HTTPPORT/1633 -d moo --retry 1 -L
</command>
</client>

#
# Verify data after the test has been "shot"
<verify>
Added jni/curl/tests/data/test1634.












































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
<testcase>
<info>
<keywords>
HTTP
HTTP GET
</keywords>
</info>

#
# Server-side
<reply>
<data>
HTTP/1.1 429 too many requests swsbounce
Retry-After: 1
Content-Length: 4

moo
</data>
<data1>
HTTP/1.1 200 OK
Content-Length: 4
Connection: close

hey
</data1>

<datacheck>
HTTP/1.1 429 too many requests swsbounce
Retry-After: 1
Content-Length: 4

HTTP/1.1 200 OK
Content-Length: 4
Connection: close

hey
</datacheck>
</reply>

#
# Client-side
<client>
<server>
http
</server>
<name>
--retry with a 429 response and Retry-After: and --fail
</name>
<command>
http://%HOSTIP:%HTTPPORT/1634 --retry 1  --fail
</command>
</client>

#
# Verify data after the test has been "shot"
<verify>
<protocol>
GET /1634 HTTP/1.1
Host: %HOSTIP:%HTTPPORT
User-Agent: curl/%VERSION
Accept: */*

GET /1634 HTTP/1.1
Host: %HOSTIP:%HTTPPORT
User-Agent: curl/%VERSION
Accept: */*

</protocol>
</verify>
</testcase>
Changes to jni/curl/tests/data/test17.
Changes to jni/curl/tests/data/test179.
Added jni/curl/tests/data/test1916.


















































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
<testcase>
<info>
<keywords>
MQTT
MQTT PUBLISH
</keywords>
</info>

#
# Server-side
<reply>
<data nocheck="yes">
hello
</data>
<datacheck hex="yes">
00 04 31 31 39 30   68 65 6c 6c 6f 5b 4c 46 5d 0a
</datacheck>
</reply>

#
# Client-side
<client>
<features>
mqtt
</features>
<server>
mqtt
</server>
<name>
MQTT PUBLISH with no POSTFIELDSIZE set
</name>
<tool>
lib1916
</tool>
<command option="binary-trace">
"mqtt://%HOSTIP:%MQTTPORT/ "
</command>
</client>

#
# Verify data after the test has been "shot"
<verify>
# These are hexadecimal protocol dumps from the client
#
# Strip out the random part of the client id from the CONNECT message
# before comparison
<strippart>
s/^(.* 00044d5154540402003c000c6375726c).*/$1/
</strippart>
<protocol>
client CONNECT 18 00044d5154540402003c000c6375726c
server CONNACK 2 20020000
client PUBLISH 3 000120
client DISCONNECT 0 e000
</protocol>
</verify>
</testcase>
Added jni/curl/tests/data/test1917.


























































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
<testcase>
<info>
<keywords>
MQTT
MQTT PUBLISH
</keywords>
</info>

#
# Server-side
<reply>
<data nocheck="yes">
hello
</data>
<datacheck hex="yes">
00 04 31 31 39 30   68 65 6c 6c 6f 5b 4c 46 5d 0a
</datacheck>
</reply>

#
# Client-side
<client>

# require HTTP too as otherwise CURLOPT_POST doesn't exist
<features>
mqtt
http
</features>
<server>
mqtt
</server>
<name>
MQTT PUBLISH with CURLOPT_POST set (no payload)
</name>
<tool>
lib1917
</tool>
<command option="binary-trace">
"mqtt://%HOSTIP:%MQTTPORT/ "
</command>
</client>

#
# Verify data after the test has been "shot"
<verify>
# These are hexadecimal protocol dumps from the client
#
# Strip out the random part of the client id from the CONNECT message
# before comparison
<strippart>
s/^(.* 00044d5154540402003c000c6375726c).*/$1/
</strippart>
<protocol>
client CONNECT 18 00044d5154540402003c000c6375726c
server CONNACK 2 20020000
</protocol>
<errorcode>
43
</errorcode>
</verify>
</testcase>
Added jni/curl/tests/data/test1918.


































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
<testcase>
<info>
<keywords>
curl_easy_option
curl_easy_option_by_name
curl_easy_option_by_id
</keywords>
</info>

# Server-side
<reply>
</reply>

# Client-side
<client>
<server>
none
</server>
<name>
curl_easy_option_by_name() and curl_easy_option_by_id()
</name>
<tool>
lib1918
</tool>

</client>

# Verify data after the test has been "shot"
<verify>
<stdout>
</stdout>
</verify>
</testcase>
Added jni/curl/tests/data/test1933.










































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
<testcase>
<info>
<keywords>
HTTP
CURLOPT_AWS_SIGV4
</keywords>
</info>

# Server-side
<reply>
<data nocheck="yes">
HTTP/1.1 302 OK
Date: Thu, 09 Nov 2010 14:49:00 GMT
Server: test-server/fake
Content-Type: text/html
Content-Length: 0
Location: /19330002

</data>
<data2>
HTTP/1.1 200 OK
Date: Thu, 09 Nov 2010 14:49:00 GMT
Server: test-server/fake
Content-Type: text/html
Content-Length: 0

</data>
</reply>

# Client-side
<client>
<server>
http
</server>
# this relies on the debug feature which allow to set the time
<features>
SSL
debug
crypto
</features>

<name>
HTTP AWS_SIGV4 with one provider and auth cred via URL
</name>
<tool>
lib1933
</tool>

<command>
http://xxx:yyy@%HOSTIP:%HTTPPORT/1933/testapi/test
</command>
</client>

# Verify data after the test has been "shot"
<verify>
<strip>
^User-Agent:.*
^Content-Type:.*
^Accept:.*
</strip>
<protocol>
GET /1933/testapi/test HTTP/1.1
Host: %HOSTIP:%HTTPPORT
Authorization: XXX4-HMAC-SHA256 Credential=xxx/19700101/0/127/xxx4_request, SignedHeaders=content-type;host;x-xxx-date, Signature=d2c2dff48c59ec49dc31ef94f18c5dc1ac3eae2a70d51633a4342dadc0683664
X-Xxx-Date: 19700101T000000Z

</protocol>
</verify>
</testcase>
Added jni/curl/tests/data/test1934.










































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
<testcase>
<info>
<keywords>
HTTP
CURLOPT_AWS_SIGV4
</keywords>
</info>

# Server-side
<reply>
<data nocheck="yes">
HTTP/1.1 302 OK
Date: Thu, 09 Nov 2010 14:49:00 GMT
Server: test-server/fake
Content-Type: text/html
Content-Length: 0
Location: /19340002

</data>
<data2>
HTTP/1.1 200 OK
Date: Thu, 09 Nov 2010 14:49:00 GMT
Server: test-server/fake
Content-Type: text/html
Content-Length: 0

</data>
</reply>

# Client-side
<client>
<server>
http
</server>
# this relies on the debug feature which allow to set the time
<features>
SSL
debug
crypto
</features>

<name>
HTTP AWS_SIGV4 with two providers
</name>
<tool>
lib1934
</tool>

<command>
http://%HOSTIP:%HTTPPORT/1934/testapi/test
</command>
</client>

# Verify data after the test has been "shot"
<verify>
<strip>
^User-Agent:.*
^Content-Type:.*
^Accept:.*
</strip>
<protocol>
GET /1934/testapi/test HTTP/1.1
Host: %HOSTIP:%HTTPPORT
Authorization: XXX4-HMAC-SHA256 Credential=xxx/19700101/0/127/xxx4_request, SignedHeaders=content-type;host;x-yyy-date, Signature=938937ca7da6bb3dbf15e30928265ec6f061532d035d2afda92fa7cb10feb196
X-Yyy-Date: 19700101T000000Z

</protocol>
</verify>
</testcase>
Added jni/curl/tests/data/test1935.










































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
<testcase>
<info>
<keywords>
HTTP
CURLOPT_AWS_SIGV4
</keywords>
</info>

# Server-side
<reply>
<data nocheck="yes">
HTTP/1.1 302 OK
Date: Thu, 09 Nov 2010 14:49:00 GMT
Server: test-server/fake
Content-Type: text/html
Content-Length: 0
Location: /19350002

</data>
<data2>
HTTP/1.1 200 OK
Date: Thu, 09 Nov 2010 14:49:00 GMT
Server: test-server/fake
Content-Type: text/html
Content-Length: 0

</data>
</reply>

# Client-side
<client>
<server>
http
</server>
# this relies on the debug feature which allow to set the time
<features>
SSL
debug
crypto
</features>

<name>
HTTP AWS_SIGV4 with two providers and region
</name>
<tool>
lib1935
</tool>

<command>
http://%HOSTIP:%HTTPPORT/1935/testapi/test
</command>
</client>

# Verify data after the test has been "shot"
<verify>
<strip>
^User-Agent:.*
^Content-Type:.*
^Accept:.*
</strip>
<protocol>
GET /1935/testapi/test HTTP/1.1
Host: %HOSTIP:%HTTPPORT
Authorization: XXX4-HMAC-SHA256 Credential=xxx/19700101/rrr/127/xxx4_request, SignedHeaders=content-type;host;x-yyy-date, Signature=240750deb9263d4c8ece71c016f3919b56e518249390ef075740f94ef8df846f
X-Yyy-Date: 19700101T000000Z

</protocol>
</verify>
</testcase>
Added jni/curl/tests/data/test1936.










































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
<testcase>
<info>
<keywords>
HTTP
CURLOPT_AWS_SIGV4
</keywords>
</info>

# Server-side
<reply>
<data nocheck="yes">
HTTP/1.1 302 OK
Date: Thu, 09 Nov 2010 14:49:00 GMT
Server: test-server/fake
Content-Type: text/html
Content-Length: 0
Location: /19360002

</data>
<data2>
HTTP/1.1 200 OK
Date: Thu, 09 Nov 2010 14:49:00 GMT
Server: test-server/fake
Content-Type: text/html
Content-Length: 0

</data>
</reply>

# Client-side
<client>
<server>
http
</server>
# this relies on the debug feature which allow to set the time
<features>
SSL
debug
crypto
</features>

<name>
HTTP AWS_SIGV4 with two providers, region and service
</name>
<tool>
lib1936
</tool>

<command>
http://%HOSTIP:%HTTPPORT/1936/testapi/test
</command>
</client>

# Verify data after the test has been "shot"
<verify>
<strip>
^User-Agent:.*
^Content-Type:.*
^Accept:.*
</strip>
<protocol>
GET /1936/testapi/test HTTP/1.1
Host: %HOSTIP:%HTTPPORT
Authorization: XXX4-HMAC-SHA256 Credential=xxx/19700101/rrr/sss/xxx4_request, SignedHeaders=content-type;host;x-yyy-date, Signature=f32cf87977cea5d3274b524b53e5d28f4aac54c372f710ae0cc3a9ececaf169f
X-Yyy-Date: 19700101T000000Z

</protocol>
</verify>
</testcase>
Changes to jni/curl/tests/data/test194.
32
33
34
35
36
37
38

39
40
41
42
43
44
45
Last-Modified: Fri, 24 Oct 2003 18:01:23 GMT
ETag: "ab57a-507-3f9968f3"
Accept-Ranges: bytes
Content-Length: 4
Content-Range: bytes */87
Content-Type: image/gif
Connection: close

</datacheck>

</reply>

# Client-side
<client>
<server>







>







32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
Last-Modified: Fri, 24 Oct 2003 18:01:23 GMT
ETag: "ab57a-507-3f9968f3"
Accept-Ranges: bytes
Content-Length: 4
Content-Range: bytes */87
Content-Type: image/gif
Connection: close

</datacheck>

</reply>

# Client-side
<client>
<server>
Changes to jni/curl/tests/data/test201.
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
<server>
file
</server>
 <name>
missing file:// file
 </name>
 <command>
file://localhost/%PWD/log/non-existant-file.txt
</command>
</client>

# Verify data after the test has been "shot"
<verify>
<errorcode>
37







|







17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
<server>
file
</server>
 <name>
missing file:// file
 </name>
 <command>
file://localhost/%PWD/log/non-existent-file.txt
</command>
</client>

# Verify data after the test has been "shot"
<verify>
<errorcode>
37
Changes to jni/curl/tests/data/test24.
37
38
39
40
41
42
43
44
45
46
47
Accept: */*

</protocol>
<errorcode>
22
</errorcode>
<file2 name="log/stderr24" mode="text">
curl: (22) The requested URL returned error: 404 BAD BOY
</file2>
</verify>
</testcase>







|



37
38
39
40
41
42
43
44
45
46
47
Accept: */*

</protocol>
<errorcode>
22
</errorcode>
<file2 name="log/stderr24" mode="text">
curl: (22) The requested URL returned error: 404
</file2>
</verify>
</testcase>
Changes to jni/curl/tests/data/test28.
26
27
28
29
30
31
32



33

34
35
36
37
38
39
40
If this is received, the location following worked

</data2>
<datacheck>
HTTP/1.1 301 This is a weirdo text message swsclose
Date: Thu, 09 Nov 2010 14:49:00 GMT
Server: test-server/fake



Location:  /online/1,1795,Welcome,00.html/280002.txt?logout=TRUE

Connection: close

HTTP/1.1 200 Followed here fine swsclose
Date: Thu, 09 Nov 2010 14:49:00 GMT
Server: test-server/fake
Content-Length: 52








>
>
>

>







26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
If this is received, the location following worked

</data2>
<datacheck>
HTTP/1.1 301 This is a weirdo text message swsclose
Date: Thu, 09 Nov 2010 14:49:00 GMT
Server: test-server/fake
%if hyper
Location: /online/1,1795,Welcome,00.html/280002.txt?logout=TRUE
%else
Location:  /online/1,1795,Welcome,00.html/280002.txt?logout=TRUE
%endif
Connection: close

HTTP/1.1 200 Followed here fine swsclose
Date: Thu, 09 Nov 2010 14:49:00 GMT
Server: test-server/fake
Content-Length: 52

Changes to jni/curl/tests/data/test281.
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
<data>
HTTP/1.1 100 Continue

HTTP/1.1 401 Bad Auth swsclose
Date: Thu, 09 Nov 2010 14:49:00 GMT
WWW-Authenticate: Basic Realm=authenticate
Server: test-server/fake
</data>
<datacheck>
HTTP/1.1 100 Continue

</datacheck>

</reply>

# Client-side
<client>
<server>
http







<
<
<

|







10
11
12
13
14
15
16



17
18
19
20
21
22
23
24
25
<data>
HTTP/1.1 100 Continue

HTTP/1.1 401 Bad Auth swsclose
Date: Thu, 09 Nov 2010 14:49:00 GMT
WWW-Authenticate: Basic Realm=authenticate
Server: test-server/fake




</data>

</reply>

# Client-side
<client>
<server>
http
Changes to jni/curl/tests/data/test31.
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
<testcase>
<info>
<keywords>
HTTP
HTTP GET
cookies
cookiejar
</keywords>
</info>
# Server-side






<reply>
<data>
HTTP/1.1 200 OK
Date: Thu, 09 Nov 2010 14:49:00 GMT
Server: test-server/fake
Content-Length: 4
Content-Type: text/html
Funny-head: yesyes

Set-Cookie: foobar=name; domain=anything.com; path=/ ; secure
Set-Cookie:ismatch=this  ; domain=127.0.0.1; path=/silly/
Set-Cookie: overwrite=this  ; domain=127.0.0.1; path=/overwrite/
Set-Cookie: overwrite=this2  ; domain=127.0.0.1; path=/overwrite
Set-Cookie: sec1value=secure1  ; domain=127.0.0.1; path=/secure1/ ; secure
Set-Cookie: sec2value=secure2  ; domain=127.0.0.1; path=/secure2/ ; secure=
Set-Cookie: sec3value=secure3  ; domain=127.0.0.1; path=/secure3/ ; secure=










>
>
>
>
>
>








>







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
<testcase>
<info>
<keywords>
HTTP
HTTP GET
cookies
cookiejar
</keywords>
</info>
# Server-side
#
# The cookies set come in two versions. This is because when curl is built
# with Hyper, the API provides the headers already "sanitized" so we cannot
# compapare with the exact server contents unlesss it too sends the data
# "clean".

<reply>
<data>
HTTP/1.1 200 OK
Date: Thu, 09 Nov 2010 14:49:00 GMT
Server: test-server/fake
Content-Length: 4
Content-Type: text/html
Funny-head: yesyes
%if !hyper
Set-Cookie: foobar=name; domain=anything.com; path=/ ; secure
Set-Cookie:ismatch=this  ; domain=127.0.0.1; path=/silly/
Set-Cookie: overwrite=this  ; domain=127.0.0.1; path=/overwrite/
Set-Cookie: overwrite=this2  ; domain=127.0.0.1; path=/overwrite
Set-Cookie: sec1value=secure1  ; domain=127.0.0.1; path=/secure1/ ; secure
Set-Cookie: sec2value=secure2  ; domain=127.0.0.1; path=/secure2/ ; secure=
Set-Cookie: sec3value=secure3  ; domain=127.0.0.1; path=/secure3/ ; secure=
53
54
55
56
57
58
59











































60
61
62
63
64
65
66
Set-Cookie: magic=yessir; path=/silly/; HttpOnly
Set-Cookie: blexp=yesyes; domain=127.0.0.1; domain=127.0.0.1; expiry=totally bad;
Set-Cookie: partialip=nono; domain=.0.0.1;
Set-Cookie: withspaces=  yes  within and around    ;
Set-Cookie: withspaces2 =before equals;
Set-Cookie: prespace=  yes before;
Set-Cookie: securewithspace=after    ; secure =












































boo
</data>
</reply>

# Client-side
<client>







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
Set-Cookie: magic=yessir; path=/silly/; HttpOnly
Set-Cookie: blexp=yesyes; domain=127.0.0.1; domain=127.0.0.1; expiry=totally bad;
Set-Cookie: partialip=nono; domain=.0.0.1;
Set-Cookie: withspaces=  yes  within and around    ;
Set-Cookie: withspaces2 =before equals;
Set-Cookie: prespace=  yes before;
Set-Cookie: securewithspace=after    ; secure =
%else
Set-Cookie: foobar=name; domain=anything.com; path=/ ; secure
Set-Cookie: ismatch=this  ; domain=127.0.0.1; path=/silly/
Set-Cookie: overwrite=this  ; domain=127.0.0.1; path=/overwrite/
Set-Cookie: overwrite=this2  ; domain=127.0.0.1; path=/overwrite
Set-Cookie: sec1value=secure1  ; domain=127.0.0.1; path=/secure1/ ; secure
Set-Cookie: sec2value=secure2  ; domain=127.0.0.1; path=/secure2/ ; secure=
Set-Cookie: sec3value=secure3  ; domain=127.0.0.1; path=/secure3/ ; secure=
Set-Cookie: sec4value=secure4  ; secure=; domain=127.0.0.1; path=/secure4/ ;
Set-Cookie: sec5value=secure5  ; secure; domain=127.0.0.1; path=/secure5/ ;
Set-Cookie: sec6value=secure6  ; secure ; domain=127.0.0.1; path=/secure6/ ;
Set-Cookie: sec7value=secure7  ; secure   ; domain=127.0.0.1; path=/secure7/ ;
Set-Cookie: sec8value=secure8  ; secure= ; domain=127.0.0.1; path=/secure8/ ;
Set-Cookie: secure=very1  ; secure=; domain=127.0.0.1; path=/secure9/;
Set-Cookie: httpo1=value1  ; domain=127.0.0.1; path=/p1/; httponly
Set-Cookie: httpo2=value2  ; domain=127.0.0.1; path=/p2/; httponly=
Set-Cookie: httpo3=value3  ; httponly; domain=127.0.0.1; path=/p3/;
Set-Cookie: httpo4=value4  ; httponly=; domain=127.0.0.1; path=/p4/;
Set-Cookie: httponly=myvalue1  ; domain=127.0.0.1; path=/p4/; httponly
Set-Cookie: httpandsec=myvalue2  ; domain=127.0.0.1; path=/p4/; httponly; secure
Set-Cookie: httpandsec2=myvalue3; domain=127.0.0.1; path=/p4/; httponly=; secure
Set-Cookie: httpandsec3=myvalue4  ; domain=127.0.0.1; path=/p4/; httponly; secure=
Set-Cookie: httpandsec4=myvalue5  ; domain=127.0.0.1; path=/p4/; httponly=; secure=
Set-Cookie: httpandsec5=myvalue6  ; domain=127.0.0.1; path=/p4/; secure; httponly=
Set-Cookie: httpandsec6=myvalue7  ; domain=127.0.0.1; path=/p4/; secure=; httponly=
Set-Cookie: httpandsec7=myvalue8  ; domain=127.0.0.1; path=/p4/; secure; httponly
Set-Cookie: httpandsec8=myvalue9; domain=127.0.0.1; path=/p4/; secure=; httponly
Set-Cookie: partmatch=present; domain=127.0.0.1 ; path=/;
Set-Cookie: eat=this; domain=moo.foo.moo;
Set-Cookie: eat=this-too; domain=.foo.moo;
Set-Cookie: nodomainnovalue
Set-Cookie: nodomain=value; expires=Fri Feb 13 11:56:27 GMT 2037
Set-Cookie: novalue; domain=reallysilly
Set-Cookie: test=yes; domain=foo.com; expires=Sat Feb 2 11:56:27 GMT 2030
Set-Cookie: test2=yes; domain=se; expires=Sat Feb 2 11:56:27 GMT 2030
Set-Cookie: magic=yessir; path=/silly/; HttpOnly
Set-Cookie: blexp=yesyes; domain=127.0.0.1; domain=127.0.0.1; expiry=totally bad;
Set-Cookie: partialip=nono; domain=.0.0.1;
Set-Cookie: withspaces=  yes  within and around    ;
Set-Cookie: withspaces2 =before equals;
Set-Cookie: prespace=  yes before;
Set-Cookie: securewithspace=after    ; secure =
%endif

boo
</data>
</reply>

# Client-side
<client>
Changes to jni/curl/tests/data/test40.
22
23
24
25
26
27
28

29



30
31
32
33
34
35
36
Date: Thu, 09 Nov 2010 14:49:00 GMT
Connection: close

body
</data2>
<datacheck>
HTTP/1.1 302 OK swsclose

Location: ../moo.html/?name=d a niel&testcase=/400002    



Date: Thu, 09 Nov 2010 14:49:00 GMT
Connection: close

HTTP/1.1 200 OK swsclose
Location: this should be ignored
Date: Thu, 09 Nov 2010 14:49:00 GMT
Connection: close







>

>
>
>







22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
Date: Thu, 09 Nov 2010 14:49:00 GMT
Connection: close

body
</data2>
<datacheck>
HTTP/1.1 302 OK swsclose
%if !hyper
Location: ../moo.html/?name=d a niel&testcase=/400002    
%else
Location: ../moo.html/?name=d a niel&testcase=/400002
%endif
Date: Thu, 09 Nov 2010 14:49:00 GMT
Connection: close

HTTP/1.1 200 OK swsclose
Location: this should be ignored
Date: Thu, 09 Nov 2010 14:49:00 GMT
Connection: close
Added jni/curl/tests/data/test410.














































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
<testcase>
<info>
<keywords>
HTTPS
HTTP GET
</keywords>
</info>

#
# Server-side
<reply>
<data>
HTTP/1.1 200 OK
Date: Thu, 09 Nov 2010 14:49:00 GMT
Server: test-server/fake
Content-Length: 7

MooMoo
</data>
</reply>

#
# Client-side
<client>
<features>
SSL
</features>
<server>
https
</server>
 <name>
HTTPS GET with very long request header
 </name>
# 14 characters repeated 3500 times makes 49000 bytes
<file name="log/file410">
Long: %repeat[3500 x header content]%
</file>
 <command>
-k https://%HOSTIP:%HTTPSPORT/410 -H @log/file410
</command>
</client>

#
# Verify data after the test has been "shot"
<verify>
<protocol>
GET /410 HTTP/1.1
Host: %HOSTIP:%HTTPSPORT
User-Agent: curl/%VERSION
Accept: */*
Long: %repeat[3500 x header content]%

</protocol>
</verify>
</testcase>
Changes to jni/curl/tests/data/test42.
22
23
24
25
26
27
28

29



30
31
32
33
34
35
36
Date: Thu, 09 Nov 2010 14:49:00 GMT
Connection: close

body
</data2>
<datacheck>
HTTP/1.1 302 OK swsclose

Location: ../m o o.html/420002    



Date: Thu, 09 Nov 2010 14:49:00 GMT
Connection: close

HTTP/1.1 200 OK swsclose
Location: this should be ignored
Date: Thu, 09 Nov 2010 14:49:00 GMT
Connection: close







>

>
>
>







22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
Date: Thu, 09 Nov 2010 14:49:00 GMT
Connection: close

body
</data2>
<datacheck>
HTTP/1.1 302 OK swsclose
%if !hyper
Location: ../m o o.html/420002    
%else
Location: ../m o o.html/420002
%endif
Date: Thu, 09 Nov 2010 14:49:00 GMT
Connection: close

HTTP/1.1 200 OK swsclose
Location: this should be ignored
Date: Thu, 09 Nov 2010 14:49:00 GMT
Connection: close
Changes to jni/curl/tests/data/test54.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<testcase>
<info>
<keywords>
HTTP
HTTP GET
followlocation
</keywords>
</info>
# Server-side
<reply>
<data>
HTTP/1.1 302 This is a weirdo text message swsclose
Connection: close
Location:  

This server reply is for testing
</data>
</reply>

# Client-side
<client>













|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<testcase>
<info>
<keywords>
HTTP
HTTP GET
followlocation
</keywords>
</info>
# Server-side
<reply>
<data>
HTTP/1.1 302 This is a weirdo text message swsclose
Connection: close
Location: 

This server reply is for testing
</data>
</reply>

# Client-side
<client>
Changes to jni/curl/tests/data/test558.
32
33
34
35
36
37
38

39
40
41
42
43

44
45
46
47
48
49
50
</command>
</client>

#
# Verify data after the test has been "shot"
<verify>
<file name="log/memdump">

MEM lib558.c: malloc()
MEM lib558.c: free()
MEM dynbuf.c: realloc()
MEM dynbuf.c: realloc()
MEM escape.c: free()

</file>
<stripfile>
s/^MEM escape.c:\d+ free\(\(nil\)\)[\n]$//
s/ =.*//
s/\(.*\)/()/
s/:\d+/:/
s:^(MEM |FD )(.*/)(.*):$1$3:







>





>







32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
</command>
</client>

#
# Verify data after the test has been "shot"
<verify>
<file name="log/memdump">
MEM easy.c: malloc()
MEM lib558.c: malloc()
MEM lib558.c: free()
MEM dynbuf.c: realloc()
MEM dynbuf.c: realloc()
MEM escape.c: free()
MEM easy.c: free()
</file>
<stripfile>
s/^MEM escape.c:\d+ free\(\(nil\)\)[\n]$//
s/ =.*//
s/\(.*\)/()/
s/:\d+/:/
s:^(MEM |FD )(.*/)(.*):$1$3:
Changes to jni/curl/tests/data/test56.
48
49
50
51
52
53
54



55

56
57
58
59
60
61
POST /that.site.com/56 HTTP/1.1
Host: %HOSTIP:%HTTPPORT
User-Agent: %repeat[99999 x a]%
Accept: */*
Transfer-Encoding: chunked
Content-Type: application/x-www-form-urlencoded




c

we post this
0

</protocol>
</verify>
</testcase>







>
>
>

>






48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
POST /that.site.com/56 HTTP/1.1
Host: %HOSTIP:%HTTPPORT
User-Agent: %repeat[99999 x a]%
Accept: */*
Transfer-Encoding: chunked
Content-Type: application/x-www-form-urlencoded

%if hyper
C
%else
c
%endif
we post this
0

</protocol>
</verify>
</testcase>
Added jni/curl/tests/data/test584.


































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
<testcase>
<info>
<keywords>
HTTP
HTTP POST
HTTP MIME
</keywords>
</info>

#
# Server-side
<reply>
<data>
HTTP/1.1 200 OK swsclose
Date: Thu, 09 Nov 2010 14:49:00 GMT
Server: test-server/fake
Content-Length: 3

OK
</data>
<datacheck>
HTTP/1.1 200 OK swsclose
Date: Thu, 09 Nov 2010 14:49:00 GMT
Server: test-server/fake
Content-Length: 3

OK
HTTP/1.1 200 OK swsclose
Date: Thu, 09 Nov 2010 14:49:00 GMT
Server: test-server/fake
Content-Length: 3

OK
</datacheck>
</reply>

# Client-side
<client>
<server>
http
</server>
# tool to invoke
<tool>
lib584
</tool>

 <name>
CURLOPT_MIMEPOST first set then set to NULL
 </name>
 <command>
http://%HOSTIP:%HTTPPORT/584
</command>
</client>

#
# Verify data after the test has been "shot"
<verify>
<strippart>
s/^--------------------------[a-z0-9]*/--------------------------/
s/boundary=------------------------[a-z0-9]*/boundary=------------------------/
</strippart>
<protocol>
POST /584 HTTP/1.1
Host: %HOSTIP:%HTTPPORT
Accept: */*
Content-Length: 144
Content-Type: multipart/form-data; boundary=------------------------

--------------------------
Content-Disposition: form-data; name="fake"

party
----------------------------
POST /584 HTTP/1.1
Host: %HOSTIP:%HTTPPORT
Accept: */*
Content-Length: 0

</protocol>
</verify>
</testcase>
Changes to jni/curl/tests/data/test60.
39
40
41
42
43
44
45

46

47
48
49
50
51
52
53
<verify>
<protocol>
PUT /bzz/60 HTTP/1.1
Host: %HOSTIP:%HTTPPORT
User-Agent: curl/%VERSION
Accept: */*
Transfer-Encoding: chunked

Content-Length: 1

Expect: 100-continue

13
more than one byte

0








>

>







39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
<verify>
<protocol>
PUT /bzz/60 HTTP/1.1
Host: %HOSTIP:%HTTPPORT
User-Agent: curl/%VERSION
Accept: */*
Transfer-Encoding: chunked
%if !hyper
Content-Length: 1
%endif
Expect: 100-continue

13
more than one byte

0

Changes to jni/curl/tests/data/test66.
11
12
13
14
15
16
17



18
19
20
21
22
23
24
<data>
no headers swsclose
</data>
</reply>

# Client-side
<client>



<server>
http
</server>
 <name>
HTTP GET without headers in the response
 </name>
 <command>







>
>
>







11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<data>
no headers swsclose
</data>
</reply>

# Client-side
<client>
<features>
!hyper
</features>
<server>
http
</server>
 <name>
HTTP GET without headers in the response
 </name>
 <command>
Changes to jni/curl/tests/data/test660.
25
26
27
28
29
30
31

32
33
34
</client>

#
# Verify data after the test has been "shot"
<verify>
<protocol>
A001 CAPABILITY

</protocol>
</verify>
</testcase>







>



25
26
27
28
29
30
31
32
33
34
35
</client>

#
# Verify data after the test has been "shot"
<verify>
<protocol>
A001 CAPABILITY
A002 LOGOUT
</protocol>
</verify>
</testcase>
Changes to jni/curl/tests/data/test970.
55
56
57
58
59
60
61
62
63
64
65
GET /970 HTTP/1.1
Host: %HOSTIP:%HTTPPORT
User-Agent: curl/%VERSION
Accept: */*

</protocol>
<stdout nonewline="yes">
{"url_effective":"http://%HOSTIP:%HTTPPORT/970","method":"GET","http_code":200,"response_code":200,"num_headers":9,"http_connect":0,"time_total":0.000013,"time_namelookup":0.000013,"time_connect":0.000013,"time_appconnect":0.000013,"time_pretransfer":0.000013,"time_starttransfer":0.000013,"size_header":4019,"size_request":4019,"size_download":445,"size_upload":0,"speed_download":13,"speed_upload":13,"content_type":"text/html","num_connects":1,"time_redirect":0.000013,"num_redirects":0,"ssl_verify_result":0,"proxy_ssl_verify_result":0,"filename_effective":"log/out970","remote_ip":"%HOSTIP","remote_port":%HTTPPORT,"local_ip":"127.0.0.1","local_port":13,"http_version":"1.1","scheme":"HTTP","curl_version":"curl-unit-test-fake-version"}
</stdout>
</verify>
</testcase>







|



55
56
57
58
59
60
61
62
63
64
65
GET /970 HTTP/1.1
Host: %HOSTIP:%HTTPPORT
User-Agent: curl/%VERSION
Accept: */*

</protocol>
<stdout nonewline="yes">
{"content_type":"text/html","filename_effective":"log/out970","http_code":200,"http_connect":0,"http_version":"1.1","local_ip":"127.0.0.1","local_port":13,"method":"GET","num_connects":1,"num_headers":9,"num_redirects":0,"proxy_ssl_verify_result":0,"remote_ip":"%HOSTIP","remote_port":%HTTPPORT,"response_code":200,"scheme":"HTTP","size_download":445,"size_header":4019,"size_request":4019,"size_upload":0,"speed_download":13,"speed_upload":13,"ssl_verify_result":0,"time_appconnect":0.000013,"time_connect":0.000013,"time_namelookup":0.000013,"time_pretransfer":0.000013,"time_redirect":0.000013,"time_starttransfer":0.000013,"time_total":0.000013,"url_effective":"http://%HOSTIP:%HTTPPORT/970","curl_version":"curl-unit-test-fake-version"}
</stdout>
</verify>
</testcase>
Changes to jni/curl/tests/libtest/Makefile.am.
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
              -I$(top_srcdir)/ares
else
AM_CPPFLAGS = -I$(top_srcdir)/include        \
              -I$(top_builddir)/lib          \
              -I$(top_srcdir)/lib
endif

EXTRA_DIST = test307.pl test610.pl test613.pl test1013.pl \
  test1022.pl Makefile.inc notexists.pl CMakeLists.txt mk-lib1521.pl

CFLAG_CURL_SYMBOL_HIDING = @CFLAG_CURL_SYMBOL_HIDING@

CFLAGS += @CURL_CFLAG_EXTRAS@

CLEANFILES = lib1521.c








|
|







40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
              -I$(top_srcdir)/ares
else
AM_CPPFLAGS = -I$(top_srcdir)/include        \
              -I$(top_builddir)/lib          \
              -I$(top_srcdir)/lib
endif

EXTRA_DIST = test307.pl test610.pl test613.pl test1013.pl test1022.pl   \
  Makefile.inc notexists.pl CMakeLists.txt mk-lib1521.pl .checksrc

CFLAG_CURL_SYMBOL_HIDING = @CFLAG_CURL_SYMBOL_HIDING@

CFLAGS += @CURL_CFLAG_EXTRAS@

CLEANFILES = lib1521.c

Changes to jni/curl/tests/libtest/Makefile.in.
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143

144
145
146
147
148


149
150
151
152
153
154
155
	lib556$(EXEEXT) lib557$(EXEEXT) lib558$(EXEEXT) \
	lib559$(EXEEXT) lib560$(EXEEXT) lib562$(EXEEXT) \
	lib564$(EXEEXT) lib565$(EXEEXT) lib566$(EXEEXT) \
	lib567$(EXEEXT) lib568$(EXEEXT) lib569$(EXEEXT) \
	lib570$(EXEEXT) lib571$(EXEEXT) lib572$(EXEEXT) \
	lib573$(EXEEXT) lib574$(EXEEXT) lib575$(EXEEXT) \
	lib576$(EXEEXT) lib578$(EXEEXT) lib579$(EXEEXT) \
	lib582$(EXEEXT) lib583$(EXEEXT) lib585$(EXEEXT) \
	lib586$(EXEEXT) lib587$(EXEEXT) lib589$(EXEEXT) \
	lib590$(EXEEXT) lib591$(EXEEXT) lib597$(EXEEXT) \
	lib598$(EXEEXT) lib599$(EXEEXT) lib643$(EXEEXT) \
	lib644$(EXEEXT) lib645$(EXEEXT) lib650$(EXEEXT) \
	lib651$(EXEEXT) lib652$(EXEEXT) lib653$(EXEEXT) \
	lib654$(EXEEXT) lib655$(EXEEXT) lib658$(EXEEXT) \
	lib659$(EXEEXT) lib661$(EXEEXT) lib666$(EXEEXT) \
	lib667$(EXEEXT) lib668$(EXEEXT) lib670$(EXEEXT) \
	lib671$(EXEEXT) lib672$(EXEEXT) lib673$(EXEEXT) \
	lib674$(EXEEXT) lib1156$(EXEEXT) lib1500$(EXEEXT) \
	lib1501$(EXEEXT) lib1502$(EXEEXT) lib1503$(EXEEXT) \
	lib1504$(EXEEXT) lib1505$(EXEEXT) lib1506$(EXEEXT) \
	lib1507$(EXEEXT) lib1508$(EXEEXT) lib1509$(EXEEXT) \
	lib1510$(EXEEXT) lib1511$(EXEEXT) lib1512$(EXEEXT) \
	lib1513$(EXEEXT) lib1514$(EXEEXT) lib1515$(EXEEXT) \
	lib1517$(EXEEXT) lib1518$(EXEEXT) lib1520$(EXEEXT) \
	lib1521$(EXEEXT) lib1522$(EXEEXT) lib1523$(EXEEXT) \
	lib1525$(EXEEXT) lib1526$(EXEEXT) lib1527$(EXEEXT) \
	lib1528$(EXEEXT) lib1529$(EXEEXT) lib1530$(EXEEXT) \
	lib1531$(EXEEXT) lib1532$(EXEEXT) lib1533$(EXEEXT) \
	lib1534$(EXEEXT) lib1535$(EXEEXT) lib1536$(EXEEXT) \
	lib1537$(EXEEXT) lib1538$(EXEEXT) lib1539$(EXEEXT) \
	lib1540$(EXEEXT) lib1550$(EXEEXT) lib1551$(EXEEXT) \
	lib1552$(EXEEXT) lib1553$(EXEEXT) lib1554$(EXEEXT) \
	lib1555$(EXEEXT) lib1556$(EXEEXT) lib1557$(EXEEXT) \
	lib1558$(EXEEXT) lib1559$(EXEEXT) lib1560$(EXEEXT) \
	lib1564$(EXEEXT) lib1565$(EXEEXT) lib1567$(EXEEXT) \

	lib1591$(EXEEXT) lib1592$(EXEEXT) lib1593$(EXEEXT) \
	lib1594$(EXEEXT) lib1596$(EXEEXT) lib1905$(EXEEXT) \
	lib1906$(EXEEXT) lib1907$(EXEEXT) lib1908$(EXEEXT) \
	lib1910$(EXEEXT) lib1911$(EXEEXT) lib1912$(EXEEXT) \
	lib1913$(EXEEXT) lib1915$(EXEEXT) lib3010$(EXEEXT)


@USE_CPPFLAG_CURL_STATICLIB_TRUE@am__append_1 = -DCURL_STATICLIB
@CURL_LT_SHLIB_USE_NO_UNDEFINED_TRUE@am__append_2 = -no-undefined
@CURL_LT_SHLIB_USE_NO_UNDEFINED_TRUE@am__append_3 = -no-undefined
@CURL_LT_SHLIB_USE_MIMPURE_TEXT_TRUE@am__append_4 = -mimpure-text
@DOING_CURL_SYMBOL_HIDING_TRUE@am__append_5 = -DCURL_HIDDEN_SYMBOLS
@DOING_CURL_SYMBOL_HIDING_TRUE@am__append_6 = $(CFLAG_CURL_SYMBOL_HIDING)








|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
>
|
|
|
|
|
>
>







109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
	lib556$(EXEEXT) lib557$(EXEEXT) lib558$(EXEEXT) \
	lib559$(EXEEXT) lib560$(EXEEXT) lib562$(EXEEXT) \
	lib564$(EXEEXT) lib565$(EXEEXT) lib566$(EXEEXT) \
	lib567$(EXEEXT) lib568$(EXEEXT) lib569$(EXEEXT) \
	lib570$(EXEEXT) lib571$(EXEEXT) lib572$(EXEEXT) \
	lib573$(EXEEXT) lib574$(EXEEXT) lib575$(EXEEXT) \
	lib576$(EXEEXT) lib578$(EXEEXT) lib579$(EXEEXT) \
	lib582$(EXEEXT) lib583$(EXEEXT) lib584$(EXEEXT) \
	lib585$(EXEEXT) lib586$(EXEEXT) lib587$(EXEEXT) \
	lib589$(EXEEXT) lib590$(EXEEXT) lib591$(EXEEXT) \
	lib597$(EXEEXT) lib598$(EXEEXT) lib599$(EXEEXT) \
	lib643$(EXEEXT) lib644$(EXEEXT) lib645$(EXEEXT) \
	lib650$(EXEEXT) lib651$(EXEEXT) lib652$(EXEEXT) \
	lib653$(EXEEXT) lib654$(EXEEXT) lib655$(EXEEXT) \
	lib658$(EXEEXT) lib659$(EXEEXT) lib661$(EXEEXT) \
	lib666$(EXEEXT) lib667$(EXEEXT) lib668$(EXEEXT) \
	lib670$(EXEEXT) lib671$(EXEEXT) lib672$(EXEEXT) \
	lib673$(EXEEXT) lib674$(EXEEXT) lib1156$(EXEEXT) \
	lib1500$(EXEEXT) lib1501$(EXEEXT) lib1502$(EXEEXT) \
	lib1503$(EXEEXT) lib1504$(EXEEXT) lib1505$(EXEEXT) \
	lib1506$(EXEEXT) lib1507$(EXEEXT) lib1508$(EXEEXT) \
	lib1509$(EXEEXT) lib1510$(EXEEXT) lib1511$(EXEEXT) \
	lib1512$(EXEEXT) lib1513$(EXEEXT) lib1514$(EXEEXT) \
	lib1515$(EXEEXT) lib1517$(EXEEXT) lib1518$(EXEEXT) \
	lib1520$(EXEEXT) lib1521$(EXEEXT) lib1522$(EXEEXT) \
	lib1523$(EXEEXT) lib1525$(EXEEXT) lib1526$(EXEEXT) \
	lib1527$(EXEEXT) lib1528$(EXEEXT) lib1529$(EXEEXT) \
	lib1530$(EXEEXT) lib1531$(EXEEXT) lib1532$(EXEEXT) \
	lib1533$(EXEEXT) lib1534$(EXEEXT) lib1535$(EXEEXT) \
	lib1536$(EXEEXT) lib1537$(EXEEXT) lib1538$(EXEEXT) \
	lib1539$(EXEEXT) lib1540$(EXEEXT) lib1550$(EXEEXT) \
	lib1551$(EXEEXT) lib1552$(EXEEXT) lib1553$(EXEEXT) \
	lib1554$(EXEEXT) lib1555$(EXEEXT) lib1556$(EXEEXT) \
	lib1557$(EXEEXT) lib1558$(EXEEXT) lib1559$(EXEEXT) \
	lib1560$(EXEEXT) lib1564$(EXEEXT) lib1565$(EXEEXT) \
	lib1567$(EXEEXT) lib1568$(EXEEXT) lib1591$(EXEEXT) \
	lib1592$(EXEEXT) lib1593$(EXEEXT) lib1594$(EXEEXT) \
	lib1596$(EXEEXT) lib1905$(EXEEXT) lib1906$(EXEEXT) \
	lib1907$(EXEEXT) lib1908$(EXEEXT) lib1910$(EXEEXT) \
	lib1911$(EXEEXT) lib1912$(EXEEXT) lib1913$(EXEEXT) \
	lib1915$(EXEEXT) lib1916$(EXEEXT) lib1917$(EXEEXT) \
	lib1918$(EXEEXT) lib1933$(EXEEXT) lib1934$(EXEEXT) \
	lib1935$(EXEEXT) lib1936$(EXEEXT) lib3010$(EXEEXT)
@USE_CPPFLAG_CURL_STATICLIB_TRUE@am__append_1 = -DCURL_STATICLIB
@CURL_LT_SHLIB_USE_NO_UNDEFINED_TRUE@am__append_2 = -no-undefined
@CURL_LT_SHLIB_USE_NO_UNDEFINED_TRUE@am__append_3 = -no-undefined
@CURL_LT_SHLIB_USE_MIMPURE_TEXT_TRUE@am__append_4 = -mimpure-text
@DOING_CURL_SYMBOL_HIDING_TRUE@am__append_5 = -DCURL_HIDDEN_SYMBOLS
@DOING_CURL_SYMBOL_HIDING_TRUE@am__append_6 = $(CFLAG_CURL_SYMBOL_HIDING)

356
357
358
359
360
361
362


363

364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565





566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657

















































658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074





1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
lib1520_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_54 = lib1521-first.$(OBJEXT)
nodist_lib1521_OBJECTS = lib1521-lib1521.$(OBJEXT) $(am__objects_54)
lib1521_OBJECTS = $(nodist_lib1521_OBJECTS)
lib1521_LDADD = $(LDADD)
lib1521_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_55 = lib1522-first.$(OBJEXT)


am_lib1522_OBJECTS = lib1522-lib1522.$(OBJEXT) $(am__objects_55)

lib1522_OBJECTS = $(am_lib1522_OBJECTS)
lib1522_LDADD = $(LDADD)
lib1522_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_56 = lib1523-first.$(OBJEXT)
am_lib1523_OBJECTS = lib1523-lib1523.$(OBJEXT) $(am__objects_56)
lib1523_OBJECTS = $(am_lib1523_OBJECTS)
lib1523_LDADD = $(LDADD)
lib1523_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_57 = lib1525-first.$(OBJEXT)
am__objects_58 = lib1525-testutil.$(OBJEXT)
am__objects_59 = ../../lib/lib1525-warnless.$(OBJEXT)
am_lib1525_OBJECTS = lib1525-lib1525.$(OBJEXT) $(am__objects_57) \
	$(am__objects_58) $(am__objects_59)
lib1525_OBJECTS = $(am_lib1525_OBJECTS)
lib1525_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_60 = lib1526-first.$(OBJEXT)
am__objects_61 = lib1526-testutil.$(OBJEXT)
am__objects_62 = ../../lib/lib1526-warnless.$(OBJEXT)
am_lib1526_OBJECTS = lib1526-lib1526.$(OBJEXT) $(am__objects_60) \
	$(am__objects_61) $(am__objects_62)
lib1526_OBJECTS = $(am_lib1526_OBJECTS)
lib1526_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_63 = lib1527-first.$(OBJEXT)
am__objects_64 = lib1527-testutil.$(OBJEXT)
am__objects_65 = ../../lib/lib1527-warnless.$(OBJEXT)
am_lib1527_OBJECTS = lib1527-lib1527.$(OBJEXT) $(am__objects_63) \
	$(am__objects_64) $(am__objects_65)
lib1527_OBJECTS = $(am_lib1527_OBJECTS)
lib1527_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_66 = lib1528-first.$(OBJEXT)
am__objects_67 = lib1528-testutil.$(OBJEXT)
am__objects_68 = ../../lib/lib1528-warnless.$(OBJEXT)
am_lib1528_OBJECTS = lib1528-lib1528.$(OBJEXT) $(am__objects_66) \
	$(am__objects_67) $(am__objects_68)
lib1528_OBJECTS = $(am_lib1528_OBJECTS)
lib1528_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_69 = lib1529-first.$(OBJEXT)
am__objects_70 = lib1529-testutil.$(OBJEXT)
am__objects_71 = ../../lib/lib1529-warnless.$(OBJEXT)
am_lib1529_OBJECTS = lib1529-lib1529.$(OBJEXT) $(am__objects_69) \
	$(am__objects_70) $(am__objects_71)
lib1529_OBJECTS = $(am_lib1529_OBJECTS)
lib1529_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_72 = lib1530-first.$(OBJEXT)
am__objects_73 = lib1530-testutil.$(OBJEXT)
am__objects_74 = ../../lib/lib1530-warnless.$(OBJEXT)
am_lib1530_OBJECTS = lib1530-lib1530.$(OBJEXT) $(am__objects_72) \
	$(am__objects_73) $(am__objects_74)
lib1530_OBJECTS = $(am_lib1530_OBJECTS)
lib1530_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_75 = lib1531-first.$(OBJEXT)
am__objects_76 = lib1531-testutil.$(OBJEXT)
am__objects_77 = ../../lib/lib1531-warnless.$(OBJEXT)
am_lib1531_OBJECTS = lib1531-lib1531.$(OBJEXT) $(am__objects_75) \
	$(am__objects_76) $(am__objects_77)
lib1531_OBJECTS = $(am_lib1531_OBJECTS)
lib1531_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_78 = lib1532-first.$(OBJEXT)
am__objects_79 = lib1532-testutil.$(OBJEXT)
am__objects_80 = ../../lib/lib1532-warnless.$(OBJEXT)
am_lib1532_OBJECTS = lib1532-lib1532.$(OBJEXT) $(am__objects_78) \
	$(am__objects_79) $(am__objects_80)
lib1532_OBJECTS = $(am_lib1532_OBJECTS)
lib1532_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_81 = lib1533-first.$(OBJEXT)
am__objects_82 = lib1533-testutil.$(OBJEXT)
am__objects_83 = ../../lib/lib1533-warnless.$(OBJEXT)
am_lib1533_OBJECTS = lib1533-lib1533.$(OBJEXT) $(am__objects_81) \
	$(am__objects_82) $(am__objects_83)
lib1533_OBJECTS = $(am_lib1533_OBJECTS)
lib1533_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_84 = lib1534-first.$(OBJEXT)
am__objects_85 = lib1534-testutil.$(OBJEXT)
am__objects_86 = ../../lib/lib1534-warnless.$(OBJEXT)
am_lib1534_OBJECTS = lib1534-lib1534.$(OBJEXT) $(am__objects_84) \
	$(am__objects_85) $(am__objects_86)
lib1534_OBJECTS = $(am_lib1534_OBJECTS)
lib1534_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_87 = lib1535-first.$(OBJEXT)
am__objects_88 = lib1535-testutil.$(OBJEXT)
am__objects_89 = ../../lib/lib1535-warnless.$(OBJEXT)
am_lib1535_OBJECTS = lib1535-lib1535.$(OBJEXT) $(am__objects_87) \
	$(am__objects_88) $(am__objects_89)
lib1535_OBJECTS = $(am_lib1535_OBJECTS)
lib1535_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_90 = lib1536-first.$(OBJEXT)
am__objects_91 = lib1536-testutil.$(OBJEXT)
am__objects_92 = ../../lib/lib1536-warnless.$(OBJEXT)
am_lib1536_OBJECTS = lib1536-lib1536.$(OBJEXT) $(am__objects_90) \
	$(am__objects_91) $(am__objects_92)
lib1536_OBJECTS = $(am_lib1536_OBJECTS)
lib1536_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_93 = lib1537-first.$(OBJEXT)
am__objects_94 = lib1537-testutil.$(OBJEXT)
am__objects_95 = ../../lib/lib1537-warnless.$(OBJEXT)
am_lib1537_OBJECTS = lib1537-lib1537.$(OBJEXT) $(am__objects_93) \
	$(am__objects_94) $(am__objects_95)
lib1537_OBJECTS = $(am_lib1537_OBJECTS)
lib1537_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_96 = lib1538-first.$(OBJEXT)
am__objects_97 = lib1538-testutil.$(OBJEXT)
am__objects_98 = ../../lib/lib1538-warnless.$(OBJEXT)
am_lib1538_OBJECTS = lib1538-lib1538.$(OBJEXT) $(am__objects_96) \
	$(am__objects_97) $(am__objects_98)
lib1538_OBJECTS = $(am_lib1538_OBJECTS)
lib1538_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_99 = lib1539-first.$(OBJEXT)
am__objects_100 = lib1539-testutil.$(OBJEXT)
am__objects_101 = ../../lib/lib1539-warnless.$(OBJEXT)
am_lib1539_OBJECTS = lib1539-lib1514.$(OBJEXT) $(am__objects_99) \
	$(am__objects_100) $(am__objects_101)
lib1539_OBJECTS = $(am_lib1539_OBJECTS)
lib1539_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_102 = lib1540-first.$(OBJEXT)
am__objects_103 = lib1540-testutil.$(OBJEXT)
am__objects_104 = ../../lib/lib1540-warnless.$(OBJEXT)
am_lib1540_OBJECTS = lib1540-lib1540.$(OBJEXT) $(am__objects_102) \
	$(am__objects_103) $(am__objects_104)
lib1540_OBJECTS = $(am_lib1540_OBJECTS)
lib1540_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_105 = lib1550-first.$(OBJEXT)
am_lib1550_OBJECTS = lib1550-lib1550.$(OBJEXT) $(am__objects_105)
lib1550_OBJECTS = $(am_lib1550_OBJECTS)
lib1550_LDADD = $(LDADD)
lib1550_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_106 = lib1551-first.$(OBJEXT)
am_lib1551_OBJECTS = lib1551-lib1551.$(OBJEXT) $(am__objects_106)
lib1551_OBJECTS = $(am_lib1551_OBJECTS)
lib1551_LDADD = $(LDADD)
lib1551_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_107 = lib1552-first.$(OBJEXT)
am__objects_108 = lib1552-testutil.$(OBJEXT)
am_lib1552_OBJECTS = lib1552-lib1552.$(OBJEXT) $(am__objects_107) \
	$(am__objects_108)
lib1552_OBJECTS = $(am_lib1552_OBJECTS)
lib1552_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_109 = lib1553-first.$(OBJEXT)
am__objects_110 = lib1553-testutil.$(OBJEXT)
am_lib1553_OBJECTS = lib1553-lib1553.$(OBJEXT) $(am__objects_109) \
	$(am__objects_110)
lib1553_OBJECTS = $(am_lib1553_OBJECTS)
lib1553_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_111 = lib1554-first.$(OBJEXT)
am_lib1554_OBJECTS = lib1554-lib1554.$(OBJEXT) $(am__objects_111)
lib1554_OBJECTS = $(am_lib1554_OBJECTS)
lib1554_LDADD = $(LDADD)
lib1554_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_112 = lib1555-first.$(OBJEXT)
am__objects_113 = lib1555-testutil.$(OBJEXT)
am__objects_114 = ../../lib/lib1555-warnless.$(OBJEXT)
am_lib1555_OBJECTS = lib1555-lib1555.$(OBJEXT) $(am__objects_112) \
	$(am__objects_113) $(am__objects_114)
lib1555_OBJECTS = $(am_lib1555_OBJECTS)
lib1555_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_115 = lib1556-first.$(OBJEXT)
am__objects_116 = lib1556-testutil.$(OBJEXT)
am__objects_117 = ../../lib/lib1556-warnless.$(OBJEXT)
am_lib1556_OBJECTS = lib1556-lib1556.$(OBJEXT) $(am__objects_115) \
	$(am__objects_116) $(am__objects_117)
lib1556_OBJECTS = $(am_lib1556_OBJECTS)
lib1556_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_118 = lib1557-first.$(OBJEXT)
am__objects_119 = lib1557-testutil.$(OBJEXT)
am__objects_120 = ../../lib/lib1557-warnless.$(OBJEXT)
am_lib1557_OBJECTS = lib1557-lib1557.$(OBJEXT) $(am__objects_118) \
	$(am__objects_119) $(am__objects_120)
lib1557_OBJECTS = $(am_lib1557_OBJECTS)
lib1557_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_121 = first.$(OBJEXT)
am__objects_122 = testutil.$(OBJEXT)
am__objects_123 = ../../lib/warnless.$(OBJEXT)
am_lib1558_OBJECTS = lib1558.$(OBJEXT) $(am__objects_121) \
	$(am__objects_122) $(am__objects_123)
lib1558_OBJECTS = $(am_lib1558_OBJECTS)
lib1558_DEPENDENCIES = $(am__DEPENDENCIES_1)
am_lib1559_OBJECTS = lib1559.$(OBJEXT) $(am__objects_121) \
	$(am__objects_122) $(am__objects_123)
lib1559_OBJECTS = $(am_lib1559_OBJECTS)
lib1559_DEPENDENCIES = $(am__DEPENDENCIES_1)
am_lib1560_OBJECTS = lib1560.$(OBJEXT) $(am__objects_121) \
	$(am__objects_122) $(am__objects_123)
lib1560_OBJECTS = $(am_lib1560_OBJECTS)
lib1560_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_124 = lib1564-first.$(OBJEXT)
am__objects_125 = lib1564-testutil.$(OBJEXT)
am__objects_126 = ../../lib/lib1564-warnless.$(OBJEXT)
am_lib1564_OBJECTS = lib1564-lib1564.$(OBJEXT) $(am__objects_124) \
	$(am__objects_125) $(am__objects_126)
lib1564_OBJECTS = $(am_lib1564_OBJECTS)
lib1564_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_127 = lib1565-first.$(OBJEXT)
am__objects_128 = lib1565-testutil.$(OBJEXT)
am__objects_129 = ../../lib/lib1565-warnless.$(OBJEXT)
am_lib1565_OBJECTS = lib1565-lib1565.$(OBJEXT) $(am__objects_127) \
	$(am__objects_128) $(am__objects_129)
lib1565_OBJECTS = $(am_lib1565_OBJECTS)
lib1565_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_130 = lib1567-first.$(OBJEXT)
am_lib1567_OBJECTS = lib1567-lib1567.$(OBJEXT) $(am__objects_130)
lib1567_OBJECTS = $(am_lib1567_OBJECTS)
lib1567_LDADD = $(LDADD)
lib1567_DEPENDENCIES = $(am__DEPENDENCIES_1)





am__objects_131 = lib1591-first.$(OBJEXT)
am__objects_132 = lib1591-testutil.$(OBJEXT)
am__objects_133 = ../../lib/lib1591-warnless.$(OBJEXT)
am_lib1591_OBJECTS = lib1591-lib1591.$(OBJEXT) $(am__objects_131) \
	$(am__objects_132) $(am__objects_133)
lib1591_OBJECTS = $(am_lib1591_OBJECTS)
lib1591_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_134 = lib1592-first.$(OBJEXT)
am__objects_135 = lib1592-testutil.$(OBJEXT)
am__objects_136 = ../../lib/lib1592-warnless.$(OBJEXT)
am_lib1592_OBJECTS = lib1592-lib1592.$(OBJEXT) $(am__objects_134) \
	$(am__objects_135) $(am__objects_136)
lib1592_OBJECTS = $(am_lib1592_OBJECTS)
lib1592_DEPENDENCIES = $(am__DEPENDENCIES_1)
am_lib1593_OBJECTS = lib1593.$(OBJEXT) $(am__objects_121) \
	$(am__objects_122) $(am__objects_123)
lib1593_OBJECTS = $(am_lib1593_OBJECTS)
lib1593_DEPENDENCIES = $(am__DEPENDENCIES_1)
am_lib1594_OBJECTS = lib1594.$(OBJEXT) $(am__objects_121) \
	$(am__objects_122) $(am__objects_123)
lib1594_OBJECTS = $(am_lib1594_OBJECTS)
lib1594_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_137 = lib1596-first.$(OBJEXT)
am__objects_138 = lib1596-testutil.$(OBJEXT)
am__objects_139 = ../../lib/lib1596-warnless.$(OBJEXT)
am_lib1596_OBJECTS = lib1596-lib1594.$(OBJEXT) $(am__objects_137) \
	$(am__objects_138) $(am__objects_139)
lib1596_OBJECTS = $(am_lib1596_OBJECTS)
lib1596_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_140 = lib1905-first.$(OBJEXT)
am__objects_141 = lib1905-testutil.$(OBJEXT)
am__objects_142 = ../../lib/lib1905-warnless.$(OBJEXT)
am_lib1905_OBJECTS = lib1905-lib1905.$(OBJEXT) $(am__objects_140) \
	$(am__objects_141) $(am__objects_142)
lib1905_OBJECTS = $(am_lib1905_OBJECTS)
lib1905_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_143 = lib1906-first.$(OBJEXT)
am__objects_144 = lib1906-testutil.$(OBJEXT)
am__objects_145 = ../../lib/lib1906-warnless.$(OBJEXT)
am_lib1906_OBJECTS = lib1906-lib1906.$(OBJEXT) $(am__objects_143) \
	$(am__objects_144) $(am__objects_145)
lib1906_OBJECTS = $(am_lib1906_OBJECTS)
lib1906_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_146 = lib1907-first.$(OBJEXT)
am__objects_147 = lib1907-testutil.$(OBJEXT)
am__objects_148 = ../../lib/lib1907-warnless.$(OBJEXT)
am_lib1907_OBJECTS = lib1907-lib1907.$(OBJEXT) $(am__objects_146) \
	$(am__objects_147) $(am__objects_148)
lib1907_OBJECTS = $(am_lib1907_OBJECTS)
lib1907_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_149 = lib1908-first.$(OBJEXT)
am__objects_150 = lib1908-testutil.$(OBJEXT)
am__objects_151 = ../../lib/lib1908-warnless.$(OBJEXT)
am_lib1908_OBJECTS = lib1908-lib1908.$(OBJEXT) $(am__objects_149) \
	$(am__objects_150) $(am__objects_151)
lib1908_OBJECTS = $(am_lib1908_OBJECTS)
lib1908_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_152 = lib1910-first.$(OBJEXT)
am__objects_153 = lib1910-testutil.$(OBJEXT)
am__objects_154 = ../../lib/lib1910-warnless.$(OBJEXT)
am_lib1910_OBJECTS = lib1910-lib1910.$(OBJEXT) $(am__objects_152) \
	$(am__objects_153) $(am__objects_154)
lib1910_OBJECTS = $(am_lib1910_OBJECTS)
lib1910_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_155 = lib1911-first.$(OBJEXT)
am__objects_156 = lib1911-testutil.$(OBJEXT)
am__objects_157 = ../../lib/lib1911-warnless.$(OBJEXT)
am_lib1911_OBJECTS = lib1911-lib1911.$(OBJEXT) $(am__objects_155) \
	$(am__objects_156) $(am__objects_157)
lib1911_OBJECTS = $(am_lib1911_OBJECTS)
lib1911_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_158 = lib1912-first.$(OBJEXT)
am__objects_159 = lib1912-testutil.$(OBJEXT)
am__objects_160 = ../../lib/lib1912-warnless.$(OBJEXT)
am_lib1912_OBJECTS = lib1912-lib1912.$(OBJEXT) $(am__objects_158) \
	$(am__objects_159) $(am__objects_160)
lib1912_OBJECTS = $(am_lib1912_OBJECTS)
lib1912_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_161 = lib1913-first.$(OBJEXT)
am__objects_162 = lib1913-testutil.$(OBJEXT)
am__objects_163 = ../../lib/lib1913-warnless.$(OBJEXT)
am_lib1913_OBJECTS = lib1913-lib1913.$(OBJEXT) $(am__objects_161) \
	$(am__objects_162) $(am__objects_163)
lib1913_OBJECTS = $(am_lib1913_OBJECTS)
lib1913_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_164 = lib1915-first.$(OBJEXT)
am__objects_165 = lib1915-testutil.$(OBJEXT)
am__objects_166 = ../../lib/lib1915-warnless.$(OBJEXT)
am_lib1915_OBJECTS = lib1915-lib1915.$(OBJEXT) $(am__objects_164) \
	$(am__objects_165) $(am__objects_166)
lib1915_OBJECTS = $(am_lib1915_OBJECTS)
lib1915_DEPENDENCIES = $(am__DEPENDENCIES_1)

















































am__objects_167 = lib3010-first.$(OBJEXT)
am__objects_168 = lib3010-testutil.$(OBJEXT)
am__objects_169 = ../../lib/lib3010-warnless.$(OBJEXT)
am_lib3010_OBJECTS = lib3010-lib3010.$(OBJEXT) $(am__objects_167) \
	$(am__objects_168) $(am__objects_169)
lib3010_OBJECTS = $(am_lib3010_OBJECTS)
lib3010_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_170 = lib500-first.$(OBJEXT)
am__objects_171 = lib500-testutil.$(OBJEXT)
am__objects_172 = lib500-testtrace.$(OBJEXT)
am__objects_173 = ../../lib/lib500-curl_multibyte.$(OBJEXT)
am_lib500_OBJECTS = lib500-lib500.$(OBJEXT) $(am__objects_170) \
	$(am__objects_171) $(am__objects_172) $(am__objects_173)
lib500_OBJECTS = $(am_lib500_OBJECTS)
lib500_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_174 = lib501-first.$(OBJEXT)
am_lib501_OBJECTS = lib501-lib501.$(OBJEXT) $(am__objects_174)
lib501_OBJECTS = $(am_lib501_OBJECTS)
lib501_LDADD = $(LDADD)
lib501_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_175 = lib502-first.$(OBJEXT)
am__objects_176 = lib502-testutil.$(OBJEXT)
am__objects_177 = ../../lib/lib502-warnless.$(OBJEXT)
am_lib502_OBJECTS = lib502-lib502.$(OBJEXT) $(am__objects_175) \
	$(am__objects_176) $(am__objects_177)
lib502_OBJECTS = $(am_lib502_OBJECTS)
lib502_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_178 = lib503-first.$(OBJEXT)
am__objects_179 = lib503-testutil.$(OBJEXT)
am__objects_180 = ../../lib/lib503-warnless.$(OBJEXT)
am_lib503_OBJECTS = lib503-lib503.$(OBJEXT) $(am__objects_178) \
	$(am__objects_179) $(am__objects_180)
lib503_OBJECTS = $(am_lib503_OBJECTS)
lib503_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_181 = lib504-first.$(OBJEXT)
am__objects_182 = lib504-testutil.$(OBJEXT)
am__objects_183 = ../../lib/lib504-warnless.$(OBJEXT)
am_lib504_OBJECTS = lib504-lib504.$(OBJEXT) $(am__objects_181) \
	$(am__objects_182) $(am__objects_183)
lib504_OBJECTS = $(am_lib504_OBJECTS)
lib504_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_184 = lib505-first.$(OBJEXT)
am__objects_185 = ../../lib/lib505-curl_multibyte.$(OBJEXT)
am_lib505_OBJECTS = lib505-lib505.$(OBJEXT) $(am__objects_184) \
	$(am__objects_185)
lib505_OBJECTS = $(am_lib505_OBJECTS)
lib505_LDADD = $(LDADD)
lib505_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_186 = lib506-first.$(OBJEXT)
am_lib506_OBJECTS = lib506-lib506.$(OBJEXT) $(am__objects_186)
lib506_OBJECTS = $(am_lib506_OBJECTS)
lib506_LDADD = $(LDADD)
lib506_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_187 = lib507-first.$(OBJEXT)
am__objects_188 = lib507-testutil.$(OBJEXT)
am__objects_189 = ../../lib/lib507-warnless.$(OBJEXT)
am_lib507_OBJECTS = lib507-lib507.$(OBJEXT) $(am__objects_187) \
	$(am__objects_188) $(am__objects_189)
lib507_OBJECTS = $(am_lib507_OBJECTS)
lib507_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_190 = lib508-first.$(OBJEXT)
am_lib508_OBJECTS = lib508-lib508.$(OBJEXT) $(am__objects_190)
lib508_OBJECTS = $(am_lib508_OBJECTS)
lib508_LDADD = $(LDADD)
lib508_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_191 = lib509-first.$(OBJEXT)
am_lib509_OBJECTS = lib509-lib509.$(OBJEXT) $(am__objects_191)
lib509_OBJECTS = $(am_lib509_OBJECTS)
lib509_LDADD = $(LDADD)
lib509_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_192 = lib510-first.$(OBJEXT)
am_lib510_OBJECTS = lib510-lib510.$(OBJEXT) $(am__objects_192)
lib510_OBJECTS = $(am_lib510_OBJECTS)
lib510_LDADD = $(LDADD)
lib510_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_193 = lib511-first.$(OBJEXT)
am_lib511_OBJECTS = lib511-lib511.$(OBJEXT) $(am__objects_193)
lib511_OBJECTS = $(am_lib511_OBJECTS)
lib511_LDADD = $(LDADD)
lib511_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_194 = lib512-first.$(OBJEXT)
am_lib512_OBJECTS = lib512-lib512.$(OBJEXT) $(am__objects_194)
lib512_OBJECTS = $(am_lib512_OBJECTS)
lib512_LDADD = $(LDADD)
lib512_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_195 = lib513-first.$(OBJEXT)
am_lib513_OBJECTS = lib513-lib513.$(OBJEXT) $(am__objects_195)
lib513_OBJECTS = $(am_lib513_OBJECTS)
lib513_LDADD = $(LDADD)
lib513_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_196 = lib514-first.$(OBJEXT)
am_lib514_OBJECTS = lib514-lib514.$(OBJEXT) $(am__objects_196)
lib514_OBJECTS = $(am_lib514_OBJECTS)
lib514_LDADD = $(LDADD)
lib514_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_197 = lib515-first.$(OBJEXT)
am_lib515_OBJECTS = lib515-lib515.$(OBJEXT) $(am__objects_197)
lib515_OBJECTS = $(am_lib515_OBJECTS)
lib515_LDADD = $(LDADD)
lib515_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_198 = lib516-first.$(OBJEXT)
am_lib516_OBJECTS = lib516-lib516.$(OBJEXT) $(am__objects_198)
lib516_OBJECTS = $(am_lib516_OBJECTS)
lib516_LDADD = $(LDADD)
lib516_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_199 = lib517-first.$(OBJEXT)
am_lib517_OBJECTS = lib517-lib517.$(OBJEXT) $(am__objects_199)
lib517_OBJECTS = $(am_lib517_OBJECTS)
lib517_LDADD = $(LDADD)
lib517_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_200 = lib518-first.$(OBJEXT)
am__objects_201 = ../../lib/lib518-warnless.$(OBJEXT)
am__objects_202 = ../../lib/lib518-curl_multibyte.$(OBJEXT)
am_lib518_OBJECTS = lib518-lib518.$(OBJEXT) $(am__objects_200) \
	$(am__objects_201) $(am__objects_202)
lib518_OBJECTS = $(am_lib518_OBJECTS)
lib518_LDADD = $(LDADD)
lib518_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_203 = lib519-first.$(OBJEXT)
am_lib519_OBJECTS = lib519-lib519.$(OBJEXT) $(am__objects_203)
lib519_OBJECTS = $(am_lib519_OBJECTS)
lib519_LDADD = $(LDADD)
lib519_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_204 = lib520-first.$(OBJEXT)
am_lib520_OBJECTS = lib520-lib520.$(OBJEXT) $(am__objects_204)
lib520_OBJECTS = $(am_lib520_OBJECTS)
lib520_LDADD = $(LDADD)
lib520_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_205 = lib521-first.$(OBJEXT)
am_lib521_OBJECTS = lib521-lib521.$(OBJEXT) $(am__objects_205)
lib521_OBJECTS = $(am_lib521_OBJECTS)
lib521_LDADD = $(LDADD)
lib521_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_206 = lib523-first.$(OBJEXT)
am_lib523_OBJECTS = lib523-lib523.$(OBJEXT) $(am__objects_206)
lib523_OBJECTS = $(am_lib523_OBJECTS)
lib523_LDADD = $(LDADD)
lib523_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_207 = lib524-first.$(OBJEXT)
am_lib524_OBJECTS = lib524-lib524.$(OBJEXT) $(am__objects_207)
lib524_OBJECTS = $(am_lib524_OBJECTS)
lib524_LDADD = $(LDADD)
lib524_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_208 = lib525-first.$(OBJEXT)
am__objects_209 = lib525-testutil.$(OBJEXT)
am__objects_210 = ../../lib/lib525-warnless.$(OBJEXT)
am__objects_211 = ../../lib/lib525-curl_multibyte.$(OBJEXT)
am_lib525_OBJECTS = lib525-lib525.$(OBJEXT) $(am__objects_208) \
	$(am__objects_209) $(am__objects_210) $(am__objects_211)
lib525_OBJECTS = $(am_lib525_OBJECTS)
lib525_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_212 = lib526-first.$(OBJEXT)
am__objects_213 = lib526-testutil.$(OBJEXT)
am__objects_214 = ../../lib/lib526-warnless.$(OBJEXT)
am_lib526_OBJECTS = lib526-lib526.$(OBJEXT) $(am__objects_212) \
	$(am__objects_213) $(am__objects_214)
lib526_OBJECTS = $(am_lib526_OBJECTS)
lib526_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_215 = lib527-first.$(OBJEXT)
am__objects_216 = lib527-testutil.$(OBJEXT)
am__objects_217 = ../../lib/lib527-warnless.$(OBJEXT)
am_lib527_OBJECTS = lib527-lib526.$(OBJEXT) $(am__objects_215) \
	$(am__objects_216) $(am__objects_217)
lib527_OBJECTS = $(am_lib527_OBJECTS)
lib527_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_218 = lib529-first.$(OBJEXT)
am__objects_219 = lib529-testutil.$(OBJEXT)
am__objects_220 = ../../lib/lib529-warnless.$(OBJEXT)
am__objects_221 = ../../lib/lib529-curl_multibyte.$(OBJEXT)
am_lib529_OBJECTS = lib529-lib525.$(OBJEXT) $(am__objects_218) \
	$(am__objects_219) $(am__objects_220) $(am__objects_221)
lib529_OBJECTS = $(am_lib529_OBJECTS)
lib529_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_222 = lib532-first.$(OBJEXT)
am__objects_223 = lib532-testutil.$(OBJEXT)
am__objects_224 = ../../lib/lib532-warnless.$(OBJEXT)
am_lib532_OBJECTS = lib532-lib526.$(OBJEXT) $(am__objects_222) \
	$(am__objects_223) $(am__objects_224)
lib532_OBJECTS = $(am_lib532_OBJECTS)
lib532_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_225 = lib533-first.$(OBJEXT)
am__objects_226 = lib533-testutil.$(OBJEXT)
am__objects_227 = ../../lib/lib533-warnless.$(OBJEXT)
am_lib533_OBJECTS = lib533-lib533.$(OBJEXT) $(am__objects_225) \
	$(am__objects_226) $(am__objects_227)
lib533_OBJECTS = $(am_lib533_OBJECTS)
lib533_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_228 = lib537-first.$(OBJEXT)
am__objects_229 = ../../lib/lib537-warnless.$(OBJEXT)
am__objects_230 = ../../lib/lib537-curl_multibyte.$(OBJEXT)
am_lib537_OBJECTS = lib537-lib537.$(OBJEXT) $(am__objects_228) \
	$(am__objects_229) $(am__objects_230)
lib537_OBJECTS = $(am_lib537_OBJECTS)
lib537_LDADD = $(LDADD)
lib537_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_231 = lib539-first.$(OBJEXT)
am_lib539_OBJECTS = lib539-lib539.$(OBJEXT) $(am__objects_231)
lib539_OBJECTS = $(am_lib539_OBJECTS)
lib539_LDADD = $(LDADD)
lib539_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_232 = lib540-first.$(OBJEXT)
am__objects_233 = lib540-testutil.$(OBJEXT)
am__objects_234 = ../../lib/lib540-warnless.$(OBJEXT)
am_lib540_OBJECTS = lib540-lib540.$(OBJEXT) $(am__objects_232) \
	$(am__objects_233) $(am__objects_234)
lib540_OBJECTS = $(am_lib540_OBJECTS)
lib540_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_235 = lib541-first.$(OBJEXT)
am__objects_236 = ../../lib/lib541-curl_multibyte.$(OBJEXT)
am_lib541_OBJECTS = lib541-lib541.$(OBJEXT) $(am__objects_235) \
	$(am__objects_236)
lib541_OBJECTS = $(am_lib541_OBJECTS)
lib541_LDADD = $(LDADD)
lib541_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_237 = lib542-first.$(OBJEXT)
am_lib542_OBJECTS = lib542-lib542.$(OBJEXT) $(am__objects_237)
lib542_OBJECTS = $(am_lib542_OBJECTS)
lib542_LDADD = $(LDADD)
lib542_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_238 = lib543-first.$(OBJEXT)
am_lib543_OBJECTS = lib543-lib543.$(OBJEXT) $(am__objects_238)
lib543_OBJECTS = $(am_lib543_OBJECTS)
lib543_LDADD = $(LDADD)
lib543_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_239 = lib544-first.$(OBJEXT)
am_lib544_OBJECTS = lib544-lib544.$(OBJEXT) $(am__objects_239)
lib544_OBJECTS = $(am_lib544_OBJECTS)
lib544_LDADD = $(LDADD)
lib544_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_240 = lib545-first.$(OBJEXT)
am_lib545_OBJECTS = lib545-lib544.$(OBJEXT) $(am__objects_240)
lib545_OBJECTS = $(am_lib545_OBJECTS)
lib545_LDADD = $(LDADD)
lib545_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_241 = lib547-first.$(OBJEXT)
am_lib547_OBJECTS = lib547-lib547.$(OBJEXT) $(am__objects_241)
lib547_OBJECTS = $(am_lib547_OBJECTS)
lib547_LDADD = $(LDADD)
lib547_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_242 = lib548-first.$(OBJEXT)
am_lib548_OBJECTS = lib548-lib547.$(OBJEXT) $(am__objects_242)
lib548_OBJECTS = $(am_lib548_OBJECTS)
lib548_LDADD = $(LDADD)
lib548_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_243 = lib549-first.$(OBJEXT)
am_lib549_OBJECTS = lib549-lib549.$(OBJEXT) $(am__objects_243)
lib549_OBJECTS = $(am_lib549_OBJECTS)
lib549_LDADD = $(LDADD)
lib549_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_244 = lib552-first.$(OBJEXT)
am__objects_245 = ../../lib/lib552-warnless.$(OBJEXT)
am_lib552_OBJECTS = lib552-lib552.$(OBJEXT) $(am__objects_244) \
	$(am__objects_245)
lib552_OBJECTS = $(am_lib552_OBJECTS)
lib552_LDADD = $(LDADD)
lib552_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_246 = lib553-first.$(OBJEXT)
am_lib553_OBJECTS = lib553-lib553.$(OBJEXT) $(am__objects_246)
lib553_OBJECTS = $(am_lib553_OBJECTS)
lib553_LDADD = $(LDADD)
lib553_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_247 = lib554-first.$(OBJEXT)
am_lib554_OBJECTS = lib554-lib554.$(OBJEXT) $(am__objects_247)
lib554_OBJECTS = $(am_lib554_OBJECTS)
lib554_LDADD = $(LDADD)
lib554_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_248 = lib555-first.$(OBJEXT)
am__objects_249 = lib555-testutil.$(OBJEXT)
am__objects_250 = ../../lib/lib555-warnless.$(OBJEXT)
am_lib555_OBJECTS = lib555-lib555.$(OBJEXT) $(am__objects_248) \
	$(am__objects_249) $(am__objects_250)
lib555_OBJECTS = $(am_lib555_OBJECTS)
lib555_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_251 = lib556-first.$(OBJEXT)
am__objects_252 = ../../lib/lib556-warnless.$(OBJEXT)
am_lib556_OBJECTS = lib556-lib556.$(OBJEXT) $(am__objects_251) \
	$(am__objects_252)
lib556_OBJECTS = $(am_lib556_OBJECTS)
lib556_LDADD = $(LDADD)
lib556_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_253 = lib557-first.$(OBJEXT)
am_lib557_OBJECTS = lib557-lib557.$(OBJEXT) $(am__objects_253)
lib557_OBJECTS = $(am_lib557_OBJECTS)
lib557_LDADD = $(LDADD)
lib557_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_254 = lib558-first.$(OBJEXT)
am_lib558_OBJECTS = lib558-lib558.$(OBJEXT) $(am__objects_254)
lib558_OBJECTS = $(am_lib558_OBJECTS)
lib558_LDADD = $(LDADD)
lib558_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_255 = lib559-first.$(OBJEXT)
am_lib559_OBJECTS = lib559-lib559.$(OBJEXT) $(am__objects_255)
lib559_OBJECTS = $(am_lib559_OBJECTS)
lib559_LDADD = $(LDADD)
lib559_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_256 = lib560-first.$(OBJEXT)
am__objects_257 = lib560-testutil.$(OBJEXT)
am__objects_258 = ../../lib/lib560-warnless.$(OBJEXT)
am_lib560_OBJECTS = lib560-lib560.$(OBJEXT) $(am__objects_256) \
	$(am__objects_257) $(am__objects_258)
lib560_OBJECTS = $(am_lib560_OBJECTS)
lib560_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_259 = lib562-first.$(OBJEXT)
am_lib562_OBJECTS = lib562-lib562.$(OBJEXT) $(am__objects_259)
lib562_OBJECTS = $(am_lib562_OBJECTS)
lib562_LDADD = $(LDADD)
lib562_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_260 = lib564-first.$(OBJEXT)
am__objects_261 = lib564-testutil.$(OBJEXT)
am__objects_262 = ../../lib/lib564-warnless.$(OBJEXT)
am_lib564_OBJECTS = lib564-lib564.$(OBJEXT) $(am__objects_260) \
	$(am__objects_261) $(am__objects_262)
lib564_OBJECTS = $(am_lib564_OBJECTS)
lib564_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_263 = lib565-first.$(OBJEXT)
am_lib565_OBJECTS = lib565-lib510.$(OBJEXT) $(am__objects_263)
lib565_OBJECTS = $(am_lib565_OBJECTS)
lib565_LDADD = $(LDADD)
lib565_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_264 = lib566-first.$(OBJEXT)
am__objects_265 = ../../lib/lib566-curl_multibyte.$(OBJEXT)
am_lib566_OBJECTS = lib566-lib566.$(OBJEXT) $(am__objects_264) \
	$(am__objects_265)
lib566_OBJECTS = $(am_lib566_OBJECTS)
lib566_LDADD = $(LDADD)
lib566_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_266 = lib567-first.$(OBJEXT)
am_lib567_OBJECTS = lib567-lib567.$(OBJEXT) $(am__objects_266)
lib567_OBJECTS = $(am_lib567_OBJECTS)
lib567_LDADD = $(LDADD)
lib567_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_267 = lib568-first.$(OBJEXT)
am__objects_268 = ../../lib/lib568-curl_multibyte.$(OBJEXT)
am_lib568_OBJECTS = lib568-lib568.$(OBJEXT) $(am__objects_267) \
	$(am__objects_268)
lib568_OBJECTS = $(am_lib568_OBJECTS)
lib568_LDADD = $(LDADD)
lib568_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_269 = lib569-first.$(OBJEXT)
am__objects_270 = ../../lib/lib569-curl_multibyte.$(OBJEXT)
am_lib569_OBJECTS = lib569-lib569.$(OBJEXT) $(am__objects_269) \
	$(am__objects_270)
lib569_OBJECTS = $(am_lib569_OBJECTS)
lib569_LDADD = $(LDADD)
lib569_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_271 = lib570-first.$(OBJEXT)
am_lib570_OBJECTS = lib570-lib570.$(OBJEXT) $(am__objects_271)
lib570_OBJECTS = $(am_lib570_OBJECTS)
lib570_LDADD = $(LDADD)
lib570_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_272 = lib571-first.$(OBJEXT)
am__objects_273 = ../../lib/lib571-warnless.$(OBJEXT)
am__objects_274 = ../../lib/lib571-curl_multibyte.$(OBJEXT)
am_lib571_OBJECTS = lib571-lib571.$(OBJEXT) $(am__objects_272) \
	$(am__objects_273) $(am__objects_274)
lib571_OBJECTS = $(am_lib571_OBJECTS)
lib571_LDADD = $(LDADD)
lib571_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_275 = lib572-first.$(OBJEXT)
am__objects_276 = ../../lib/lib572-curl_multibyte.$(OBJEXT)
am_lib572_OBJECTS = lib572-lib572.$(OBJEXT) $(am__objects_275) \
	$(am__objects_276)
lib572_OBJECTS = $(am_lib572_OBJECTS)
lib572_LDADD = $(LDADD)
lib572_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_277 = lib573-first.$(OBJEXT)
am__objects_278 = lib573-testutil.$(OBJEXT)
am__objects_279 = ../../lib/lib573-warnless.$(OBJEXT)
am__objects_280 = lib573-testtrace.$(OBJEXT)
am_lib573_OBJECTS = lib573-lib573.$(OBJEXT) $(am__objects_277) \
	$(am__objects_278) $(am__objects_279) $(am__objects_280)
lib573_OBJECTS = $(am_lib573_OBJECTS)
lib573_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_281 = lib574-first.$(OBJEXT)
am_lib574_OBJECTS = lib574-lib574.$(OBJEXT) $(am__objects_281)
lib574_OBJECTS = $(am_lib574_OBJECTS)
lib574_LDADD = $(LDADD)
lib574_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_282 = lib575-first.$(OBJEXT)
am__objects_283 = lib575-testutil.$(OBJEXT)
am__objects_284 = ../../lib/lib575-warnless.$(OBJEXT)
am_lib575_OBJECTS = lib575-lib575.$(OBJEXT) $(am__objects_282) \
	$(am__objects_283) $(am__objects_284)
lib575_OBJECTS = $(am_lib575_OBJECTS)
lib575_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_285 = lib576-first.$(OBJEXT)
am_lib576_OBJECTS = lib576-lib576.$(OBJEXT) $(am__objects_285)
lib576_OBJECTS = $(am_lib576_OBJECTS)
lib576_LDADD = $(LDADD)
lib576_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_286 = lib578-first.$(OBJEXT)
am__objects_287 = ../../lib/lib578-curl_multibyte.$(OBJEXT)
am_lib578_OBJECTS = lib578-lib578.$(OBJEXT) $(am__objects_286) \
	$(am__objects_287)
lib578_OBJECTS = $(am_lib578_OBJECTS)
lib578_LDADD = $(LDADD)
lib578_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_288 = lib579-first.$(OBJEXT)
am__objects_289 = ../../lib/lib579-curl_multibyte.$(OBJEXT)
am_lib579_OBJECTS = lib579-lib579.$(OBJEXT) $(am__objects_288) \
	$(am__objects_289)
lib579_OBJECTS = $(am_lib579_OBJECTS)
lib579_LDADD = $(LDADD)
lib579_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_290 = lib582-first.$(OBJEXT)
am__objects_291 = lib582-testutil.$(OBJEXT)
am__objects_292 = ../../lib/lib582-warnless.$(OBJEXT)
am__objects_293 = ../../lib/lib582-curl_multibyte.$(OBJEXT)
am_lib582_OBJECTS = lib582-lib582.$(OBJEXT) $(am__objects_290) \
	$(am__objects_291) $(am__objects_292) $(am__objects_293)
lib582_OBJECTS = $(am_lib582_OBJECTS)
lib582_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_294 = lib583-first.$(OBJEXT)
am_lib583_OBJECTS = lib583-lib583.$(OBJEXT) $(am__objects_294)
lib583_OBJECTS = $(am_lib583_OBJECTS)
lib583_LDADD = $(LDADD)
lib583_DEPENDENCIES = $(am__DEPENDENCIES_1)





am__objects_295 = lib585-first.$(OBJEXT)
am__objects_296 = lib585-testutil.$(OBJEXT)
am__objects_297 = lib585-testtrace.$(OBJEXT)
am__objects_298 = ../../lib/lib585-curl_multibyte.$(OBJEXT)
am_lib585_OBJECTS = lib585-lib500.$(OBJEXT) $(am__objects_295) \
	$(am__objects_296) $(am__objects_297) $(am__objects_298)
lib585_OBJECTS = $(am_lib585_OBJECTS)
lib585_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_299 = lib586-first.$(OBJEXT)
am_lib586_OBJECTS = lib586-lib586.$(OBJEXT) $(am__objects_299)
lib586_OBJECTS = $(am_lib586_OBJECTS)
lib586_LDADD = $(LDADD)
lib586_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_300 = lib587-first.$(OBJEXT)
am_lib587_OBJECTS = lib587-lib554.$(OBJEXT) $(am__objects_300)
lib587_OBJECTS = $(am_lib587_OBJECTS)
lib587_LDADD = $(LDADD)
lib587_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_301 = lib589-first.$(OBJEXT)
am_lib589_OBJECTS = lib589-lib589.$(OBJEXT) $(am__objects_301)
lib589_OBJECTS = $(am_lib589_OBJECTS)
lib589_LDADD = $(LDADD)
lib589_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_302 = lib590-first.$(OBJEXT)
am_lib590_OBJECTS = lib590-lib590.$(OBJEXT) $(am__objects_302)
lib590_OBJECTS = $(am_lib590_OBJECTS)
lib590_LDADD = $(LDADD)
lib590_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_303 = lib591-first.$(OBJEXT)
am__objects_304 = lib591-testutil.$(OBJEXT)
am__objects_305 = ../../lib/lib591-warnless.$(OBJEXT)
am__objects_306 = ../../lib/lib591-curl_multibyte.$(OBJEXT)
am_lib591_OBJECTS = lib591-lib591.$(OBJEXT) $(am__objects_303) \
	$(am__objects_304) $(am__objects_305) $(am__objects_306)
lib591_OBJECTS = $(am_lib591_OBJECTS)
lib591_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_307 = lib597-first.$(OBJEXT)
am__objects_308 = lib597-testutil.$(OBJEXT)
am__objects_309 = ../../lib/lib597-warnless.$(OBJEXT)
am_lib597_OBJECTS = lib597-lib597.$(OBJEXT) $(am__objects_307) \
	$(am__objects_308) $(am__objects_309)
lib597_OBJECTS = $(am_lib597_OBJECTS)
lib597_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_310 = lib598-first.$(OBJEXT)
am_lib598_OBJECTS = lib598-lib598.$(OBJEXT) $(am__objects_310)
lib598_OBJECTS = $(am_lib598_OBJECTS)
lib598_LDADD = $(LDADD)
lib598_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_311 = lib599-first.$(OBJEXT)
am__objects_312 = ../../lib/lib599-curl_multibyte.$(OBJEXT)
am_lib599_OBJECTS = lib599-lib599.$(OBJEXT) $(am__objects_311) \
	$(am__objects_312)
lib599_OBJECTS = $(am_lib599_OBJECTS)
lib599_LDADD = $(LDADD)
lib599_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_313 = lib643-first.$(OBJEXT)
am_lib643_OBJECTS = lib643-lib643.$(OBJEXT) $(am__objects_313)
lib643_OBJECTS = $(am_lib643_OBJECTS)
lib643_LDADD = $(LDADD)
lib643_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_314 = lib644-first.$(OBJEXT)
am_lib644_OBJECTS = lib644-lib643.$(OBJEXT) $(am__objects_314)
lib644_OBJECTS = $(am_lib644_OBJECTS)
lib644_LDADD = $(LDADD)
lib644_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_315 = lib645-first.$(OBJEXT)
am_lib645_OBJECTS = lib645-lib643.$(OBJEXT) $(am__objects_315)
lib645_OBJECTS = $(am_lib645_OBJECTS)
lib645_LDADD = $(LDADD)
lib645_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_316 = lib650-first.$(OBJEXT)
am_lib650_OBJECTS = lib650-lib650.$(OBJEXT) $(am__objects_316)
lib650_OBJECTS = $(am_lib650_OBJECTS)
lib650_LDADD = $(LDADD)
lib650_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_317 = lib651-first.$(OBJEXT)
am_lib651_OBJECTS = lib651-lib651.$(OBJEXT) $(am__objects_317)
lib651_OBJECTS = $(am_lib651_OBJECTS)
lib651_LDADD = $(LDADD)
lib651_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_318 = lib652-first.$(OBJEXT)
am_lib652_OBJECTS = lib652-lib652.$(OBJEXT) $(am__objects_318)
lib652_OBJECTS = $(am_lib652_OBJECTS)
lib652_LDADD = $(LDADD)
lib652_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_319 = lib653-first.$(OBJEXT)
am_lib653_OBJECTS = lib653-lib653.$(OBJEXT) $(am__objects_319)
lib653_OBJECTS = $(am_lib653_OBJECTS)
lib653_LDADD = $(LDADD)
lib653_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_320 = lib654-first.$(OBJEXT)
am_lib654_OBJECTS = lib654-lib654.$(OBJEXT) $(am__objects_320)
lib654_OBJECTS = $(am_lib654_OBJECTS)
lib654_LDADD = $(LDADD)
lib654_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_321 = lib655-first.$(OBJEXT)
am_lib655_OBJECTS = lib655-lib655.$(OBJEXT) $(am__objects_321)
lib655_OBJECTS = $(am_lib655_OBJECTS)
lib655_LDADD = $(LDADD)
lib655_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_322 = lib658-first.$(OBJEXT)
am__objects_323 = lib658-testutil.$(OBJEXT)
am__objects_324 = ../../lib/lib658-warnless.$(OBJEXT)
am_lib658_OBJECTS = lib658-lib658.$(OBJEXT) $(am__objects_322) \
	$(am__objects_323) $(am__objects_324)
lib658_OBJECTS = $(am_lib658_OBJECTS)
lib658_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_325 = lib659-first.$(OBJEXT)
am__objects_326 = lib659-testutil.$(OBJEXT)
am__objects_327 = ../../lib/lib659-warnless.$(OBJEXT)
am_lib659_OBJECTS = lib659-lib659.$(OBJEXT) $(am__objects_325) \
	$(am__objects_326) $(am__objects_327)
lib659_OBJECTS = $(am_lib659_OBJECTS)
lib659_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_328 = lib661-first.$(OBJEXT)
am_lib661_OBJECTS = lib661-lib661.$(OBJEXT) $(am__objects_328)
lib661_OBJECTS = $(am_lib661_OBJECTS)
lib661_LDADD = $(LDADD)
lib661_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_329 = lib666-first.$(OBJEXT)
am_lib666_OBJECTS = lib666-lib666.$(OBJEXT) $(am__objects_329)
lib666_OBJECTS = $(am_lib666_OBJECTS)
lib666_LDADD = $(LDADD)
lib666_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_330 = lib667-first.$(OBJEXT)
am__objects_331 = lib667-testutil.$(OBJEXT)
am__objects_332 = ../../lib/lib667-warnless.$(OBJEXT)
am_lib667_OBJECTS = lib667-lib667.$(OBJEXT) $(am__objects_330) \
	$(am__objects_331) $(am__objects_332)
lib667_OBJECTS = $(am_lib667_OBJECTS)
lib667_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_333 = lib668-first.$(OBJEXT)
am__objects_334 = lib668-testutil.$(OBJEXT)
am__objects_335 = ../../lib/lib668-warnless.$(OBJEXT)
am_lib668_OBJECTS = lib668-lib668.$(OBJEXT) $(am__objects_333) \
	$(am__objects_334) $(am__objects_335)
lib668_OBJECTS = $(am_lib668_OBJECTS)
lib668_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_336 = lib670-first.$(OBJEXT)
am__objects_337 = lib670-testutil.$(OBJEXT)
am__objects_338 = ../../lib/lib670-warnless.$(OBJEXT)
am_lib670_OBJECTS = lib670-lib670.$(OBJEXT) $(am__objects_336) \
	$(am__objects_337) $(am__objects_338)
lib670_OBJECTS = $(am_lib670_OBJECTS)
lib670_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_339 = lib671-first.$(OBJEXT)
am__objects_340 = lib671-testutil.$(OBJEXT)
am__objects_341 = ../../lib/lib671-warnless.$(OBJEXT)
am_lib671_OBJECTS = lib671-lib670.$(OBJEXT) $(am__objects_339) \
	$(am__objects_340) $(am__objects_341)
lib671_OBJECTS = $(am_lib671_OBJECTS)
lib671_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_342 = lib672-first.$(OBJEXT)
am__objects_343 = lib672-testutil.$(OBJEXT)
am__objects_344 = ../../lib/lib672-warnless.$(OBJEXT)
am_lib672_OBJECTS = lib672-lib670.$(OBJEXT) $(am__objects_342) \
	$(am__objects_343) $(am__objects_344)
lib672_OBJECTS = $(am_lib672_OBJECTS)
lib672_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_345 = lib673-first.$(OBJEXT)
am__objects_346 = lib673-testutil.$(OBJEXT)
am__objects_347 = ../../lib/lib673-warnless.$(OBJEXT)
am_lib673_OBJECTS = lib673-lib670.$(OBJEXT) $(am__objects_345) \
	$(am__objects_346) $(am__objects_347)
lib673_OBJECTS = $(am_lib673_OBJECTS)
lib673_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_348 = lib674-first.$(OBJEXT)
am__objects_349 = lib674-testutil.$(OBJEXT)
am__objects_350 = ../../lib/lib674-warnless.$(OBJEXT)
am_lib674_OBJECTS = lib674-lib674.$(OBJEXT) $(am__objects_348) \
	$(am__objects_349) $(am__objects_350)
lib674_OBJECTS = $(am_lib674_OBJECTS)
lib674_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_351 = libauthretry-first.$(OBJEXT)
am_libauthretry_OBJECTS = libauthretry-libauthretry.$(OBJEXT) \
	$(am__objects_351)
libauthretry_OBJECTS = $(am_libauthretry_OBJECTS)
libauthretry_LDADD = $(LDADD)
libauthretry_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_352 = libntlmconnect-first.$(OBJEXT)
am__objects_353 = libntlmconnect-testutil.$(OBJEXT)
am__objects_354 = ../../lib/libntlmconnect-warnless.$(OBJEXT)
am_libntlmconnect_OBJECTS = libntlmconnect-libntlmconnect.$(OBJEXT) \
	$(am__objects_352) $(am__objects_353) $(am__objects_354)
libntlmconnect_OBJECTS = $(am_libntlmconnect_OBJECTS)
libntlmconnect_DEPENDENCIES = $(am__DEPENDENCIES_1)
AM_V_P = $(am__v_P_@AM_V@)
am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
am__v_P_0 = false
am__v_P_1 = :
AM_V_GEN = $(am__v_GEN_@AM_V@)







>
>
|
>

<

|
|



|
|
|
|
|


|
|
|
|
|


|
|
|
|
|


|
|
|
|
|


|
|
|
|
|


|
|
|
|
|


|
|
|
|
|


|
|
|
|
|


|
|
|
|
|


|
|
|
|
|


|
|
|
|
|


|
|
|
|
|


|
|
|
|
|


|
|
|
|
|


|
|
|
|
|


|
|
|
|
|


|
|



|
|



|
|
|
|


|
|
|
|


|
|



|
|
|
|
|


|
|
|
|
|


|
|
|
|
|


|
|
|
|
|


|
|


|
|


|
|
|
|
|


|
|
|
|
|


|
|



>
>
>
>
>
|
|
|
|
|


|
|
|
|
|


|
|


|
|


|
|
|
|
|


|
|
|
|
|


|
|
|
|
|


|
|
|
|
|


|
|
|
|
|


|
|
|
|
|


|
|
|
|
|


|
|
|
|
|


|
|
|
|
|


|
|
|
|
|


>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
|
|
|
|


|
|
|
|
|
|


|
|



|
|
|
|
|


|
|
|
|
|


|
|
|
|
|


|
|
|
|



|
|



|
|
|
|
|


|
|



|
|



|
|



|
|



|
|



|
|



|
|



|
|



|
|



|
|



|
|
|
|
|



|
|



|
|



|
|



|
|



|
|



|
|
|
|
|
|


|
|
|
|
|


|
|
|
|
|


|
|
|
|
|
|


|
|
|
|
|


|
|
|
|
|


|
|
|
|
|



|
|



|
|
|
|
|


|
|
|
|



|
|



|
|



|
|



|
|



|
|



|
|



|
|



|
|
|
|



|
|



|
|



|
|
|
|
|


|
|
|
|



|
|



|
|



|
|



|
|
|
|
|


|
|



|
|
|
|
|


|
|



|
|
|
|



|
|



|
|
|
|



|
|
|
|



|
|



|
|
|
|
|



|
|
|
|



|
|
|
|
|
|


|
|



|
|
|
|
|


|
|



|
|
|
|



|
|
|
|



|
|
|
|
|
|


|
|



>
>
>
>
>
|
|
|
|
|
|


|
|



|
|



|
|



|
|



|
|
|
|
|
|


|
|
|
|
|


|
|



|
|
|
|



|
|



|
|



|
|



|
|



|
|



|
|



|
|



|
|



|
|



|
|
|
|
|


|
|
|
|
|


|
|



|
|



|
|
|
|
|


|
|
|
|
|


|
|
|
|
|


|
|
|
|
|


|
|
|
|
|


|
|
|
|
|


|
|
|
|
|


|

|



|
|
|

|







359
360
361
362
363
364
365
366
367
368
369
370

371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
lib1520_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_54 = lib1521-first.$(OBJEXT)
nodist_lib1521_OBJECTS = lib1521-lib1521.$(OBJEXT) $(am__objects_54)
lib1521_OBJECTS = $(nodist_lib1521_OBJECTS)
lib1521_LDADD = $(LDADD)
lib1521_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_55 = lib1522-first.$(OBJEXT)
am__objects_56 = lib1522-testutil.$(OBJEXT)
am__objects_57 = lib1522-testtrace.$(OBJEXT)
am_lib1522_OBJECTS = lib1522-lib1522.$(OBJEXT) $(am__objects_55) \
	$(am__objects_56) $(am__objects_57)
lib1522_OBJECTS = $(am_lib1522_OBJECTS)

lib1522_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_58 = lib1523-first.$(OBJEXT)
am_lib1523_OBJECTS = lib1523-lib1523.$(OBJEXT) $(am__objects_58)
lib1523_OBJECTS = $(am_lib1523_OBJECTS)
lib1523_LDADD = $(LDADD)
lib1523_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_59 = lib1525-first.$(OBJEXT)
am__objects_60 = lib1525-testutil.$(OBJEXT)
am__objects_61 = ../../lib/lib1525-warnless.$(OBJEXT)
am_lib1525_OBJECTS = lib1525-lib1525.$(OBJEXT) $(am__objects_59) \
	$(am__objects_60) $(am__objects_61)
lib1525_OBJECTS = $(am_lib1525_OBJECTS)
lib1525_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_62 = lib1526-first.$(OBJEXT)
am__objects_63 = lib1526-testutil.$(OBJEXT)
am__objects_64 = ../../lib/lib1526-warnless.$(OBJEXT)
am_lib1526_OBJECTS = lib1526-lib1526.$(OBJEXT) $(am__objects_62) \
	$(am__objects_63) $(am__objects_64)
lib1526_OBJECTS = $(am_lib1526_OBJECTS)
lib1526_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_65 = lib1527-first.$(OBJEXT)
am__objects_66 = lib1527-testutil.$(OBJEXT)
am__objects_67 = ../../lib/lib1527-warnless.$(OBJEXT)
am_lib1527_OBJECTS = lib1527-lib1527.$(OBJEXT) $(am__objects_65) \
	$(am__objects_66) $(am__objects_67)
lib1527_OBJECTS = $(am_lib1527_OBJECTS)
lib1527_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_68 = lib1528-first.$(OBJEXT)
am__objects_69 = lib1528-testutil.$(OBJEXT)
am__objects_70 = ../../lib/lib1528-warnless.$(OBJEXT)
am_lib1528_OBJECTS = lib1528-lib1528.$(OBJEXT) $(am__objects_68) \
	$(am__objects_69) $(am__objects_70)
lib1528_OBJECTS = $(am_lib1528_OBJECTS)
lib1528_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_71 = lib1529-first.$(OBJEXT)
am__objects_72 = lib1529-testutil.$(OBJEXT)
am__objects_73 = ../../lib/lib1529-warnless.$(OBJEXT)
am_lib1529_OBJECTS = lib1529-lib1529.$(OBJEXT) $(am__objects_71) \
	$(am__objects_72) $(am__objects_73)
lib1529_OBJECTS = $(am_lib1529_OBJECTS)
lib1529_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_74 = lib1530-first.$(OBJEXT)
am__objects_75 = lib1530-testutil.$(OBJEXT)
am__objects_76 = ../../lib/lib1530-warnless.$(OBJEXT)
am_lib1530_OBJECTS = lib1530-lib1530.$(OBJEXT) $(am__objects_74) \
	$(am__objects_75) $(am__objects_76)
lib1530_OBJECTS = $(am_lib1530_OBJECTS)
lib1530_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_77 = lib1531-first.$(OBJEXT)
am__objects_78 = lib1531-testutil.$(OBJEXT)
am__objects_79 = ../../lib/lib1531-warnless.$(OBJEXT)
am_lib1531_OBJECTS = lib1531-lib1531.$(OBJEXT) $(am__objects_77) \
	$(am__objects_78) $(am__objects_79)
lib1531_OBJECTS = $(am_lib1531_OBJECTS)
lib1531_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_80 = lib1532-first.$(OBJEXT)
am__objects_81 = lib1532-testutil.$(OBJEXT)
am__objects_82 = ../../lib/lib1532-warnless.$(OBJEXT)
am_lib1532_OBJECTS = lib1532-lib1532.$(OBJEXT) $(am__objects_80) \
	$(am__objects_81) $(am__objects_82)
lib1532_OBJECTS = $(am_lib1532_OBJECTS)
lib1532_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_83 = lib1533-first.$(OBJEXT)
am__objects_84 = lib1533-testutil.$(OBJEXT)
am__objects_85 = ../../lib/lib1533-warnless.$(OBJEXT)
am_lib1533_OBJECTS = lib1533-lib1533.$(OBJEXT) $(am__objects_83) \
	$(am__objects_84) $(am__objects_85)
lib1533_OBJECTS = $(am_lib1533_OBJECTS)
lib1533_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_86 = lib1534-first.$(OBJEXT)
am__objects_87 = lib1534-testutil.$(OBJEXT)
am__objects_88 = ../../lib/lib1534-warnless.$(OBJEXT)
am_lib1534_OBJECTS = lib1534-lib1534.$(OBJEXT) $(am__objects_86) \
	$(am__objects_87) $(am__objects_88)
lib1534_OBJECTS = $(am_lib1534_OBJECTS)
lib1534_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_89 = lib1535-first.$(OBJEXT)
am__objects_90 = lib1535-testutil.$(OBJEXT)
am__objects_91 = ../../lib/lib1535-warnless.$(OBJEXT)
am_lib1535_OBJECTS = lib1535-lib1535.$(OBJEXT) $(am__objects_89) \
	$(am__objects_90) $(am__objects_91)
lib1535_OBJECTS = $(am_lib1535_OBJECTS)
lib1535_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_92 = lib1536-first.$(OBJEXT)
am__objects_93 = lib1536-testutil.$(OBJEXT)
am__objects_94 = ../../lib/lib1536-warnless.$(OBJEXT)
am_lib1536_OBJECTS = lib1536-lib1536.$(OBJEXT) $(am__objects_92) \
	$(am__objects_93) $(am__objects_94)
lib1536_OBJECTS = $(am_lib1536_OBJECTS)
lib1536_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_95 = lib1537-first.$(OBJEXT)
am__objects_96 = lib1537-testutil.$(OBJEXT)
am__objects_97 = ../../lib/lib1537-warnless.$(OBJEXT)
am_lib1537_OBJECTS = lib1537-lib1537.$(OBJEXT) $(am__objects_95) \
	$(am__objects_96) $(am__objects_97)
lib1537_OBJECTS = $(am_lib1537_OBJECTS)
lib1537_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_98 = lib1538-first.$(OBJEXT)
am__objects_99 = lib1538-testutil.$(OBJEXT)
am__objects_100 = ../../lib/lib1538-warnless.$(OBJEXT)
am_lib1538_OBJECTS = lib1538-lib1538.$(OBJEXT) $(am__objects_98) \
	$(am__objects_99) $(am__objects_100)
lib1538_OBJECTS = $(am_lib1538_OBJECTS)
lib1538_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_101 = lib1539-first.$(OBJEXT)
am__objects_102 = lib1539-testutil.$(OBJEXT)
am__objects_103 = ../../lib/lib1539-warnless.$(OBJEXT)
am_lib1539_OBJECTS = lib1539-lib1514.$(OBJEXT) $(am__objects_101) \
	$(am__objects_102) $(am__objects_103)
lib1539_OBJECTS = $(am_lib1539_OBJECTS)
lib1539_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_104 = lib1540-first.$(OBJEXT)
am__objects_105 = lib1540-testutil.$(OBJEXT)
am__objects_106 = ../../lib/lib1540-warnless.$(OBJEXT)
am_lib1540_OBJECTS = lib1540-lib1540.$(OBJEXT) $(am__objects_104) \
	$(am__objects_105) $(am__objects_106)
lib1540_OBJECTS = $(am_lib1540_OBJECTS)
lib1540_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_107 = lib1550-first.$(OBJEXT)
am_lib1550_OBJECTS = lib1550-lib1550.$(OBJEXT) $(am__objects_107)
lib1550_OBJECTS = $(am_lib1550_OBJECTS)
lib1550_LDADD = $(LDADD)
lib1550_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_108 = lib1551-first.$(OBJEXT)
am_lib1551_OBJECTS = lib1551-lib1551.$(OBJEXT) $(am__objects_108)
lib1551_OBJECTS = $(am_lib1551_OBJECTS)
lib1551_LDADD = $(LDADD)
lib1551_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_109 = lib1552-first.$(OBJEXT)
am__objects_110 = lib1552-testutil.$(OBJEXT)
am_lib1552_OBJECTS = lib1552-lib1552.$(OBJEXT) $(am__objects_109) \
	$(am__objects_110)
lib1552_OBJECTS = $(am_lib1552_OBJECTS)
lib1552_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_111 = lib1553-first.$(OBJEXT)
am__objects_112 = lib1553-testutil.$(OBJEXT)
am_lib1553_OBJECTS = lib1553-lib1553.$(OBJEXT) $(am__objects_111) \
	$(am__objects_112)
lib1553_OBJECTS = $(am_lib1553_OBJECTS)
lib1553_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_113 = lib1554-first.$(OBJEXT)
am_lib1554_OBJECTS = lib1554-lib1554.$(OBJEXT) $(am__objects_113)
lib1554_OBJECTS = $(am_lib1554_OBJECTS)
lib1554_LDADD = $(LDADD)
lib1554_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_114 = lib1555-first.$(OBJEXT)
am__objects_115 = lib1555-testutil.$(OBJEXT)
am__objects_116 = ../../lib/lib1555-warnless.$(OBJEXT)
am_lib1555_OBJECTS = lib1555-lib1555.$(OBJEXT) $(am__objects_114) \
	$(am__objects_115) $(am__objects_116)
lib1555_OBJECTS = $(am_lib1555_OBJECTS)
lib1555_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_117 = lib1556-first.$(OBJEXT)
am__objects_118 = lib1556-testutil.$(OBJEXT)
am__objects_119 = ../../lib/lib1556-warnless.$(OBJEXT)
am_lib1556_OBJECTS = lib1556-lib1556.$(OBJEXT) $(am__objects_117) \
	$(am__objects_118) $(am__objects_119)
lib1556_OBJECTS = $(am_lib1556_OBJECTS)
lib1556_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_120 = lib1557-first.$(OBJEXT)
am__objects_121 = lib1557-testutil.$(OBJEXT)
am__objects_122 = ../../lib/lib1557-warnless.$(OBJEXT)
am_lib1557_OBJECTS = lib1557-lib1557.$(OBJEXT) $(am__objects_120) \
	$(am__objects_121) $(am__objects_122)
lib1557_OBJECTS = $(am_lib1557_OBJECTS)
lib1557_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_123 = first.$(OBJEXT)
am__objects_124 = testutil.$(OBJEXT)
am__objects_125 = ../../lib/warnless.$(OBJEXT)
am_lib1558_OBJECTS = lib1558.$(OBJEXT) $(am__objects_123) \
	$(am__objects_124) $(am__objects_125)
lib1558_OBJECTS = $(am_lib1558_OBJECTS)
lib1558_DEPENDENCIES = $(am__DEPENDENCIES_1)
am_lib1559_OBJECTS = lib1559.$(OBJEXT) $(am__objects_123) \
	$(am__objects_124) $(am__objects_125)
lib1559_OBJECTS = $(am_lib1559_OBJECTS)
lib1559_DEPENDENCIES = $(am__DEPENDENCIES_1)
am_lib1560_OBJECTS = lib1560.$(OBJEXT) $(am__objects_123) \
	$(am__objects_124) $(am__objects_125)
lib1560_OBJECTS = $(am_lib1560_OBJECTS)
lib1560_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_126 = lib1564-first.$(OBJEXT)
am__objects_127 = lib1564-testutil.$(OBJEXT)
am__objects_128 = ../../lib/lib1564-warnless.$(OBJEXT)
am_lib1564_OBJECTS = lib1564-lib1564.$(OBJEXT) $(am__objects_126) \
	$(am__objects_127) $(am__objects_128)
lib1564_OBJECTS = $(am_lib1564_OBJECTS)
lib1564_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_129 = lib1565-first.$(OBJEXT)
am__objects_130 = lib1565-testutil.$(OBJEXT)
am__objects_131 = ../../lib/lib1565-warnless.$(OBJEXT)
am_lib1565_OBJECTS = lib1565-lib1565.$(OBJEXT) $(am__objects_129) \
	$(am__objects_130) $(am__objects_131)
lib1565_OBJECTS = $(am_lib1565_OBJECTS)
lib1565_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_132 = lib1567-first.$(OBJEXT)
am_lib1567_OBJECTS = lib1567-lib1567.$(OBJEXT) $(am__objects_132)
lib1567_OBJECTS = $(am_lib1567_OBJECTS)
lib1567_LDADD = $(LDADD)
lib1567_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_133 = lib1568-first.$(OBJEXT)
am_lib1568_OBJECTS = lib1568-lib1568.$(OBJEXT) $(am__objects_133)
lib1568_OBJECTS = $(am_lib1568_OBJECTS)
lib1568_LDADD = $(LDADD)
lib1568_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_134 = lib1591-first.$(OBJEXT)
am__objects_135 = lib1591-testutil.$(OBJEXT)
am__objects_136 = ../../lib/lib1591-warnless.$(OBJEXT)
am_lib1591_OBJECTS = lib1591-lib1591.$(OBJEXT) $(am__objects_134) \
	$(am__objects_135) $(am__objects_136)
lib1591_OBJECTS = $(am_lib1591_OBJECTS)
lib1591_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_137 = lib1592-first.$(OBJEXT)
am__objects_138 = lib1592-testutil.$(OBJEXT)
am__objects_139 = ../../lib/lib1592-warnless.$(OBJEXT)
am_lib1592_OBJECTS = lib1592-lib1592.$(OBJEXT) $(am__objects_137) \
	$(am__objects_138) $(am__objects_139)
lib1592_OBJECTS = $(am_lib1592_OBJECTS)
lib1592_DEPENDENCIES = $(am__DEPENDENCIES_1)
am_lib1593_OBJECTS = lib1593.$(OBJEXT) $(am__objects_123) \
	$(am__objects_124) $(am__objects_125)
lib1593_OBJECTS = $(am_lib1593_OBJECTS)
lib1593_DEPENDENCIES = $(am__DEPENDENCIES_1)
am_lib1594_OBJECTS = lib1594.$(OBJEXT) $(am__objects_123) \
	$(am__objects_124) $(am__objects_125)
lib1594_OBJECTS = $(am_lib1594_OBJECTS)
lib1594_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_140 = lib1596-first.$(OBJEXT)
am__objects_141 = lib1596-testutil.$(OBJEXT)
am__objects_142 = ../../lib/lib1596-warnless.$(OBJEXT)
am_lib1596_OBJECTS = lib1596-lib1594.$(OBJEXT) $(am__objects_140) \
	$(am__objects_141) $(am__objects_142)
lib1596_OBJECTS = $(am_lib1596_OBJECTS)
lib1596_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_143 = lib1905-first.$(OBJEXT)
am__objects_144 = lib1905-testutil.$(OBJEXT)
am__objects_145 = ../../lib/lib1905-warnless.$(OBJEXT)
am_lib1905_OBJECTS = lib1905-lib1905.$(OBJEXT) $(am__objects_143) \
	$(am__objects_144) $(am__objects_145)
lib1905_OBJECTS = $(am_lib1905_OBJECTS)
lib1905_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_146 = lib1906-first.$(OBJEXT)
am__objects_147 = lib1906-testutil.$(OBJEXT)
am__objects_148 = ../../lib/lib1906-warnless.$(OBJEXT)
am_lib1906_OBJECTS = lib1906-lib1906.$(OBJEXT) $(am__objects_146) \
	$(am__objects_147) $(am__objects_148)
lib1906_OBJECTS = $(am_lib1906_OBJECTS)
lib1906_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_149 = lib1907-first.$(OBJEXT)
am__objects_150 = lib1907-testutil.$(OBJEXT)
am__objects_151 = ../../lib/lib1907-warnless.$(OBJEXT)
am_lib1907_OBJECTS = lib1907-lib1907.$(OBJEXT) $(am__objects_149) \
	$(am__objects_150) $(am__objects_151)
lib1907_OBJECTS = $(am_lib1907_OBJECTS)
lib1907_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_152 = lib1908-first.$(OBJEXT)
am__objects_153 = lib1908-testutil.$(OBJEXT)
am__objects_154 = ../../lib/lib1908-warnless.$(OBJEXT)
am_lib1908_OBJECTS = lib1908-lib1908.$(OBJEXT) $(am__objects_152) \
	$(am__objects_153) $(am__objects_154)
lib1908_OBJECTS = $(am_lib1908_OBJECTS)
lib1908_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_155 = lib1910-first.$(OBJEXT)
am__objects_156 = lib1910-testutil.$(OBJEXT)
am__objects_157 = ../../lib/lib1910-warnless.$(OBJEXT)
am_lib1910_OBJECTS = lib1910-lib1910.$(OBJEXT) $(am__objects_155) \
	$(am__objects_156) $(am__objects_157)
lib1910_OBJECTS = $(am_lib1910_OBJECTS)
lib1910_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_158 = lib1911-first.$(OBJEXT)
am__objects_159 = lib1911-testutil.$(OBJEXT)
am__objects_160 = ../../lib/lib1911-warnless.$(OBJEXT)
am_lib1911_OBJECTS = lib1911-lib1911.$(OBJEXT) $(am__objects_158) \
	$(am__objects_159) $(am__objects_160)
lib1911_OBJECTS = $(am_lib1911_OBJECTS)
lib1911_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_161 = lib1912-first.$(OBJEXT)
am__objects_162 = lib1912-testutil.$(OBJEXT)
am__objects_163 = ../../lib/lib1912-warnless.$(OBJEXT)
am_lib1912_OBJECTS = lib1912-lib1912.$(OBJEXT) $(am__objects_161) \
	$(am__objects_162) $(am__objects_163)
lib1912_OBJECTS = $(am_lib1912_OBJECTS)
lib1912_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_164 = lib1913-first.$(OBJEXT)
am__objects_165 = lib1913-testutil.$(OBJEXT)
am__objects_166 = ../../lib/lib1913-warnless.$(OBJEXT)
am_lib1913_OBJECTS = lib1913-lib1913.$(OBJEXT) $(am__objects_164) \
	$(am__objects_165) $(am__objects_166)
lib1913_OBJECTS = $(am_lib1913_OBJECTS)
lib1913_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_167 = lib1915-first.$(OBJEXT)
am__objects_168 = lib1915-testutil.$(OBJEXT)
am__objects_169 = ../../lib/lib1915-warnless.$(OBJEXT)
am_lib1915_OBJECTS = lib1915-lib1915.$(OBJEXT) $(am__objects_167) \
	$(am__objects_168) $(am__objects_169)
lib1915_OBJECTS = $(am_lib1915_OBJECTS)
lib1915_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_170 = lib1916-first.$(OBJEXT)
am__objects_171 = ../../lib/lib1916-warnless.$(OBJEXT)
am_lib1916_OBJECTS = lib1916-lib1916.$(OBJEXT) $(am__objects_170) \
	$(am__objects_171)
lib1916_OBJECTS = $(am_lib1916_OBJECTS)
lib1916_LDADD = $(LDADD)
lib1916_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_172 = lib1917-first.$(OBJEXT)
am__objects_173 = ../../lib/lib1917-warnless.$(OBJEXT)
am_lib1917_OBJECTS = lib1917-lib1916.$(OBJEXT) $(am__objects_172) \
	$(am__objects_173)
lib1917_OBJECTS = $(am_lib1917_OBJECTS)
lib1917_LDADD = $(LDADD)
lib1917_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_174 = lib1918-first.$(OBJEXT)
am__objects_175 = ../../lib/lib1918-warnless.$(OBJEXT)
am_lib1918_OBJECTS = lib1918-lib1918.$(OBJEXT) $(am__objects_174) \
	$(am__objects_175)
lib1918_OBJECTS = $(am_lib1918_OBJECTS)
lib1918_LDADD = $(LDADD)
lib1918_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_176 = lib1933-first.$(OBJEXT)
am__objects_177 = lib1933-testutil.$(OBJEXT)
am__objects_178 = ../../lib/lib1933-warnless.$(OBJEXT)
am_lib1933_OBJECTS = lib1933-lib1933.$(OBJEXT) $(am__objects_176) \
	$(am__objects_177) $(am__objects_178)
lib1933_OBJECTS = $(am_lib1933_OBJECTS)
lib1933_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_179 = lib1934-first.$(OBJEXT)
am__objects_180 = lib1934-testutil.$(OBJEXT)
am__objects_181 = ../../lib/lib1934-warnless.$(OBJEXT)
am_lib1934_OBJECTS = lib1934-lib1934.$(OBJEXT) $(am__objects_179) \
	$(am__objects_180) $(am__objects_181)
lib1934_OBJECTS = $(am_lib1934_OBJECTS)
lib1934_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_182 = lib1935-first.$(OBJEXT)
am__objects_183 = lib1935-testutil.$(OBJEXT)
am__objects_184 = ../../lib/lib1935-warnless.$(OBJEXT)
am_lib1935_OBJECTS = lib1935-lib1935.$(OBJEXT) $(am__objects_182) \
	$(am__objects_183) $(am__objects_184)
lib1935_OBJECTS = $(am_lib1935_OBJECTS)
lib1935_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_185 = lib1936-first.$(OBJEXT)
am__objects_186 = lib1936-testutil.$(OBJEXT)
am__objects_187 = ../../lib/lib1936-warnless.$(OBJEXT)
am_lib1936_OBJECTS = lib1936-lib1936.$(OBJEXT) $(am__objects_185) \
	$(am__objects_186) $(am__objects_187)
lib1936_OBJECTS = $(am_lib1936_OBJECTS)
lib1936_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_188 = lib3010-first.$(OBJEXT)
am__objects_189 = lib3010-testutil.$(OBJEXT)
am__objects_190 = ../../lib/lib3010-warnless.$(OBJEXT)
am_lib3010_OBJECTS = lib3010-lib3010.$(OBJEXT) $(am__objects_188) \
	$(am__objects_189) $(am__objects_190)
lib3010_OBJECTS = $(am_lib3010_OBJECTS)
lib3010_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_191 = lib500-first.$(OBJEXT)
am__objects_192 = lib500-testutil.$(OBJEXT)
am__objects_193 = lib500-testtrace.$(OBJEXT)
am__objects_194 = ../../lib/lib500-curl_multibyte.$(OBJEXT)
am_lib500_OBJECTS = lib500-lib500.$(OBJEXT) $(am__objects_191) \
	$(am__objects_192) $(am__objects_193) $(am__objects_194)
lib500_OBJECTS = $(am_lib500_OBJECTS)
lib500_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_195 = lib501-first.$(OBJEXT)
am_lib501_OBJECTS = lib501-lib501.$(OBJEXT) $(am__objects_195)
lib501_OBJECTS = $(am_lib501_OBJECTS)
lib501_LDADD = $(LDADD)
lib501_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_196 = lib502-first.$(OBJEXT)
am__objects_197 = lib502-testutil.$(OBJEXT)
am__objects_198 = ../../lib/lib502-warnless.$(OBJEXT)
am_lib502_OBJECTS = lib502-lib502.$(OBJEXT) $(am__objects_196) \
	$(am__objects_197) $(am__objects_198)
lib502_OBJECTS = $(am_lib502_OBJECTS)
lib502_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_199 = lib503-first.$(OBJEXT)
am__objects_200 = lib503-testutil.$(OBJEXT)
am__objects_201 = ../../lib/lib503-warnless.$(OBJEXT)
am_lib503_OBJECTS = lib503-lib503.$(OBJEXT) $(am__objects_199) \
	$(am__objects_200) $(am__objects_201)
lib503_OBJECTS = $(am_lib503_OBJECTS)
lib503_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_202 = lib504-first.$(OBJEXT)
am__objects_203 = lib504-testutil.$(OBJEXT)
am__objects_204 = ../../lib/lib504-warnless.$(OBJEXT)
am_lib504_OBJECTS = lib504-lib504.$(OBJEXT) $(am__objects_202) \
	$(am__objects_203) $(am__objects_204)
lib504_OBJECTS = $(am_lib504_OBJECTS)
lib504_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_205 = lib505-first.$(OBJEXT)
am__objects_206 = ../../lib/lib505-curl_multibyte.$(OBJEXT)
am_lib505_OBJECTS = lib505-lib505.$(OBJEXT) $(am__objects_205) \
	$(am__objects_206)
lib505_OBJECTS = $(am_lib505_OBJECTS)
lib505_LDADD = $(LDADD)
lib505_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_207 = lib506-first.$(OBJEXT)
am_lib506_OBJECTS = lib506-lib506.$(OBJEXT) $(am__objects_207)
lib506_OBJECTS = $(am_lib506_OBJECTS)
lib506_LDADD = $(LDADD)
lib506_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_208 = lib507-first.$(OBJEXT)
am__objects_209 = lib507-testutil.$(OBJEXT)
am__objects_210 = ../../lib/lib507-warnless.$(OBJEXT)
am_lib507_OBJECTS = lib507-lib507.$(OBJEXT) $(am__objects_208) \
	$(am__objects_209) $(am__objects_210)
lib507_OBJECTS = $(am_lib507_OBJECTS)
lib507_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_211 = lib508-first.$(OBJEXT)
am_lib508_OBJECTS = lib508-lib508.$(OBJEXT) $(am__objects_211)
lib508_OBJECTS = $(am_lib508_OBJECTS)
lib508_LDADD = $(LDADD)
lib508_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_212 = lib509-first.$(OBJEXT)
am_lib509_OBJECTS = lib509-lib509.$(OBJEXT) $(am__objects_212)
lib509_OBJECTS = $(am_lib509_OBJECTS)
lib509_LDADD = $(LDADD)
lib509_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_213 = lib510-first.$(OBJEXT)
am_lib510_OBJECTS = lib510-lib510.$(OBJEXT) $(am__objects_213)
lib510_OBJECTS = $(am_lib510_OBJECTS)
lib510_LDADD = $(LDADD)
lib510_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_214 = lib511-first.$(OBJEXT)
am_lib511_OBJECTS = lib511-lib511.$(OBJEXT) $(am__objects_214)
lib511_OBJECTS = $(am_lib511_OBJECTS)
lib511_LDADD = $(LDADD)
lib511_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_215 = lib512-first.$(OBJEXT)
am_lib512_OBJECTS = lib512-lib512.$(OBJEXT) $(am__objects_215)
lib512_OBJECTS = $(am_lib512_OBJECTS)
lib512_LDADD = $(LDADD)
lib512_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_216 = lib513-first.$(OBJEXT)
am_lib513_OBJECTS = lib513-lib513.$(OBJEXT) $(am__objects_216)
lib513_OBJECTS = $(am_lib513_OBJECTS)
lib513_LDADD = $(LDADD)
lib513_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_217 = lib514-first.$(OBJEXT)
am_lib514_OBJECTS = lib514-lib514.$(OBJEXT) $(am__objects_217)
lib514_OBJECTS = $(am_lib514_OBJECTS)
lib514_LDADD = $(LDADD)
lib514_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_218 = lib515-first.$(OBJEXT)
am_lib515_OBJECTS = lib515-lib515.$(OBJEXT) $(am__objects_218)
lib515_OBJECTS = $(am_lib515_OBJECTS)
lib515_LDADD = $(LDADD)
lib515_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_219 = lib516-first.$(OBJEXT)
am_lib516_OBJECTS = lib516-lib516.$(OBJEXT) $(am__objects_219)
lib516_OBJECTS = $(am_lib516_OBJECTS)
lib516_LDADD = $(LDADD)
lib516_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_220 = lib517-first.$(OBJEXT)
am_lib517_OBJECTS = lib517-lib517.$(OBJEXT) $(am__objects_220)
lib517_OBJECTS = $(am_lib517_OBJECTS)
lib517_LDADD = $(LDADD)
lib517_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_221 = lib518-first.$(OBJEXT)
am__objects_222 = ../../lib/lib518-warnless.$(OBJEXT)
am__objects_223 = ../../lib/lib518-curl_multibyte.$(OBJEXT)
am_lib518_OBJECTS = lib518-lib518.$(OBJEXT) $(am__objects_221) \
	$(am__objects_222) $(am__objects_223)
lib518_OBJECTS = $(am_lib518_OBJECTS)
lib518_LDADD = $(LDADD)
lib518_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_224 = lib519-first.$(OBJEXT)
am_lib519_OBJECTS = lib519-lib519.$(OBJEXT) $(am__objects_224)
lib519_OBJECTS = $(am_lib519_OBJECTS)
lib519_LDADD = $(LDADD)
lib519_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_225 = lib520-first.$(OBJEXT)
am_lib520_OBJECTS = lib520-lib520.$(OBJEXT) $(am__objects_225)
lib520_OBJECTS = $(am_lib520_OBJECTS)
lib520_LDADD = $(LDADD)
lib520_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_226 = lib521-first.$(OBJEXT)
am_lib521_OBJECTS = lib521-lib521.$(OBJEXT) $(am__objects_226)
lib521_OBJECTS = $(am_lib521_OBJECTS)
lib521_LDADD = $(LDADD)
lib521_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_227 = lib523-first.$(OBJEXT)
am_lib523_OBJECTS = lib523-lib523.$(OBJEXT) $(am__objects_227)
lib523_OBJECTS = $(am_lib523_OBJECTS)
lib523_LDADD = $(LDADD)
lib523_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_228 = lib524-first.$(OBJEXT)
am_lib524_OBJECTS = lib524-lib524.$(OBJEXT) $(am__objects_228)
lib524_OBJECTS = $(am_lib524_OBJECTS)
lib524_LDADD = $(LDADD)
lib524_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_229 = lib525-first.$(OBJEXT)
am__objects_230 = lib525-testutil.$(OBJEXT)
am__objects_231 = ../../lib/lib525-warnless.$(OBJEXT)
am__objects_232 = ../../lib/lib525-curl_multibyte.$(OBJEXT)
am_lib525_OBJECTS = lib525-lib525.$(OBJEXT) $(am__objects_229) \
	$(am__objects_230) $(am__objects_231) $(am__objects_232)
lib525_OBJECTS = $(am_lib525_OBJECTS)
lib525_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_233 = lib526-first.$(OBJEXT)
am__objects_234 = lib526-testutil.$(OBJEXT)
am__objects_235 = ../../lib/lib526-warnless.$(OBJEXT)
am_lib526_OBJECTS = lib526-lib526.$(OBJEXT) $(am__objects_233) \
	$(am__objects_234) $(am__objects_235)
lib526_OBJECTS = $(am_lib526_OBJECTS)
lib526_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_236 = lib527-first.$(OBJEXT)
am__objects_237 = lib527-testutil.$(OBJEXT)
am__objects_238 = ../../lib/lib527-warnless.$(OBJEXT)
am_lib527_OBJECTS = lib527-lib526.$(OBJEXT) $(am__objects_236) \
	$(am__objects_237) $(am__objects_238)
lib527_OBJECTS = $(am_lib527_OBJECTS)
lib527_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_239 = lib529-first.$(OBJEXT)
am__objects_240 = lib529-testutil.$(OBJEXT)
am__objects_241 = ../../lib/lib529-warnless.$(OBJEXT)
am__objects_242 = ../../lib/lib529-curl_multibyte.$(OBJEXT)
am_lib529_OBJECTS = lib529-lib525.$(OBJEXT) $(am__objects_239) \
	$(am__objects_240) $(am__objects_241) $(am__objects_242)
lib529_OBJECTS = $(am_lib529_OBJECTS)
lib529_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_243 = lib532-first.$(OBJEXT)
am__objects_244 = lib532-testutil.$(OBJEXT)
am__objects_245 = ../../lib/lib532-warnless.$(OBJEXT)
am_lib532_OBJECTS = lib532-lib526.$(OBJEXT) $(am__objects_243) \
	$(am__objects_244) $(am__objects_245)
lib532_OBJECTS = $(am_lib532_OBJECTS)
lib532_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_246 = lib533-first.$(OBJEXT)
am__objects_247 = lib533-testutil.$(OBJEXT)
am__objects_248 = ../../lib/lib533-warnless.$(OBJEXT)
am_lib533_OBJECTS = lib533-lib533.$(OBJEXT) $(am__objects_246) \
	$(am__objects_247) $(am__objects_248)
lib533_OBJECTS = $(am_lib533_OBJECTS)
lib533_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_249 = lib537-first.$(OBJEXT)
am__objects_250 = ../../lib/lib537-warnless.$(OBJEXT)
am__objects_251 = ../../lib/lib537-curl_multibyte.$(OBJEXT)
am_lib537_OBJECTS = lib537-lib537.$(OBJEXT) $(am__objects_249) \
	$(am__objects_250) $(am__objects_251)
lib537_OBJECTS = $(am_lib537_OBJECTS)
lib537_LDADD = $(LDADD)
lib537_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_252 = lib539-first.$(OBJEXT)
am_lib539_OBJECTS = lib539-lib539.$(OBJEXT) $(am__objects_252)
lib539_OBJECTS = $(am_lib539_OBJECTS)
lib539_LDADD = $(LDADD)
lib539_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_253 = lib540-first.$(OBJEXT)
am__objects_254 = lib540-testutil.$(OBJEXT)
am__objects_255 = ../../lib/lib540-warnless.$(OBJEXT)
am_lib540_OBJECTS = lib540-lib540.$(OBJEXT) $(am__objects_253) \
	$(am__objects_254) $(am__objects_255)
lib540_OBJECTS = $(am_lib540_OBJECTS)
lib540_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_256 = lib541-first.$(OBJEXT)
am__objects_257 = ../../lib/lib541-curl_multibyte.$(OBJEXT)
am_lib541_OBJECTS = lib541-lib541.$(OBJEXT) $(am__objects_256) \
	$(am__objects_257)
lib541_OBJECTS = $(am_lib541_OBJECTS)
lib541_LDADD = $(LDADD)
lib541_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_258 = lib542-first.$(OBJEXT)
am_lib542_OBJECTS = lib542-lib542.$(OBJEXT) $(am__objects_258)
lib542_OBJECTS = $(am_lib542_OBJECTS)
lib542_LDADD = $(LDADD)
lib542_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_259 = lib543-first.$(OBJEXT)
am_lib543_OBJECTS = lib543-lib543.$(OBJEXT) $(am__objects_259)
lib543_OBJECTS = $(am_lib543_OBJECTS)
lib543_LDADD = $(LDADD)
lib543_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_260 = lib544-first.$(OBJEXT)
am_lib544_OBJECTS = lib544-lib544.$(OBJEXT) $(am__objects_260)
lib544_OBJECTS = $(am_lib544_OBJECTS)
lib544_LDADD = $(LDADD)
lib544_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_261 = lib545-first.$(OBJEXT)
am_lib545_OBJECTS = lib545-lib544.$(OBJEXT) $(am__objects_261)
lib545_OBJECTS = $(am_lib545_OBJECTS)
lib545_LDADD = $(LDADD)
lib545_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_262 = lib547-first.$(OBJEXT)
am_lib547_OBJECTS = lib547-lib547.$(OBJEXT) $(am__objects_262)
lib547_OBJECTS = $(am_lib547_OBJECTS)
lib547_LDADD = $(LDADD)
lib547_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_263 = lib548-first.$(OBJEXT)
am_lib548_OBJECTS = lib548-lib547.$(OBJEXT) $(am__objects_263)
lib548_OBJECTS = $(am_lib548_OBJECTS)
lib548_LDADD = $(LDADD)
lib548_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_264 = lib549-first.$(OBJEXT)
am_lib549_OBJECTS = lib549-lib549.$(OBJEXT) $(am__objects_264)
lib549_OBJECTS = $(am_lib549_OBJECTS)
lib549_LDADD = $(LDADD)
lib549_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_265 = lib552-first.$(OBJEXT)
am__objects_266 = ../../lib/lib552-warnless.$(OBJEXT)
am_lib552_OBJECTS = lib552-lib552.$(OBJEXT) $(am__objects_265) \
	$(am__objects_266)
lib552_OBJECTS = $(am_lib552_OBJECTS)
lib552_LDADD = $(LDADD)
lib552_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_267 = lib553-first.$(OBJEXT)
am_lib553_OBJECTS = lib553-lib553.$(OBJEXT) $(am__objects_267)
lib553_OBJECTS = $(am_lib553_OBJECTS)
lib553_LDADD = $(LDADD)
lib553_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_268 = lib554-first.$(OBJEXT)
am_lib554_OBJECTS = lib554-lib554.$(OBJEXT) $(am__objects_268)
lib554_OBJECTS = $(am_lib554_OBJECTS)
lib554_LDADD = $(LDADD)
lib554_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_269 = lib555-first.$(OBJEXT)
am__objects_270 = lib555-testutil.$(OBJEXT)
am__objects_271 = ../../lib/lib555-warnless.$(OBJEXT)
am_lib555_OBJECTS = lib555-lib555.$(OBJEXT) $(am__objects_269) \
	$(am__objects_270) $(am__objects_271)
lib555_OBJECTS = $(am_lib555_OBJECTS)
lib555_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_272 = lib556-first.$(OBJEXT)
am__objects_273 = ../../lib/lib556-warnless.$(OBJEXT)
am_lib556_OBJECTS = lib556-lib556.$(OBJEXT) $(am__objects_272) \
	$(am__objects_273)
lib556_OBJECTS = $(am_lib556_OBJECTS)
lib556_LDADD = $(LDADD)
lib556_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_274 = lib557-first.$(OBJEXT)
am_lib557_OBJECTS = lib557-lib557.$(OBJEXT) $(am__objects_274)
lib557_OBJECTS = $(am_lib557_OBJECTS)
lib557_LDADD = $(LDADD)
lib557_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_275 = lib558-first.$(OBJEXT)
am_lib558_OBJECTS = lib558-lib558.$(OBJEXT) $(am__objects_275)
lib558_OBJECTS = $(am_lib558_OBJECTS)
lib558_LDADD = $(LDADD)
lib558_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_276 = lib559-first.$(OBJEXT)
am_lib559_OBJECTS = lib559-lib559.$(OBJEXT) $(am__objects_276)
lib559_OBJECTS = $(am_lib559_OBJECTS)
lib559_LDADD = $(LDADD)
lib559_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_277 = lib560-first.$(OBJEXT)
am__objects_278 = lib560-testutil.$(OBJEXT)
am__objects_279 = ../../lib/lib560-warnless.$(OBJEXT)
am_lib560_OBJECTS = lib560-lib560.$(OBJEXT) $(am__objects_277) \
	$(am__objects_278) $(am__objects_279)
lib560_OBJECTS = $(am_lib560_OBJECTS)
lib560_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_280 = lib562-first.$(OBJEXT)
am_lib562_OBJECTS = lib562-lib562.$(OBJEXT) $(am__objects_280)
lib562_OBJECTS = $(am_lib562_OBJECTS)
lib562_LDADD = $(LDADD)
lib562_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_281 = lib564-first.$(OBJEXT)
am__objects_282 = lib564-testutil.$(OBJEXT)
am__objects_283 = ../../lib/lib564-warnless.$(OBJEXT)
am_lib564_OBJECTS = lib564-lib564.$(OBJEXT) $(am__objects_281) \
	$(am__objects_282) $(am__objects_283)
lib564_OBJECTS = $(am_lib564_OBJECTS)
lib564_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_284 = lib565-first.$(OBJEXT)
am_lib565_OBJECTS = lib565-lib510.$(OBJEXT) $(am__objects_284)
lib565_OBJECTS = $(am_lib565_OBJECTS)
lib565_LDADD = $(LDADD)
lib565_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_285 = lib566-first.$(OBJEXT)
am__objects_286 = ../../lib/lib566-curl_multibyte.$(OBJEXT)
am_lib566_OBJECTS = lib566-lib566.$(OBJEXT) $(am__objects_285) \
	$(am__objects_286)
lib566_OBJECTS = $(am_lib566_OBJECTS)
lib566_LDADD = $(LDADD)
lib566_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_287 = lib567-first.$(OBJEXT)
am_lib567_OBJECTS = lib567-lib567.$(OBJEXT) $(am__objects_287)
lib567_OBJECTS = $(am_lib567_OBJECTS)
lib567_LDADD = $(LDADD)
lib567_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_288 = lib568-first.$(OBJEXT)
am__objects_289 = ../../lib/lib568-curl_multibyte.$(OBJEXT)
am_lib568_OBJECTS = lib568-lib568.$(OBJEXT) $(am__objects_288) \
	$(am__objects_289)
lib568_OBJECTS = $(am_lib568_OBJECTS)
lib568_LDADD = $(LDADD)
lib568_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_290 = lib569-first.$(OBJEXT)
am__objects_291 = ../../lib/lib569-curl_multibyte.$(OBJEXT)
am_lib569_OBJECTS = lib569-lib569.$(OBJEXT) $(am__objects_290) \
	$(am__objects_291)
lib569_OBJECTS = $(am_lib569_OBJECTS)
lib569_LDADD = $(LDADD)
lib569_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_292 = lib570-first.$(OBJEXT)
am_lib570_OBJECTS = lib570-lib570.$(OBJEXT) $(am__objects_292)
lib570_OBJECTS = $(am_lib570_OBJECTS)
lib570_LDADD = $(LDADD)
lib570_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_293 = lib571-first.$(OBJEXT)
am__objects_294 = ../../lib/lib571-warnless.$(OBJEXT)
am__objects_295 = ../../lib/lib571-curl_multibyte.$(OBJEXT)
am_lib571_OBJECTS = lib571-lib571.$(OBJEXT) $(am__objects_293) \
	$(am__objects_294) $(am__objects_295)
lib571_OBJECTS = $(am_lib571_OBJECTS)
lib571_LDADD = $(LDADD)
lib571_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_296 = lib572-first.$(OBJEXT)
am__objects_297 = ../../lib/lib572-curl_multibyte.$(OBJEXT)
am_lib572_OBJECTS = lib572-lib572.$(OBJEXT) $(am__objects_296) \
	$(am__objects_297)
lib572_OBJECTS = $(am_lib572_OBJECTS)
lib572_LDADD = $(LDADD)
lib572_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_298 = lib573-first.$(OBJEXT)
am__objects_299 = lib573-testutil.$(OBJEXT)
am__objects_300 = ../../lib/lib573-warnless.$(OBJEXT)
am__objects_301 = lib573-testtrace.$(OBJEXT)
am_lib573_OBJECTS = lib573-lib573.$(OBJEXT) $(am__objects_298) \
	$(am__objects_299) $(am__objects_300) $(am__objects_301)
lib573_OBJECTS = $(am_lib573_OBJECTS)
lib573_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_302 = lib574-first.$(OBJEXT)
am_lib574_OBJECTS = lib574-lib574.$(OBJEXT) $(am__objects_302)
lib574_OBJECTS = $(am_lib574_OBJECTS)
lib574_LDADD = $(LDADD)
lib574_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_303 = lib575-first.$(OBJEXT)
am__objects_304 = lib575-testutil.$(OBJEXT)
am__objects_305 = ../../lib/lib575-warnless.$(OBJEXT)
am_lib575_OBJECTS = lib575-lib575.$(OBJEXT) $(am__objects_303) \
	$(am__objects_304) $(am__objects_305)
lib575_OBJECTS = $(am_lib575_OBJECTS)
lib575_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_306 = lib576-first.$(OBJEXT)
am_lib576_OBJECTS = lib576-lib576.$(OBJEXT) $(am__objects_306)
lib576_OBJECTS = $(am_lib576_OBJECTS)
lib576_LDADD = $(LDADD)
lib576_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_307 = lib578-first.$(OBJEXT)
am__objects_308 = ../../lib/lib578-curl_multibyte.$(OBJEXT)
am_lib578_OBJECTS = lib578-lib578.$(OBJEXT) $(am__objects_307) \
	$(am__objects_308)
lib578_OBJECTS = $(am_lib578_OBJECTS)
lib578_LDADD = $(LDADD)
lib578_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_309 = lib579-first.$(OBJEXT)
am__objects_310 = ../../lib/lib579-curl_multibyte.$(OBJEXT)
am_lib579_OBJECTS = lib579-lib579.$(OBJEXT) $(am__objects_309) \
	$(am__objects_310)
lib579_OBJECTS = $(am_lib579_OBJECTS)
lib579_LDADD = $(LDADD)
lib579_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_311 = lib582-first.$(OBJEXT)
am__objects_312 = lib582-testutil.$(OBJEXT)
am__objects_313 = ../../lib/lib582-warnless.$(OBJEXT)
am__objects_314 = ../../lib/lib582-curl_multibyte.$(OBJEXT)
am_lib582_OBJECTS = lib582-lib582.$(OBJEXT) $(am__objects_311) \
	$(am__objects_312) $(am__objects_313) $(am__objects_314)
lib582_OBJECTS = $(am_lib582_OBJECTS)
lib582_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_315 = lib583-first.$(OBJEXT)
am_lib583_OBJECTS = lib583-lib583.$(OBJEXT) $(am__objects_315)
lib583_OBJECTS = $(am_lib583_OBJECTS)
lib583_LDADD = $(LDADD)
lib583_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_316 = lib584-first.$(OBJEXT)
am_lib584_OBJECTS = lib584-lib589.$(OBJEXT) $(am__objects_316)
lib584_OBJECTS = $(am_lib584_OBJECTS)
lib584_LDADD = $(LDADD)
lib584_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_317 = lib585-first.$(OBJEXT)
am__objects_318 = lib585-testutil.$(OBJEXT)
am__objects_319 = lib585-testtrace.$(OBJEXT)
am__objects_320 = ../../lib/lib585-curl_multibyte.$(OBJEXT)
am_lib585_OBJECTS = lib585-lib500.$(OBJEXT) $(am__objects_317) \
	$(am__objects_318) $(am__objects_319) $(am__objects_320)
lib585_OBJECTS = $(am_lib585_OBJECTS)
lib585_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_321 = lib586-first.$(OBJEXT)
am_lib586_OBJECTS = lib586-lib586.$(OBJEXT) $(am__objects_321)
lib586_OBJECTS = $(am_lib586_OBJECTS)
lib586_LDADD = $(LDADD)
lib586_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_322 = lib587-first.$(OBJEXT)
am_lib587_OBJECTS = lib587-lib554.$(OBJEXT) $(am__objects_322)
lib587_OBJECTS = $(am_lib587_OBJECTS)
lib587_LDADD = $(LDADD)
lib587_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_323 = lib589-first.$(OBJEXT)
am_lib589_OBJECTS = lib589-lib589.$(OBJEXT) $(am__objects_323)
lib589_OBJECTS = $(am_lib589_OBJECTS)
lib589_LDADD = $(LDADD)
lib589_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_324 = lib590-first.$(OBJEXT)
am_lib590_OBJECTS = lib590-lib590.$(OBJEXT) $(am__objects_324)
lib590_OBJECTS = $(am_lib590_OBJECTS)
lib590_LDADD = $(LDADD)
lib590_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_325 = lib591-first.$(OBJEXT)
am__objects_326 = lib591-testutil.$(OBJEXT)
am__objects_327 = ../../lib/lib591-warnless.$(OBJEXT)
am__objects_328 = ../../lib/lib591-curl_multibyte.$(OBJEXT)
am_lib591_OBJECTS = lib591-lib591.$(OBJEXT) $(am__objects_325) \
	$(am__objects_326) $(am__objects_327) $(am__objects_328)
lib591_OBJECTS = $(am_lib591_OBJECTS)
lib591_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_329 = lib597-first.$(OBJEXT)
am__objects_330 = lib597-testutil.$(OBJEXT)
am__objects_331 = ../../lib/lib597-warnless.$(OBJEXT)
am_lib597_OBJECTS = lib597-lib597.$(OBJEXT) $(am__objects_329) \
	$(am__objects_330) $(am__objects_331)
lib597_OBJECTS = $(am_lib597_OBJECTS)
lib597_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_332 = lib598-first.$(OBJEXT)
am_lib598_OBJECTS = lib598-lib598.$(OBJEXT) $(am__objects_332)
lib598_OBJECTS = $(am_lib598_OBJECTS)
lib598_LDADD = $(LDADD)
lib598_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_333 = lib599-first.$(OBJEXT)
am__objects_334 = ../../lib/lib599-curl_multibyte.$(OBJEXT)
am_lib599_OBJECTS = lib599-lib599.$(OBJEXT) $(am__objects_333) \
	$(am__objects_334)
lib599_OBJECTS = $(am_lib599_OBJECTS)
lib599_LDADD = $(LDADD)
lib599_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_335 = lib643-first.$(OBJEXT)
am_lib643_OBJECTS = lib643-lib643.$(OBJEXT) $(am__objects_335)
lib643_OBJECTS = $(am_lib643_OBJECTS)
lib643_LDADD = $(LDADD)
lib643_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_336 = lib644-first.$(OBJEXT)
am_lib644_OBJECTS = lib644-lib643.$(OBJEXT) $(am__objects_336)
lib644_OBJECTS = $(am_lib644_OBJECTS)
lib644_LDADD = $(LDADD)
lib644_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_337 = lib645-first.$(OBJEXT)
am_lib645_OBJECTS = lib645-lib643.$(OBJEXT) $(am__objects_337)
lib645_OBJECTS = $(am_lib645_OBJECTS)
lib645_LDADD = $(LDADD)
lib645_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_338 = lib650-first.$(OBJEXT)
am_lib650_OBJECTS = lib650-lib650.$(OBJEXT) $(am__objects_338)
lib650_OBJECTS = $(am_lib650_OBJECTS)
lib650_LDADD = $(LDADD)
lib650_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_339 = lib651-first.$(OBJEXT)
am_lib651_OBJECTS = lib651-lib651.$(OBJEXT) $(am__objects_339)
lib651_OBJECTS = $(am_lib651_OBJECTS)
lib651_LDADD = $(LDADD)
lib651_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_340 = lib652-first.$(OBJEXT)
am_lib652_OBJECTS = lib652-lib652.$(OBJEXT) $(am__objects_340)
lib652_OBJECTS = $(am_lib652_OBJECTS)
lib652_LDADD = $(LDADD)
lib652_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_341 = lib653-first.$(OBJEXT)
am_lib653_OBJECTS = lib653-lib653.$(OBJEXT) $(am__objects_341)
lib653_OBJECTS = $(am_lib653_OBJECTS)
lib653_LDADD = $(LDADD)
lib653_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_342 = lib654-first.$(OBJEXT)
am_lib654_OBJECTS = lib654-lib654.$(OBJEXT) $(am__objects_342)
lib654_OBJECTS = $(am_lib654_OBJECTS)
lib654_LDADD = $(LDADD)
lib654_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_343 = lib655-first.$(OBJEXT)
am_lib655_OBJECTS = lib655-lib655.$(OBJEXT) $(am__objects_343)
lib655_OBJECTS = $(am_lib655_OBJECTS)
lib655_LDADD = $(LDADD)
lib655_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_344 = lib658-first.$(OBJEXT)
am__objects_345 = lib658-testutil.$(OBJEXT)
am__objects_346 = ../../lib/lib658-warnless.$(OBJEXT)
am_lib658_OBJECTS = lib658-lib658.$(OBJEXT) $(am__objects_344) \
	$(am__objects_345) $(am__objects_346)
lib658_OBJECTS = $(am_lib658_OBJECTS)
lib658_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_347 = lib659-first.$(OBJEXT)
am__objects_348 = lib659-testutil.$(OBJEXT)
am__objects_349 = ../../lib/lib659-warnless.$(OBJEXT)
am_lib659_OBJECTS = lib659-lib659.$(OBJEXT) $(am__objects_347) \
	$(am__objects_348) $(am__objects_349)
lib659_OBJECTS = $(am_lib659_OBJECTS)
lib659_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_350 = lib661-first.$(OBJEXT)
am_lib661_OBJECTS = lib661-lib661.$(OBJEXT) $(am__objects_350)
lib661_OBJECTS = $(am_lib661_OBJECTS)
lib661_LDADD = $(LDADD)
lib661_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_351 = lib666-first.$(OBJEXT)
am_lib666_OBJECTS = lib666-lib666.$(OBJEXT) $(am__objects_351)
lib666_OBJECTS = $(am_lib666_OBJECTS)
lib666_LDADD = $(LDADD)
lib666_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_352 = lib667-first.$(OBJEXT)
am__objects_353 = lib667-testutil.$(OBJEXT)
am__objects_354 = ../../lib/lib667-warnless.$(OBJEXT)
am_lib667_OBJECTS = lib667-lib667.$(OBJEXT) $(am__objects_352) \
	$(am__objects_353) $(am__objects_354)
lib667_OBJECTS = $(am_lib667_OBJECTS)
lib667_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_355 = lib668-first.$(OBJEXT)
am__objects_356 = lib668-testutil.$(OBJEXT)
am__objects_357 = ../../lib/lib668-warnless.$(OBJEXT)
am_lib668_OBJECTS = lib668-lib668.$(OBJEXT) $(am__objects_355) \
	$(am__objects_356) $(am__objects_357)
lib668_OBJECTS = $(am_lib668_OBJECTS)
lib668_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_358 = lib670-first.$(OBJEXT)
am__objects_359 = lib670-testutil.$(OBJEXT)
am__objects_360 = ../../lib/lib670-warnless.$(OBJEXT)
am_lib670_OBJECTS = lib670-lib670.$(OBJEXT) $(am__objects_358) \
	$(am__objects_359) $(am__objects_360)
lib670_OBJECTS = $(am_lib670_OBJECTS)
lib670_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_361 = lib671-first.$(OBJEXT)
am__objects_362 = lib671-testutil.$(OBJEXT)
am__objects_363 = ../../lib/lib671-warnless.$(OBJEXT)
am_lib671_OBJECTS = lib671-lib670.$(OBJEXT) $(am__objects_361) \
	$(am__objects_362) $(am__objects_363)
lib671_OBJECTS = $(am_lib671_OBJECTS)
lib671_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_364 = lib672-first.$(OBJEXT)
am__objects_365 = lib672-testutil.$(OBJEXT)
am__objects_366 = ../../lib/lib672-warnless.$(OBJEXT)
am_lib672_OBJECTS = lib672-lib670.$(OBJEXT) $(am__objects_364) \
	$(am__objects_365) $(am__objects_366)
lib672_OBJECTS = $(am_lib672_OBJECTS)
lib672_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_367 = lib673-first.$(OBJEXT)
am__objects_368 = lib673-testutil.$(OBJEXT)
am__objects_369 = ../../lib/lib673-warnless.$(OBJEXT)
am_lib673_OBJECTS = lib673-lib670.$(OBJEXT) $(am__objects_367) \
	$(am__objects_368) $(am__objects_369)
lib673_OBJECTS = $(am_lib673_OBJECTS)
lib673_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_370 = lib674-first.$(OBJEXT)
am__objects_371 = lib674-testutil.$(OBJEXT)
am__objects_372 = ../../lib/lib674-warnless.$(OBJEXT)
am_lib674_OBJECTS = lib674-lib674.$(OBJEXT) $(am__objects_370) \
	$(am__objects_371) $(am__objects_372)
lib674_OBJECTS = $(am_lib674_OBJECTS)
lib674_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_373 = libauthretry-first.$(OBJEXT)
am_libauthretry_OBJECTS = libauthretry-libauthretry.$(OBJEXT) \
	$(am__objects_373)
libauthretry_OBJECTS = $(am_libauthretry_OBJECTS)
libauthretry_LDADD = $(LDADD)
libauthretry_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_374 = libntlmconnect-first.$(OBJEXT)
am__objects_375 = libntlmconnect-testutil.$(OBJEXT)
am__objects_376 = ../../lib/libntlmconnect-warnless.$(OBJEXT)
am_libntlmconnect_OBJECTS = libntlmconnect-libntlmconnect.$(OBJEXT) \
	$(am__objects_374) $(am__objects_375) $(am__objects_376)
libntlmconnect_OBJECTS = $(am_libntlmconnect_OBJECTS)
libntlmconnect_DEPENDENCIES = $(am__DEPENDENCIES_1)
AM_V_P = $(am__v_P_@AM_V@)
am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
am__v_P_0 = false
am__v_P_1 = :
AM_V_GEN = $(am__v_GEN_@AM_V@)
1324
1325
1326
1327
1328
1329
1330







1331
1332
1333
1334
1335
1336
1337
	../../lib/$(DEPDIR)/lib1907-warnless.Po \
	../../lib/$(DEPDIR)/lib1908-warnless.Po \
	../../lib/$(DEPDIR)/lib1910-warnless.Po \
	../../lib/$(DEPDIR)/lib1911-warnless.Po \
	../../lib/$(DEPDIR)/lib1912-warnless.Po \
	../../lib/$(DEPDIR)/lib1913-warnless.Po \
	../../lib/$(DEPDIR)/lib1915-warnless.Po \







	../../lib/$(DEPDIR)/lib3010-warnless.Po \
	../../lib/$(DEPDIR)/lib500-curl_multibyte.Po \
	../../lib/$(DEPDIR)/lib502-warnless.Po \
	../../lib/$(DEPDIR)/lib503-warnless.Po \
	../../lib/$(DEPDIR)/lib504-warnless.Po \
	../../lib/$(DEPDIR)/lib505-curl_multibyte.Po \
	../../lib/$(DEPDIR)/lib507-warnless.Po \







>
>
>
>
>
>
>







1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
	../../lib/$(DEPDIR)/lib1907-warnless.Po \
	../../lib/$(DEPDIR)/lib1908-warnless.Po \
	../../lib/$(DEPDIR)/lib1910-warnless.Po \
	../../lib/$(DEPDIR)/lib1911-warnless.Po \
	../../lib/$(DEPDIR)/lib1912-warnless.Po \
	../../lib/$(DEPDIR)/lib1913-warnless.Po \
	../../lib/$(DEPDIR)/lib1915-warnless.Po \
	../../lib/$(DEPDIR)/lib1916-warnless.Po \
	../../lib/$(DEPDIR)/lib1917-warnless.Po \
	../../lib/$(DEPDIR)/lib1918-warnless.Po \
	../../lib/$(DEPDIR)/lib1933-warnless.Po \
	../../lib/$(DEPDIR)/lib1934-warnless.Po \
	../../lib/$(DEPDIR)/lib1935-warnless.Po \
	../../lib/$(DEPDIR)/lib1936-warnless.Po \
	../../lib/$(DEPDIR)/lib3010-warnless.Po \
	../../lib/$(DEPDIR)/lib500-curl_multibyte.Po \
	../../lib/$(DEPDIR)/lib502-warnless.Po \
	../../lib/$(DEPDIR)/lib503-warnless.Po \
	../../lib/$(DEPDIR)/lib504-warnless.Po \
	../../lib/$(DEPDIR)/lib505-curl_multibyte.Po \
	../../lib/$(DEPDIR)/lib507-warnless.Po \
1410
1411
1412
1413
1414
1415
1416
1417


1418
1419
1420
1421
1422
1423
1424
	./$(DEPDIR)/lib1514-lib1514.Po ./$(DEPDIR)/lib1514-testutil.Po \
	./$(DEPDIR)/lib1515-first.Po ./$(DEPDIR)/lib1515-lib1515.Po \
	./$(DEPDIR)/lib1515-testutil.Po ./$(DEPDIR)/lib1517-first.Po \
	./$(DEPDIR)/lib1517-lib1517.Po ./$(DEPDIR)/lib1518-first.Po \
	./$(DEPDIR)/lib1518-lib1518.Po ./$(DEPDIR)/lib1520-first.Po \
	./$(DEPDIR)/lib1520-lib1520.Po ./$(DEPDIR)/lib1521-first.Po \
	./$(DEPDIR)/lib1521-lib1521.Po ./$(DEPDIR)/lib1522-first.Po \
	./$(DEPDIR)/lib1522-lib1522.Po ./$(DEPDIR)/lib1523-first.Po \


	./$(DEPDIR)/lib1523-lib1523.Po ./$(DEPDIR)/lib1525-first.Po \
	./$(DEPDIR)/lib1525-lib1525.Po ./$(DEPDIR)/lib1525-testutil.Po \
	./$(DEPDIR)/lib1526-first.Po ./$(DEPDIR)/lib1526-lib1526.Po \
	./$(DEPDIR)/lib1526-testutil.Po ./$(DEPDIR)/lib1527-first.Po \
	./$(DEPDIR)/lib1527-lib1527.Po ./$(DEPDIR)/lib1527-testutil.Po \
	./$(DEPDIR)/lib1528-first.Po ./$(DEPDIR)/lib1528-lib1528.Po \
	./$(DEPDIR)/lib1528-testutil.Po ./$(DEPDIR)/lib1529-first.Po \







|
>
>







1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
	./$(DEPDIR)/lib1514-lib1514.Po ./$(DEPDIR)/lib1514-testutil.Po \
	./$(DEPDIR)/lib1515-first.Po ./$(DEPDIR)/lib1515-lib1515.Po \
	./$(DEPDIR)/lib1515-testutil.Po ./$(DEPDIR)/lib1517-first.Po \
	./$(DEPDIR)/lib1517-lib1517.Po ./$(DEPDIR)/lib1518-first.Po \
	./$(DEPDIR)/lib1518-lib1518.Po ./$(DEPDIR)/lib1520-first.Po \
	./$(DEPDIR)/lib1520-lib1520.Po ./$(DEPDIR)/lib1521-first.Po \
	./$(DEPDIR)/lib1521-lib1521.Po ./$(DEPDIR)/lib1522-first.Po \
	./$(DEPDIR)/lib1522-lib1522.Po \
	./$(DEPDIR)/lib1522-testtrace.Po \
	./$(DEPDIR)/lib1522-testutil.Po ./$(DEPDIR)/lib1523-first.Po \
	./$(DEPDIR)/lib1523-lib1523.Po ./$(DEPDIR)/lib1525-first.Po \
	./$(DEPDIR)/lib1525-lib1525.Po ./$(DEPDIR)/lib1525-testutil.Po \
	./$(DEPDIR)/lib1526-first.Po ./$(DEPDIR)/lib1526-lib1526.Po \
	./$(DEPDIR)/lib1526-testutil.Po ./$(DEPDIR)/lib1527-first.Po \
	./$(DEPDIR)/lib1527-lib1527.Po ./$(DEPDIR)/lib1527-testutil.Po \
	./$(DEPDIR)/lib1528-first.Po ./$(DEPDIR)/lib1528-lib1528.Po \
	./$(DEPDIR)/lib1528-testutil.Po ./$(DEPDIR)/lib1529-first.Po \
1451
1452
1453
1454
1455
1456
1457
1458

1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477









1478
1479
1480
1481
1482
1483
1484
	./$(DEPDIR)/lib1556-testutil.Po ./$(DEPDIR)/lib1557-first.Po \
	./$(DEPDIR)/lib1557-lib1557.Po ./$(DEPDIR)/lib1557-testutil.Po \
	./$(DEPDIR)/lib1558.Po ./$(DEPDIR)/lib1559.Po \
	./$(DEPDIR)/lib1560.Po ./$(DEPDIR)/lib1564-first.Po \
	./$(DEPDIR)/lib1564-lib1564.Po ./$(DEPDIR)/lib1564-testutil.Po \
	./$(DEPDIR)/lib1565-first.Po ./$(DEPDIR)/lib1565-lib1565.Po \
	./$(DEPDIR)/lib1565-testutil.Po ./$(DEPDIR)/lib1567-first.Po \
	./$(DEPDIR)/lib1567-lib1567.Po ./$(DEPDIR)/lib1591-first.Po \

	./$(DEPDIR)/lib1591-lib1591.Po ./$(DEPDIR)/lib1591-testutil.Po \
	./$(DEPDIR)/lib1592-first.Po ./$(DEPDIR)/lib1592-lib1592.Po \
	./$(DEPDIR)/lib1592-testutil.Po ./$(DEPDIR)/lib1593.Po \
	./$(DEPDIR)/lib1594.Po ./$(DEPDIR)/lib1596-first.Po \
	./$(DEPDIR)/lib1596-lib1594.Po ./$(DEPDIR)/lib1596-testutil.Po \
	./$(DEPDIR)/lib1905-first.Po ./$(DEPDIR)/lib1905-lib1905.Po \
	./$(DEPDIR)/lib1905-testutil.Po ./$(DEPDIR)/lib1906-first.Po \
	./$(DEPDIR)/lib1906-lib1906.Po ./$(DEPDIR)/lib1906-testutil.Po \
	./$(DEPDIR)/lib1907-first.Po ./$(DEPDIR)/lib1907-lib1907.Po \
	./$(DEPDIR)/lib1907-testutil.Po ./$(DEPDIR)/lib1908-first.Po \
	./$(DEPDIR)/lib1908-lib1908.Po ./$(DEPDIR)/lib1908-testutil.Po \
	./$(DEPDIR)/lib1910-first.Po ./$(DEPDIR)/lib1910-lib1910.Po \
	./$(DEPDIR)/lib1910-testutil.Po ./$(DEPDIR)/lib1911-first.Po \
	./$(DEPDIR)/lib1911-lib1911.Po ./$(DEPDIR)/lib1911-testutil.Po \
	./$(DEPDIR)/lib1912-first.Po ./$(DEPDIR)/lib1912-lib1912.Po \
	./$(DEPDIR)/lib1912-testutil.Po ./$(DEPDIR)/lib1913-first.Po \
	./$(DEPDIR)/lib1913-lib1913.Po ./$(DEPDIR)/lib1913-testutil.Po \
	./$(DEPDIR)/lib1915-first.Po ./$(DEPDIR)/lib1915-lib1915.Po \
	./$(DEPDIR)/lib1915-testutil.Po ./$(DEPDIR)/lib3010-first.Po \









	./$(DEPDIR)/lib3010-lib3010.Po ./$(DEPDIR)/lib3010-testutil.Po \
	./$(DEPDIR)/lib500-first.Po ./$(DEPDIR)/lib500-lib500.Po \
	./$(DEPDIR)/lib500-testtrace.Po ./$(DEPDIR)/lib500-testutil.Po \
	./$(DEPDIR)/lib501-first.Po ./$(DEPDIR)/lib501-lib501.Po \
	./$(DEPDIR)/lib502-first.Po ./$(DEPDIR)/lib502-lib502.Po \
	./$(DEPDIR)/lib502-testutil.Po ./$(DEPDIR)/lib503-first.Po \
	./$(DEPDIR)/lib503-lib503.Po ./$(DEPDIR)/lib503-testutil.Po \







|
>


















|
>
>
>
>
>
>
>
>
>







1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
	./$(DEPDIR)/lib1556-testutil.Po ./$(DEPDIR)/lib1557-first.Po \
	./$(DEPDIR)/lib1557-lib1557.Po ./$(DEPDIR)/lib1557-testutil.Po \
	./$(DEPDIR)/lib1558.Po ./$(DEPDIR)/lib1559.Po \
	./$(DEPDIR)/lib1560.Po ./$(DEPDIR)/lib1564-first.Po \
	./$(DEPDIR)/lib1564-lib1564.Po ./$(DEPDIR)/lib1564-testutil.Po \
	./$(DEPDIR)/lib1565-first.Po ./$(DEPDIR)/lib1565-lib1565.Po \
	./$(DEPDIR)/lib1565-testutil.Po ./$(DEPDIR)/lib1567-first.Po \
	./$(DEPDIR)/lib1567-lib1567.Po ./$(DEPDIR)/lib1568-first.Po \
	./$(DEPDIR)/lib1568-lib1568.Po ./$(DEPDIR)/lib1591-first.Po \
	./$(DEPDIR)/lib1591-lib1591.Po ./$(DEPDIR)/lib1591-testutil.Po \
	./$(DEPDIR)/lib1592-first.Po ./$(DEPDIR)/lib1592-lib1592.Po \
	./$(DEPDIR)/lib1592-testutil.Po ./$(DEPDIR)/lib1593.Po \
	./$(DEPDIR)/lib1594.Po ./$(DEPDIR)/lib1596-first.Po \
	./$(DEPDIR)/lib1596-lib1594.Po ./$(DEPDIR)/lib1596-testutil.Po \
	./$(DEPDIR)/lib1905-first.Po ./$(DEPDIR)/lib1905-lib1905.Po \
	./$(DEPDIR)/lib1905-testutil.Po ./$(DEPDIR)/lib1906-first.Po \
	./$(DEPDIR)/lib1906-lib1906.Po ./$(DEPDIR)/lib1906-testutil.Po \
	./$(DEPDIR)/lib1907-first.Po ./$(DEPDIR)/lib1907-lib1907.Po \
	./$(DEPDIR)/lib1907-testutil.Po ./$(DEPDIR)/lib1908-first.Po \
	./$(DEPDIR)/lib1908-lib1908.Po ./$(DEPDIR)/lib1908-testutil.Po \
	./$(DEPDIR)/lib1910-first.Po ./$(DEPDIR)/lib1910-lib1910.Po \
	./$(DEPDIR)/lib1910-testutil.Po ./$(DEPDIR)/lib1911-first.Po \
	./$(DEPDIR)/lib1911-lib1911.Po ./$(DEPDIR)/lib1911-testutil.Po \
	./$(DEPDIR)/lib1912-first.Po ./$(DEPDIR)/lib1912-lib1912.Po \
	./$(DEPDIR)/lib1912-testutil.Po ./$(DEPDIR)/lib1913-first.Po \
	./$(DEPDIR)/lib1913-lib1913.Po ./$(DEPDIR)/lib1913-testutil.Po \
	./$(DEPDIR)/lib1915-first.Po ./$(DEPDIR)/lib1915-lib1915.Po \
	./$(DEPDIR)/lib1915-testutil.Po ./$(DEPDIR)/lib1916-first.Po \
	./$(DEPDIR)/lib1916-lib1916.Po ./$(DEPDIR)/lib1917-first.Po \
	./$(DEPDIR)/lib1917-lib1916.Po ./$(DEPDIR)/lib1918-first.Po \
	./$(DEPDIR)/lib1918-lib1918.Po ./$(DEPDIR)/lib1933-first.Po \
	./$(DEPDIR)/lib1933-lib1933.Po ./$(DEPDIR)/lib1933-testutil.Po \
	./$(DEPDIR)/lib1934-first.Po ./$(DEPDIR)/lib1934-lib1934.Po \
	./$(DEPDIR)/lib1934-testutil.Po ./$(DEPDIR)/lib1935-first.Po \
	./$(DEPDIR)/lib1935-lib1935.Po ./$(DEPDIR)/lib1935-testutil.Po \
	./$(DEPDIR)/lib1936-first.Po ./$(DEPDIR)/lib1936-lib1936.Po \
	./$(DEPDIR)/lib1936-testutil.Po ./$(DEPDIR)/lib3010-first.Po \
	./$(DEPDIR)/lib3010-lib3010.Po ./$(DEPDIR)/lib3010-testutil.Po \
	./$(DEPDIR)/lib500-first.Po ./$(DEPDIR)/lib500-lib500.Po \
	./$(DEPDIR)/lib500-testtrace.Po ./$(DEPDIR)/lib500-testutil.Po \
	./$(DEPDIR)/lib501-first.Po ./$(DEPDIR)/lib501-lib501.Po \
	./$(DEPDIR)/lib502-first.Po ./$(DEPDIR)/lib502-lib502.Po \
	./$(DEPDIR)/lib502-testutil.Po ./$(DEPDIR)/lib503-first.Po \
	./$(DEPDIR)/lib503-lib503.Po ./$(DEPDIR)/lib503-testutil.Po \
1550
1551
1552
1553
1554
1555
1556

1557
1558
1559
1560
1561
1562
1563
	./$(DEPDIR)/lib575-first.Po ./$(DEPDIR)/lib575-lib575.Po \
	./$(DEPDIR)/lib575-testutil.Po ./$(DEPDIR)/lib576-first.Po \
	./$(DEPDIR)/lib576-lib576.Po ./$(DEPDIR)/lib578-first.Po \
	./$(DEPDIR)/lib578-lib578.Po ./$(DEPDIR)/lib579-first.Po \
	./$(DEPDIR)/lib579-lib579.Po ./$(DEPDIR)/lib582-first.Po \
	./$(DEPDIR)/lib582-lib582.Po ./$(DEPDIR)/lib582-testutil.Po \
	./$(DEPDIR)/lib583-first.Po ./$(DEPDIR)/lib583-lib583.Po \

	./$(DEPDIR)/lib585-first.Po ./$(DEPDIR)/lib585-lib500.Po \
	./$(DEPDIR)/lib585-testtrace.Po ./$(DEPDIR)/lib585-testutil.Po \
	./$(DEPDIR)/lib586-first.Po ./$(DEPDIR)/lib586-lib586.Po \
	./$(DEPDIR)/lib587-first.Po ./$(DEPDIR)/lib587-lib554.Po \
	./$(DEPDIR)/lib589-first.Po ./$(DEPDIR)/lib589-lib589.Po \
	./$(DEPDIR)/lib590-first.Po ./$(DEPDIR)/lib590-lib590.Po \
	./$(DEPDIR)/lib591-first.Po ./$(DEPDIR)/lib591-lib591.Po \







>







1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
	./$(DEPDIR)/lib575-first.Po ./$(DEPDIR)/lib575-lib575.Po \
	./$(DEPDIR)/lib575-testutil.Po ./$(DEPDIR)/lib576-first.Po \
	./$(DEPDIR)/lib576-lib576.Po ./$(DEPDIR)/lib578-first.Po \
	./$(DEPDIR)/lib578-lib578.Po ./$(DEPDIR)/lib579-first.Po \
	./$(DEPDIR)/lib579-lib579.Po ./$(DEPDIR)/lib582-first.Po \
	./$(DEPDIR)/lib582-lib582.Po ./$(DEPDIR)/lib582-testutil.Po \
	./$(DEPDIR)/lib583-first.Po ./$(DEPDIR)/lib583-lib583.Po \
	./$(DEPDIR)/lib584-first.Po ./$(DEPDIR)/lib584-lib589.Po \
	./$(DEPDIR)/lib585-first.Po ./$(DEPDIR)/lib585-lib500.Po \
	./$(DEPDIR)/lib585-testtrace.Po ./$(DEPDIR)/lib585-testutil.Po \
	./$(DEPDIR)/lib586-first.Po ./$(DEPDIR)/lib586-lib586.Po \
	./$(DEPDIR)/lib587-first.Po ./$(DEPDIR)/lib587-lib554.Po \
	./$(DEPDIR)/lib589-first.Po ./$(DEPDIR)/lib589-lib589.Po \
	./$(DEPDIR)/lib590-first.Po ./$(DEPDIR)/lib590-lib590.Po \
	./$(DEPDIR)/lib591-first.Po ./$(DEPDIR)/lib591-lib591.Po \
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644



1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
	$(lib1533_SOURCES) $(lib1534_SOURCES) $(lib1535_SOURCES) \
	$(lib1536_SOURCES) $(lib1537_SOURCES) $(lib1538_SOURCES) \
	$(lib1539_SOURCES) $(lib1540_SOURCES) $(lib1550_SOURCES) \
	$(lib1551_SOURCES) $(lib1552_SOURCES) $(lib1553_SOURCES) \
	$(lib1554_SOURCES) $(lib1555_SOURCES) $(lib1556_SOURCES) \
	$(lib1557_SOURCES) $(lib1558_SOURCES) $(lib1559_SOURCES) \
	$(lib1560_SOURCES) $(lib1564_SOURCES) $(lib1565_SOURCES) \
	$(lib1567_SOURCES) $(lib1591_SOURCES) $(lib1592_SOURCES) \
	$(lib1593_SOURCES) $(lib1594_SOURCES) $(lib1596_SOURCES) \
	$(lib1905_SOURCES) $(lib1906_SOURCES) $(lib1907_SOURCES) \
	$(lib1908_SOURCES) $(lib1910_SOURCES) $(lib1911_SOURCES) \
	$(lib1912_SOURCES) $(lib1913_SOURCES) $(lib1915_SOURCES) \



	$(lib3010_SOURCES) $(lib500_SOURCES) $(lib501_SOURCES) \
	$(lib502_SOURCES) $(lib503_SOURCES) $(lib504_SOURCES) \
	$(lib505_SOURCES) $(lib506_SOURCES) $(lib507_SOURCES) \
	$(lib508_SOURCES) $(lib509_SOURCES) $(lib510_SOURCES) \
	$(lib511_SOURCES) $(lib512_SOURCES) $(lib513_SOURCES) \
	$(lib514_SOURCES) $(lib515_SOURCES) $(lib516_SOURCES) \
	$(lib517_SOURCES) $(lib518_SOURCES) $(lib519_SOURCES) \
	$(lib520_SOURCES) $(lib521_SOURCES) $(lib523_SOURCES) \
	$(lib524_SOURCES) $(lib525_SOURCES) $(lib526_SOURCES) \
	$(lib527_SOURCES) $(lib529_SOURCES) $(lib532_SOURCES) \
	$(lib533_SOURCES) $(lib537_SOURCES) $(lib539_SOURCES) \
	$(lib540_SOURCES) $(lib541_SOURCES) $(lib542_SOURCES) \
	$(lib543_SOURCES) $(lib544_SOURCES) $(lib545_SOURCES) \
	$(lib547_SOURCES) $(lib548_SOURCES) $(lib549_SOURCES) \
	$(lib552_SOURCES) $(lib553_SOURCES) $(lib554_SOURCES) \
	$(lib555_SOURCES) $(lib556_SOURCES) $(lib557_SOURCES) \
	$(lib558_SOURCES) $(lib559_SOURCES) $(lib560_SOURCES) \
	$(lib562_SOURCES) $(lib564_SOURCES) $(lib565_SOURCES) \
	$(lib566_SOURCES) $(lib567_SOURCES) $(lib568_SOURCES) \
	$(lib569_SOURCES) $(lib570_SOURCES) $(lib571_SOURCES) \
	$(lib572_SOURCES) $(lib573_SOURCES) $(lib574_SOURCES) \
	$(lib575_SOURCES) $(lib576_SOURCES) $(lib578_SOURCES) \
	$(lib579_SOURCES) $(lib582_SOURCES) $(lib583_SOURCES) \
	$(lib585_SOURCES) $(lib586_SOURCES) $(lib587_SOURCES) \
	$(lib589_SOURCES) $(lib590_SOURCES) $(lib591_SOURCES) \
	$(lib597_SOURCES) $(lib598_SOURCES) $(lib599_SOURCES) \
	$(lib643_SOURCES) $(lib644_SOURCES) $(lib645_SOURCES) \
	$(lib650_SOURCES) $(lib651_SOURCES) $(lib652_SOURCES) \
	$(lib653_SOURCES) $(lib654_SOURCES) $(lib655_SOURCES) \
	$(lib658_SOURCES) $(lib659_SOURCES) $(lib661_SOURCES) \







|
|
|
|
|
>
>
>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|







1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
	$(lib1533_SOURCES) $(lib1534_SOURCES) $(lib1535_SOURCES) \
	$(lib1536_SOURCES) $(lib1537_SOURCES) $(lib1538_SOURCES) \
	$(lib1539_SOURCES) $(lib1540_SOURCES) $(lib1550_SOURCES) \
	$(lib1551_SOURCES) $(lib1552_SOURCES) $(lib1553_SOURCES) \
	$(lib1554_SOURCES) $(lib1555_SOURCES) $(lib1556_SOURCES) \
	$(lib1557_SOURCES) $(lib1558_SOURCES) $(lib1559_SOURCES) \
	$(lib1560_SOURCES) $(lib1564_SOURCES) $(lib1565_SOURCES) \
	$(lib1567_SOURCES) $(lib1568_SOURCES) $(lib1591_SOURCES) \
	$(lib1592_SOURCES) $(lib1593_SOURCES) $(lib1594_SOURCES) \
	$(lib1596_SOURCES) $(lib1905_SOURCES) $(lib1906_SOURCES) \
	$(lib1907_SOURCES) $(lib1908_SOURCES) $(lib1910_SOURCES) \
	$(lib1911_SOURCES) $(lib1912_SOURCES) $(lib1913_SOURCES) \
	$(lib1915_SOURCES) $(lib1916_SOURCES) $(lib1917_SOURCES) \
	$(lib1918_SOURCES) $(lib1933_SOURCES) $(lib1934_SOURCES) \
	$(lib1935_SOURCES) $(lib1936_SOURCES) $(lib3010_SOURCES) \
	$(lib500_SOURCES) $(lib501_SOURCES) $(lib502_SOURCES) \
	$(lib503_SOURCES) $(lib504_SOURCES) $(lib505_SOURCES) \
	$(lib506_SOURCES) $(lib507_SOURCES) $(lib508_SOURCES) \
	$(lib509_SOURCES) $(lib510_SOURCES) $(lib511_SOURCES) \
	$(lib512_SOURCES) $(lib513_SOURCES) $(lib514_SOURCES) \
	$(lib515_SOURCES) $(lib516_SOURCES) $(lib517_SOURCES) \
	$(lib518_SOURCES) $(lib519_SOURCES) $(lib520_SOURCES) \
	$(lib521_SOURCES) $(lib523_SOURCES) $(lib524_SOURCES) \
	$(lib525_SOURCES) $(lib526_SOURCES) $(lib527_SOURCES) \
	$(lib529_SOURCES) $(lib532_SOURCES) $(lib533_SOURCES) \
	$(lib537_SOURCES) $(lib539_SOURCES) $(lib540_SOURCES) \
	$(lib541_SOURCES) $(lib542_SOURCES) $(lib543_SOURCES) \
	$(lib544_SOURCES) $(lib545_SOURCES) $(lib547_SOURCES) \
	$(lib548_SOURCES) $(lib549_SOURCES) $(lib552_SOURCES) \
	$(lib553_SOURCES) $(lib554_SOURCES) $(lib555_SOURCES) \
	$(lib556_SOURCES) $(lib557_SOURCES) $(lib558_SOURCES) \
	$(lib559_SOURCES) $(lib560_SOURCES) $(lib562_SOURCES) \
	$(lib564_SOURCES) $(lib565_SOURCES) $(lib566_SOURCES) \
	$(lib567_SOURCES) $(lib568_SOURCES) $(lib569_SOURCES) \
	$(lib570_SOURCES) $(lib571_SOURCES) $(lib572_SOURCES) \
	$(lib573_SOURCES) $(lib574_SOURCES) $(lib575_SOURCES) \
	$(lib576_SOURCES) $(lib578_SOURCES) $(lib579_SOURCES) \
	$(lib582_SOURCES) $(lib583_SOURCES) $(lib584_SOURCES) \
	$(lib585_SOURCES) $(lib586_SOURCES) $(lib587_SOURCES) \
	$(lib589_SOURCES) $(lib590_SOURCES) $(lib591_SOURCES) \
	$(lib597_SOURCES) $(lib598_SOURCES) $(lib599_SOURCES) \
	$(lib643_SOURCES) $(lib644_SOURCES) $(lib645_SOURCES) \
	$(lib650_SOURCES) $(lib651_SOURCES) $(lib652_SOURCES) \
	$(lib653_SOURCES) $(lib654_SOURCES) $(lib655_SOURCES) \
	$(lib658_SOURCES) $(lib659_SOURCES) $(lib661_SOURCES) \
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702



1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
	$(lib1532_SOURCES) $(lib1533_SOURCES) $(lib1534_SOURCES) \
	$(lib1535_SOURCES) $(lib1536_SOURCES) $(lib1537_SOURCES) \
	$(lib1538_SOURCES) $(lib1539_SOURCES) $(lib1540_SOURCES) \
	$(lib1550_SOURCES) $(lib1551_SOURCES) $(lib1552_SOURCES) \
	$(lib1553_SOURCES) $(lib1554_SOURCES) $(lib1555_SOURCES) \
	$(lib1556_SOURCES) $(lib1557_SOURCES) $(lib1558_SOURCES) \
	$(lib1559_SOURCES) $(lib1560_SOURCES) $(lib1564_SOURCES) \
	$(lib1565_SOURCES) $(lib1567_SOURCES) $(lib1591_SOURCES) \
	$(lib1592_SOURCES) $(lib1593_SOURCES) $(lib1594_SOURCES) \
	$(lib1596_SOURCES) $(lib1905_SOURCES) $(lib1906_SOURCES) \
	$(lib1907_SOURCES) $(lib1908_SOURCES) $(lib1910_SOURCES) \
	$(lib1911_SOURCES) $(lib1912_SOURCES) $(lib1913_SOURCES) \



	$(lib1915_SOURCES) $(lib3010_SOURCES) $(lib500_SOURCES) \
	$(lib501_SOURCES) $(lib502_SOURCES) $(lib503_SOURCES) \
	$(lib504_SOURCES) $(lib505_SOURCES) $(lib506_SOURCES) \
	$(lib507_SOURCES) $(lib508_SOURCES) $(lib509_SOURCES) \
	$(lib510_SOURCES) $(lib511_SOURCES) $(lib512_SOURCES) \
	$(lib513_SOURCES) $(lib514_SOURCES) $(lib515_SOURCES) \
	$(lib516_SOURCES) $(lib517_SOURCES) $(lib518_SOURCES) \
	$(lib519_SOURCES) $(lib520_SOURCES) $(lib521_SOURCES) \
	$(lib523_SOURCES) $(lib524_SOURCES) $(lib525_SOURCES) \
	$(lib526_SOURCES) $(lib527_SOURCES) $(lib529_SOURCES) \
	$(lib532_SOURCES) $(lib533_SOURCES) $(lib537_SOURCES) \
	$(lib539_SOURCES) $(lib540_SOURCES) $(lib541_SOURCES) \
	$(lib542_SOURCES) $(lib543_SOURCES) $(lib544_SOURCES) \
	$(lib545_SOURCES) $(lib547_SOURCES) $(lib548_SOURCES) \
	$(lib549_SOURCES) $(lib552_SOURCES) $(lib553_SOURCES) \
	$(lib554_SOURCES) $(lib555_SOURCES) $(lib556_SOURCES) \
	$(lib557_SOURCES) $(lib558_SOURCES) $(lib559_SOURCES) \
	$(lib560_SOURCES) $(lib562_SOURCES) $(lib564_SOURCES) \
	$(lib565_SOURCES) $(lib566_SOURCES) $(lib567_SOURCES) \
	$(lib568_SOURCES) $(lib569_SOURCES) $(lib570_SOURCES) \
	$(lib571_SOURCES) $(lib572_SOURCES) $(lib573_SOURCES) \
	$(lib574_SOURCES) $(lib575_SOURCES) $(lib576_SOURCES) \
	$(lib578_SOURCES) $(lib579_SOURCES) $(lib582_SOURCES) \
	$(lib583_SOURCES) $(lib585_SOURCES) $(lib586_SOURCES) \
	$(lib587_SOURCES) $(lib589_SOURCES) $(lib590_SOURCES) \
	$(lib591_SOURCES) $(lib597_SOURCES) $(lib598_SOURCES) \
	$(lib599_SOURCES) $(lib643_SOURCES) $(lib644_SOURCES) \
	$(lib645_SOURCES) $(lib650_SOURCES) $(lib651_SOURCES) \
	$(lib652_SOURCES) $(lib653_SOURCES) $(lib654_SOURCES) \
	$(lib655_SOURCES) $(lib658_SOURCES) $(lib659_SOURCES) \
	$(lib661_SOURCES) $(lib666_SOURCES) $(lib667_SOURCES) \







|
|
|
|
|
>
>
>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|







1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
	$(lib1532_SOURCES) $(lib1533_SOURCES) $(lib1534_SOURCES) \
	$(lib1535_SOURCES) $(lib1536_SOURCES) $(lib1537_SOURCES) \
	$(lib1538_SOURCES) $(lib1539_SOURCES) $(lib1540_SOURCES) \
	$(lib1550_SOURCES) $(lib1551_SOURCES) $(lib1552_SOURCES) \
	$(lib1553_SOURCES) $(lib1554_SOURCES) $(lib1555_SOURCES) \
	$(lib1556_SOURCES) $(lib1557_SOURCES) $(lib1558_SOURCES) \
	$(lib1559_SOURCES) $(lib1560_SOURCES) $(lib1564_SOURCES) \
	$(lib1565_SOURCES) $(lib1567_SOURCES) $(lib1568_SOURCES) \
	$(lib1591_SOURCES) $(lib1592_SOURCES) $(lib1593_SOURCES) \
	$(lib1594_SOURCES) $(lib1596_SOURCES) $(lib1905_SOURCES) \
	$(lib1906_SOURCES) $(lib1907_SOURCES) $(lib1908_SOURCES) \
	$(lib1910_SOURCES) $(lib1911_SOURCES) $(lib1912_SOURCES) \
	$(lib1913_SOURCES) $(lib1915_SOURCES) $(lib1916_SOURCES) \
	$(lib1917_SOURCES) $(lib1918_SOURCES) $(lib1933_SOURCES) \
	$(lib1934_SOURCES) $(lib1935_SOURCES) $(lib1936_SOURCES) \
	$(lib3010_SOURCES) $(lib500_SOURCES) $(lib501_SOURCES) \
	$(lib502_SOURCES) $(lib503_SOURCES) $(lib504_SOURCES) \
	$(lib505_SOURCES) $(lib506_SOURCES) $(lib507_SOURCES) \
	$(lib508_SOURCES) $(lib509_SOURCES) $(lib510_SOURCES) \
	$(lib511_SOURCES) $(lib512_SOURCES) $(lib513_SOURCES) \
	$(lib514_SOURCES) $(lib515_SOURCES) $(lib516_SOURCES) \
	$(lib517_SOURCES) $(lib518_SOURCES) $(lib519_SOURCES) \
	$(lib520_SOURCES) $(lib521_SOURCES) $(lib523_SOURCES) \
	$(lib524_SOURCES) $(lib525_SOURCES) $(lib526_SOURCES) \
	$(lib527_SOURCES) $(lib529_SOURCES) $(lib532_SOURCES) \
	$(lib533_SOURCES) $(lib537_SOURCES) $(lib539_SOURCES) \
	$(lib540_SOURCES) $(lib541_SOURCES) $(lib542_SOURCES) \
	$(lib543_SOURCES) $(lib544_SOURCES) $(lib545_SOURCES) \
	$(lib547_SOURCES) $(lib548_SOURCES) $(lib549_SOURCES) \
	$(lib552_SOURCES) $(lib553_SOURCES) $(lib554_SOURCES) \
	$(lib555_SOURCES) $(lib556_SOURCES) $(lib557_SOURCES) \
	$(lib558_SOURCES) $(lib559_SOURCES) $(lib560_SOURCES) \
	$(lib562_SOURCES) $(lib564_SOURCES) $(lib565_SOURCES) \
	$(lib566_SOURCES) $(lib567_SOURCES) $(lib568_SOURCES) \
	$(lib569_SOURCES) $(lib570_SOURCES) $(lib571_SOURCES) \
	$(lib572_SOURCES) $(lib573_SOURCES) $(lib574_SOURCES) \
	$(lib575_SOURCES) $(lib576_SOURCES) $(lib578_SOURCES) \
	$(lib579_SOURCES) $(lib582_SOURCES) $(lib583_SOURCES) \
	$(lib584_SOURCES) $(lib585_SOURCES) $(lib586_SOURCES) \
	$(lib587_SOURCES) $(lib589_SOURCES) $(lib590_SOURCES) \
	$(lib591_SOURCES) $(lib597_SOURCES) $(lib598_SOURCES) \
	$(lib599_SOURCES) $(lib643_SOURCES) $(lib644_SOURCES) \
	$(lib645_SOURCES) $(lib650_SOURCES) $(lib651_SOURCES) \
	$(lib652_SOURCES) $(lib653_SOURCES) $(lib654_SOURCES) \
	$(lib655_SOURCES) $(lib658_SOURCES) $(lib659_SOURCES) \
	$(lib661_SOURCES) $(lib666_SOURCES) $(lib667_SOURCES) \
1890
1891
1892
1893
1894
1895
1896

1897
1898
1899
1900
1901
1902
1903
STRIP = @STRIP@
SUPPORT_FEATURES = @SUPPORT_FEATURES@
SUPPORT_PROTOCOLS = @SUPPORT_PROTOCOLS@
USE_ARES = @USE_ARES@
USE_BEARSSL = @USE_BEARSSL@
USE_GNUTLS = @USE_GNUTLS@
USE_GNUTLS_NETTLE = @USE_GNUTLS_NETTLE@

USE_LIBRTMP = @USE_LIBRTMP@
USE_LIBSSH = @USE_LIBSSH@
USE_LIBSSH2 = @USE_LIBSSH2@
USE_MBEDTLS = @USE_MBEDTLS@
USE_MESALINK = @USE_MESALINK@
USE_NGHTTP2 = @USE_NGHTTP2@
USE_NGHTTP3 = @USE_NGHTTP3@







>







1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
STRIP = @STRIP@
SUPPORT_FEATURES = @SUPPORT_FEATURES@
SUPPORT_PROTOCOLS = @SUPPORT_PROTOCOLS@
USE_ARES = @USE_ARES@
USE_BEARSSL = @USE_BEARSSL@
USE_GNUTLS = @USE_GNUTLS@
USE_GNUTLS_NETTLE = @USE_GNUTLS_NETTLE@
USE_HYPER = @USE_HYPER@
USE_LIBRTMP = @USE_LIBRTMP@
USE_LIBSSH = @USE_LIBSSH@
USE_LIBSSH2 = @USE_LIBSSH2@
USE_MBEDTLS = @USE_MBEDTLS@
USE_MESALINK = @USE_MESALINK@
USE_NGHTTP2 = @USE_NGHTTP2@
USE_NGHTTP3 = @USE_NGHTTP3@
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
# $(top_builddir)/ares is for in-tree c-ares's generated ares_build.h file
# $(top_srcdir)/ares is for in-tree c-ares's external include files
@USE_EMBEDDED_ARES_TRUE@AM_CPPFLAGS = -I$(top_srcdir)/include \
@USE_EMBEDDED_ARES_TRUE@	-I$(top_builddir)/lib \
@USE_EMBEDDED_ARES_TRUE@	-I$(top_srcdir)/lib \
@USE_EMBEDDED_ARES_TRUE@	-I$(top_builddir)/ares \
@USE_EMBEDDED_ARES_TRUE@	-I$(top_srcdir)/ares $(am__append_1)
EXTRA_DIST = test307.pl test610.pl test613.pl test1013.pl \
  test1022.pl Makefile.inc notexists.pl CMakeLists.txt mk-lib1521.pl

CLEANFILES = lib1521.c
@USE_EXPLICIT_LIB_DEPS_FALSE@SUPPORTFILES_LIBS = $(top_builddir)/lib/libcurl.la @CURL_NETWORK_LIBS@ @NSS_LIBS@
@USE_EXPLICIT_LIB_DEPS_TRUE@SUPPORTFILES_LIBS = $(top_builddir)/lib/libcurl.la @LIBCURL_LIBS@
@USE_EXPLICIT_LIB_DEPS_FALSE@TESTUTIL_LIBS = $(top_builddir)/lib/libcurl.la @CURL_NETWORK_AND_TIME_LIBS@ @NSS_LIBS@
@USE_EXPLICIT_LIB_DEPS_TRUE@TESTUTIL_LIBS = $(top_builddir)/lib/libcurl.la @LIBCURL_LIBS@

# Dependencies (may need to be overridden)
LDADD = $(SUPPORTFILES_LIBS)

#***************************************************************************
#                                  _   _ ____  _
#  Project                     ___| | | |  _ \| |
#                             / __| | | | |_) | |
#                            | (__| |_| |  _ <| |___
#                             \___|\___/|_| \_\_____|
#
# Copyright (C) 1998 - 2020, 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 https://curl.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







|
|

















|







2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
# $(top_builddir)/ares is for in-tree c-ares's generated ares_build.h file
# $(top_srcdir)/ares is for in-tree c-ares's external include files
@USE_EMBEDDED_ARES_TRUE@AM_CPPFLAGS = -I$(top_srcdir)/include \
@USE_EMBEDDED_ARES_TRUE@	-I$(top_builddir)/lib \
@USE_EMBEDDED_ARES_TRUE@	-I$(top_srcdir)/lib \
@USE_EMBEDDED_ARES_TRUE@	-I$(top_builddir)/ares \
@USE_EMBEDDED_ARES_TRUE@	-I$(top_srcdir)/ares $(am__append_1)
EXTRA_DIST = test307.pl test610.pl test613.pl test1013.pl test1022.pl   \
  Makefile.inc notexists.pl CMakeLists.txt mk-lib1521.pl .checksrc

CLEANFILES = lib1521.c
@USE_EXPLICIT_LIB_DEPS_FALSE@SUPPORTFILES_LIBS = $(top_builddir)/lib/libcurl.la @CURL_NETWORK_LIBS@ @NSS_LIBS@
@USE_EXPLICIT_LIB_DEPS_TRUE@SUPPORTFILES_LIBS = $(top_builddir)/lib/libcurl.la @LIBCURL_LIBS@
@USE_EXPLICIT_LIB_DEPS_FALSE@TESTUTIL_LIBS = $(top_builddir)/lib/libcurl.la @CURL_NETWORK_AND_TIME_LIBS@ @NSS_LIBS@
@USE_EXPLICIT_LIB_DEPS_TRUE@TESTUTIL_LIBS = $(top_builddir)/lib/libcurl.la @LIBCURL_LIBS@

# Dependencies (may need to be overridden)
LDADD = $(SUPPORTFILES_LIBS)

#***************************************************************************
#                                  _   _ ____  _
#  Project                     ___| | | |  _ \| |
#                             / __| | | | |_) | |
#                            | (__| |_| |  _ <| |___
#                             \___|\___/|_| \_\_____|
#
# Copyright (C) 1998 - 2021, 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 https://curl.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
2227
2228
2229
2230
2231
2232
2233


2234
2235
2236
2237
2238
2239
2240
lib579_SOURCES = lib579.c $(SUPPORTFILES) $(MULTIBYTE)
lib579_CPPFLAGS = $(AM_CPPFLAGS)
lib582_SOURCES = lib582.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS) $(MULTIBYTE)
lib582_LDADD = $(TESTUTIL_LIBS)
lib582_CPPFLAGS = $(AM_CPPFLAGS)
lib583_SOURCES = lib583.c $(SUPPORTFILES)
lib583_CPPFLAGS = $(AM_CPPFLAGS)


lib585_SOURCES = lib500.c $(SUPPORTFILES) $(TESTUTIL) $(TSTTRACE) $(MULTIBYTE)
lib585_LDADD = $(TESTUTIL_LIBS)
lib585_CPPFLAGS = $(AM_CPPFLAGS) -DLIB585
lib586_SOURCES = lib586.c $(SUPPORTFILES)
lib586_CPPFLAGS = $(AM_CPPFLAGS)
lib587_SOURCES = lib554.c $(SUPPORTFILES)
lib587_CPPFLAGS = $(AM_CPPFLAGS) -DLIB587







>
>







2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
lib579_SOURCES = lib579.c $(SUPPORTFILES) $(MULTIBYTE)
lib579_CPPFLAGS = $(AM_CPPFLAGS)
lib582_SOURCES = lib582.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS) $(MULTIBYTE)
lib582_LDADD = $(TESTUTIL_LIBS)
lib582_CPPFLAGS = $(AM_CPPFLAGS)
lib583_SOURCES = lib583.c $(SUPPORTFILES)
lib583_CPPFLAGS = $(AM_CPPFLAGS)
lib584_SOURCES = lib589.c $(SUPPORTFILES)
lib584_CPPFLAGS = $(AM_CPPFLAGS) -DLIB584
lib585_SOURCES = lib500.c $(SUPPORTFILES) $(TESTUTIL) $(TSTTRACE) $(MULTIBYTE)
lib585_LDADD = $(TESTUTIL_LIBS)
lib585_CPPFLAGS = $(AM_CPPFLAGS) -DLIB585
lib586_SOURCES = lib586.c $(SUPPORTFILES)
lib586_CPPFLAGS = $(AM_CPPFLAGS)
lib587_SOURCES = lib554.c $(SUPPORTFILES)
lib587_CPPFLAGS = $(AM_CPPFLAGS) -DLIB587
2356
2357
2358
2359
2360
2361
2362
2363

2364
2365
2366
2367
2368
2369
2370
lib1517_CPPFLAGS = $(AM_CPPFLAGS) -DLIB1517
lib1518_SOURCES = lib1518.c $(SUPPORTFILES)
lib1518_CPPFLAGS = $(AM_CPPFLAGS)
lib1520_SOURCES = lib1520.c $(SUPPORTFILES)
lib1520_CPPFLAGS = $(AM_CPPFLAGS) -DLIB1520
nodist_lib1521_SOURCES = lib1521.c $(SUPPORTFILES)
lib1521_CPPFLAGS = $(AM_CPPFLAGS) -I$(srcdir)
lib1522_SOURCES = lib1522.c $(SUPPORTFILES)

lib1522_CPPFLAGS = $(AM_CPPFLAGS)
lib1523_SOURCES = lib1523.c $(SUPPORTFILES)
lib1523_CPPFLAGS = $(AM_CPPFLAGS)
lib1525_SOURCES = lib1525.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS)
lib1525_LDADD = $(TESTUTIL_LIBS)
lib1525_CPPFLAGS = $(AM_CPPFLAGS) -DLIB1525
lib1526_SOURCES = lib1526.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS)







|
>







2449
2450
2451
2452
2453
2454
2455
2456
2457
2458
2459
2460
2461
2462
2463
2464
lib1517_CPPFLAGS = $(AM_CPPFLAGS) -DLIB1517
lib1518_SOURCES = lib1518.c $(SUPPORTFILES)
lib1518_CPPFLAGS = $(AM_CPPFLAGS)
lib1520_SOURCES = lib1520.c $(SUPPORTFILES)
lib1520_CPPFLAGS = $(AM_CPPFLAGS) -DLIB1520
nodist_lib1521_SOURCES = lib1521.c $(SUPPORTFILES)
lib1521_CPPFLAGS = $(AM_CPPFLAGS) -I$(srcdir)
lib1522_SOURCES = lib1522.c $(SUPPORTFILES) $(TESTUTIL) $(TSTTRACE) 
lib1522_LDADD = $(TESTUTIL_LIBS)
lib1522_CPPFLAGS = $(AM_CPPFLAGS)
lib1523_SOURCES = lib1523.c $(SUPPORTFILES)
lib1523_CPPFLAGS = $(AM_CPPFLAGS)
lib1525_SOURCES = lib1525.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS)
lib1525_LDADD = $(TESTUTIL_LIBS)
lib1525_CPPFLAGS = $(AM_CPPFLAGS) -DLIB1525
lib1526_SOURCES = lib1526.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS)
2443
2444
2445
2446
2447
2448
2449


2450
2451
2452
2453
2454
2455
2456
lib1564_LDADD = $(TESTUTIL_LIBS)
lib1564_CPPFLAGS = $(AM_CPPFLAGS)
lib1565_SOURCES = lib1565.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS)
lib1565_LDADD = $(TESTUTIL_LIBS)
lib1565_CPPFLAGS = $(AM_CPPFLAGS)
lib1567_SOURCES = lib1567.c $(SUPPORTFILES)
lib1567_CPPFLAGS = $(AM_CPPFLAGS)


lib1591_SOURCES = lib1591.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS)
lib1591_LDADD = $(TESTUTIL_LIBS)
lib1591_CPPFLAGS = $(AM_CPPFLAGS) -DLIB1591
lib1592_SOURCES = lib1592.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS)
lib1592_LDADD = $(TESTUTIL_LIBS)
lib1592_CPPFLAGS = $(AM_CPPFLAGS) -DLIB1592
lib1593_SOURCES = lib1593.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS)







>
>







2537
2538
2539
2540
2541
2542
2543
2544
2545
2546
2547
2548
2549
2550
2551
2552
lib1564_LDADD = $(TESTUTIL_LIBS)
lib1564_CPPFLAGS = $(AM_CPPFLAGS)
lib1565_SOURCES = lib1565.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS)
lib1565_LDADD = $(TESTUTIL_LIBS)
lib1565_CPPFLAGS = $(AM_CPPFLAGS)
lib1567_SOURCES = lib1567.c $(SUPPORTFILES)
lib1567_CPPFLAGS = $(AM_CPPFLAGS)
lib1568_SOURCES = lib1568.c $(SUPPORTFILES)
lib1568_CPPFLAGS = $(AM_CPPFLAGS)
lib1591_SOURCES = lib1591.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS)
lib1591_LDADD = $(TESTUTIL_LIBS)
lib1591_CPPFLAGS = $(AM_CPPFLAGS) -DLIB1591
lib1592_SOURCES = lib1592.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS)
lib1592_LDADD = $(TESTUTIL_LIBS)
lib1592_CPPFLAGS = $(AM_CPPFLAGS) -DLIB1592
lib1593_SOURCES = lib1593.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS)
2483
2484
2485
2486
2487
2488
2489


















2490
2491
2492
2493
2494
2495
2496
lib1912_CPPFLAGS = $(AM_CPPFLAGS)
lib1913_SOURCES = lib1913.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS)
lib1913_LDADD = $(TESTUTIL_LIBS)
lib1913_CPPFLAGS = $(AM_CPPFLAGS)
lib1915_SOURCES = lib1915.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS)
lib1915_LDADD = $(TESTUTIL_LIBS)
lib1915_CPPFLAGS = $(AM_CPPFLAGS)


















lib3010_SOURCES = lib3010.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS)
lib3010_LDADD = $(TESTUTIL_LIBS)
lib3010_CPPFLAGS = $(AM_CPPFLAGS)
@BUILD_LIBHOSTNAME_FALSE@noinst_LTLIBRARIES = $(am__append_7)

# Makefile.inc provides the source defines (TESTUTIL, SUPPORTFILES,
# noinst_PROGRAMS, lib*_SOURCES, and lib*_CFLAGS)







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







2579
2580
2581
2582
2583
2584
2585
2586
2587
2588
2589
2590
2591
2592
2593
2594
2595
2596
2597
2598
2599
2600
2601
2602
2603
2604
2605
2606
2607
2608
2609
2610
lib1912_CPPFLAGS = $(AM_CPPFLAGS)
lib1913_SOURCES = lib1913.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS)
lib1913_LDADD = $(TESTUTIL_LIBS)
lib1913_CPPFLAGS = $(AM_CPPFLAGS)
lib1915_SOURCES = lib1915.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS)
lib1915_LDADD = $(TESTUTIL_LIBS)
lib1915_CPPFLAGS = $(AM_CPPFLAGS)
lib1916_SOURCES = lib1916.c $(SUPPORTFILES) $(WARNLESS)
lib1916_CPPFLAGS = $(AM_CPPFLAGS)
lib1917_SOURCES = lib1916.c $(SUPPORTFILES) $(WARNLESS)
lib1917_CPPFLAGS = $(AM_CPPFLAGS) -DLIB1917
lib1918_SOURCES = lib1918.c $(SUPPORTFILES) $(WARNLESS)
lib1918_CPPFLAGS = $(AM_CPPFLAGS)
lib1933_SOURCES = lib1933.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS)
lib1933_LDADD = $(TESTUTIL_LIBS)
lib1933_CPPFLAGS = $(AM_CPPFLAGS)
lib1934_SOURCES = lib1934.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS)
lib1934_LDADD = $(TESTUTIL_LIBS)
lib1934_CPPFLAGS = $(AM_CPPFLAGS)
lib1935_SOURCES = lib1935.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS)
lib1935_LDADD = $(TESTUTIL_LIBS)
lib1935_CPPFLAGS = $(AM_CPPFLAGS)
lib1936_SOURCES = lib1936.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS)
lib1936_LDADD = $(TESTUTIL_LIBS)
lib1936_CPPFLAGS = $(AM_CPPFLAGS)
lib3010_SOURCES = lib3010.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS)
lib3010_LDADD = $(TESTUTIL_LIBS)
lib3010_CPPFLAGS = $(AM_CPPFLAGS)
@BUILD_LIBHOSTNAME_FALSE@noinst_LTLIBRARIES = $(am__append_7)

# Makefile.inc provides the source defines (TESTUTIL, SUPPORTFILES,
# noinst_PROGRAMS, lib*_SOURCES, and lib*_CFLAGS)
2890
2891
2892
2893
2894
2895
2896




2897
2898
2899
2900
2901
2902
2903
lib1565$(EXEEXT): $(lib1565_OBJECTS) $(lib1565_DEPENDENCIES) $(EXTRA_lib1565_DEPENDENCIES) 
	@rm -f lib1565$(EXEEXT)
	$(AM_V_CCLD)$(LINK) $(lib1565_OBJECTS) $(lib1565_LDADD) $(LIBS)

lib1567$(EXEEXT): $(lib1567_OBJECTS) $(lib1567_DEPENDENCIES) $(EXTRA_lib1567_DEPENDENCIES) 
	@rm -f lib1567$(EXEEXT)
	$(AM_V_CCLD)$(LINK) $(lib1567_OBJECTS) $(lib1567_LDADD) $(LIBS)




../../lib/lib1591-warnless.$(OBJEXT): ../../lib/$(am__dirstamp) \
	../../lib/$(DEPDIR)/$(am__dirstamp)

lib1591$(EXEEXT): $(lib1591_OBJECTS) $(lib1591_DEPENDENCIES) $(EXTRA_lib1591_DEPENDENCIES) 
	@rm -f lib1591$(EXEEXT)
	$(AM_V_CCLD)$(LINK) $(lib1591_OBJECTS) $(lib1591_LDADD) $(LIBS)
../../lib/lib1592-warnless.$(OBJEXT): ../../lib/$(am__dirstamp) \







>
>
>
>







3004
3005
3006
3007
3008
3009
3010
3011
3012
3013
3014
3015
3016
3017
3018
3019
3020
3021
lib1565$(EXEEXT): $(lib1565_OBJECTS) $(lib1565_DEPENDENCIES) $(EXTRA_lib1565_DEPENDENCIES) 
	@rm -f lib1565$(EXEEXT)
	$(AM_V_CCLD)$(LINK) $(lib1565_OBJECTS) $(lib1565_LDADD) $(LIBS)

lib1567$(EXEEXT): $(lib1567_OBJECTS) $(lib1567_DEPENDENCIES) $(EXTRA_lib1567_DEPENDENCIES) 
	@rm -f lib1567$(EXEEXT)
	$(AM_V_CCLD)$(LINK) $(lib1567_OBJECTS) $(lib1567_LDADD) $(LIBS)

lib1568$(EXEEXT): $(lib1568_OBJECTS) $(lib1568_DEPENDENCIES) $(EXTRA_lib1568_DEPENDENCIES) 
	@rm -f lib1568$(EXEEXT)
	$(AM_V_CCLD)$(LINK) $(lib1568_OBJECTS) $(lib1568_LDADD) $(LIBS)
../../lib/lib1591-warnless.$(OBJEXT): ../../lib/$(am__dirstamp) \
	../../lib/$(DEPDIR)/$(am__dirstamp)

lib1591$(EXEEXT): $(lib1591_OBJECTS) $(lib1591_DEPENDENCIES) $(EXTRA_lib1591_DEPENDENCIES) 
	@rm -f lib1591$(EXEEXT)
	$(AM_V_CCLD)$(LINK) $(lib1591_OBJECTS) $(lib1591_LDADD) $(LIBS)
../../lib/lib1592-warnless.$(OBJEXT): ../../lib/$(am__dirstamp) \
2970
2971
2972
2973
2974
2975
2976










































2977
2978
2979
2980
2981
2982
2983
	$(AM_V_CCLD)$(LINK) $(lib1913_OBJECTS) $(lib1913_LDADD) $(LIBS)
../../lib/lib1915-warnless.$(OBJEXT): ../../lib/$(am__dirstamp) \
	../../lib/$(DEPDIR)/$(am__dirstamp)

lib1915$(EXEEXT): $(lib1915_OBJECTS) $(lib1915_DEPENDENCIES) $(EXTRA_lib1915_DEPENDENCIES) 
	@rm -f lib1915$(EXEEXT)
	$(AM_V_CCLD)$(LINK) $(lib1915_OBJECTS) $(lib1915_LDADD) $(LIBS)










































../../lib/lib3010-warnless.$(OBJEXT): ../../lib/$(am__dirstamp) \
	../../lib/$(DEPDIR)/$(am__dirstamp)

lib3010$(EXEEXT): $(lib3010_OBJECTS) $(lib3010_DEPENDENCIES) $(EXTRA_lib3010_DEPENDENCIES) 
	@rm -f lib3010$(EXEEXT)
	$(AM_V_CCLD)$(LINK) $(lib3010_OBJECTS) $(lib3010_LDADD) $(LIBS)
../../lib/lib500-curl_multibyte.$(OBJEXT): ../../lib/$(am__dirstamp) \







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







3088
3089
3090
3091
3092
3093
3094
3095
3096
3097
3098
3099
3100
3101
3102
3103
3104
3105
3106
3107
3108
3109
3110
3111
3112
3113
3114
3115
3116
3117
3118
3119
3120
3121
3122
3123
3124
3125
3126
3127
3128
3129
3130
3131
3132
3133
3134
3135
3136
3137
3138
3139
3140
3141
3142
3143
	$(AM_V_CCLD)$(LINK) $(lib1913_OBJECTS) $(lib1913_LDADD) $(LIBS)
../../lib/lib1915-warnless.$(OBJEXT): ../../lib/$(am__dirstamp) \
	../../lib/$(DEPDIR)/$(am__dirstamp)

lib1915$(EXEEXT): $(lib1915_OBJECTS) $(lib1915_DEPENDENCIES) $(EXTRA_lib1915_DEPENDENCIES) 
	@rm -f lib1915$(EXEEXT)
	$(AM_V_CCLD)$(LINK) $(lib1915_OBJECTS) $(lib1915_LDADD) $(LIBS)
../../lib/lib1916-warnless.$(OBJEXT): ../../lib/$(am__dirstamp) \
	../../lib/$(DEPDIR)/$(am__dirstamp)

lib1916$(EXEEXT): $(lib1916_OBJECTS) $(lib1916_DEPENDENCIES) $(EXTRA_lib1916_DEPENDENCIES) 
	@rm -f lib1916$(EXEEXT)
	$(AM_V_CCLD)$(LINK) $(lib1916_OBJECTS) $(lib1916_LDADD) $(LIBS)
../../lib/lib1917-warnless.$(OBJEXT): ../../lib/$(am__dirstamp) \
	../../lib/$(DEPDIR)/$(am__dirstamp)

lib1917$(EXEEXT): $(lib1917_OBJECTS) $(lib1917_DEPENDENCIES) $(EXTRA_lib1917_DEPENDENCIES) 
	@rm -f lib1917$(EXEEXT)
	$(AM_V_CCLD)$(LINK) $(lib1917_OBJECTS) $(lib1917_LDADD) $(LIBS)
../../lib/lib1918-warnless.$(OBJEXT): ../../lib/$(am__dirstamp) \
	../../lib/$(DEPDIR)/$(am__dirstamp)

lib1918$(EXEEXT): $(lib1918_OBJECTS) $(lib1918_DEPENDENCIES) $(EXTRA_lib1918_DEPENDENCIES) 
	@rm -f lib1918$(EXEEXT)
	$(AM_V_CCLD)$(LINK) $(lib1918_OBJECTS) $(lib1918_LDADD) $(LIBS)
../../lib/lib1933-warnless.$(OBJEXT): ../../lib/$(am__dirstamp) \
	../../lib/$(DEPDIR)/$(am__dirstamp)

lib1933$(EXEEXT): $(lib1933_OBJECTS) $(lib1933_DEPENDENCIES) $(EXTRA_lib1933_DEPENDENCIES) 
	@rm -f lib1933$(EXEEXT)
	$(AM_V_CCLD)$(LINK) $(lib1933_OBJECTS) $(lib1933_LDADD) $(LIBS)
../../lib/lib1934-warnless.$(OBJEXT): ../../lib/$(am__dirstamp) \
	../../lib/$(DEPDIR)/$(am__dirstamp)

lib1934$(EXEEXT): $(lib1934_OBJECTS) $(lib1934_DEPENDENCIES) $(EXTRA_lib1934_DEPENDENCIES) 
	@rm -f lib1934$(EXEEXT)
	$(AM_V_CCLD)$(LINK) $(lib1934_OBJECTS) $(lib1934_LDADD) $(LIBS)
../../lib/lib1935-warnless.$(OBJEXT): ../../lib/$(am__dirstamp) \
	../../lib/$(DEPDIR)/$(am__dirstamp)

lib1935$(EXEEXT): $(lib1935_OBJECTS) $(lib1935_DEPENDENCIES) $(EXTRA_lib1935_DEPENDENCIES) 
	@rm -f lib1935$(EXEEXT)
	$(AM_V_CCLD)$(LINK) $(lib1935_OBJECTS) $(lib1935_LDADD) $(LIBS)
../../lib/lib1936-warnless.$(OBJEXT): ../../lib/$(am__dirstamp) \
	../../lib/$(DEPDIR)/$(am__dirstamp)

lib1936$(EXEEXT): $(lib1936_OBJECTS) $(lib1936_DEPENDENCIES) $(EXTRA_lib1936_DEPENDENCIES) 
	@rm -f lib1936$(EXEEXT)
	$(AM_V_CCLD)$(LINK) $(lib1936_OBJECTS) $(lib1936_LDADD) $(LIBS)
../../lib/lib3010-warnless.$(OBJEXT): ../../lib/$(am__dirstamp) \
	../../lib/$(DEPDIR)/$(am__dirstamp)

lib3010$(EXEEXT): $(lib3010_OBJECTS) $(lib3010_DEPENDENCIES) $(EXTRA_lib3010_DEPENDENCIES) 
	@rm -f lib3010$(EXEEXT)
	$(AM_V_CCLD)$(LINK) $(lib3010_OBJECTS) $(lib3010_LDADD) $(LIBS)
../../lib/lib500-curl_multibyte.$(OBJEXT): ../../lib/$(am__dirstamp) \
3322
3323
3324
3325
3326
3327
3328




3329
3330
3331
3332
3333
3334
3335
lib582$(EXEEXT): $(lib582_OBJECTS) $(lib582_DEPENDENCIES) $(EXTRA_lib582_DEPENDENCIES) 
	@rm -f lib582$(EXEEXT)
	$(AM_V_CCLD)$(LINK) $(lib582_OBJECTS) $(lib582_LDADD) $(LIBS)

lib583$(EXEEXT): $(lib583_OBJECTS) $(lib583_DEPENDENCIES) $(EXTRA_lib583_DEPENDENCIES) 
	@rm -f lib583$(EXEEXT)
	$(AM_V_CCLD)$(LINK) $(lib583_OBJECTS) $(lib583_LDADD) $(LIBS)




../../lib/lib585-curl_multibyte.$(OBJEXT): ../../lib/$(am__dirstamp) \
	../../lib/$(DEPDIR)/$(am__dirstamp)

lib585$(EXEEXT): $(lib585_OBJECTS) $(lib585_DEPENDENCIES) $(EXTRA_lib585_DEPENDENCIES) 
	@rm -f lib585$(EXEEXT)
	$(AM_V_CCLD)$(LINK) $(lib585_OBJECTS) $(lib585_LDADD) $(LIBS)








>
>
>
>







3482
3483
3484
3485
3486
3487
3488
3489
3490
3491
3492
3493
3494
3495
3496
3497
3498
3499
lib582$(EXEEXT): $(lib582_OBJECTS) $(lib582_DEPENDENCIES) $(EXTRA_lib582_DEPENDENCIES) 
	@rm -f lib582$(EXEEXT)
	$(AM_V_CCLD)$(LINK) $(lib582_OBJECTS) $(lib582_LDADD) $(LIBS)

lib583$(EXEEXT): $(lib583_OBJECTS) $(lib583_DEPENDENCIES) $(EXTRA_lib583_DEPENDENCIES) 
	@rm -f lib583$(EXEEXT)
	$(AM_V_CCLD)$(LINK) $(lib583_OBJECTS) $(lib583_LDADD) $(LIBS)

lib584$(EXEEXT): $(lib584_OBJECTS) $(lib584_DEPENDENCIES) $(EXTRA_lib584_DEPENDENCIES) 
	@rm -f lib584$(EXEEXT)
	$(AM_V_CCLD)$(LINK) $(lib584_OBJECTS) $(lib584_LDADD) $(LIBS)
../../lib/lib585-curl_multibyte.$(OBJEXT): ../../lib/$(am__dirstamp) \
	../../lib/$(DEPDIR)/$(am__dirstamp)

lib585$(EXEEXT): $(lib585_OBJECTS) $(lib585_DEPENDENCIES) $(EXTRA_lib585_DEPENDENCIES) 
	@rm -f lib585$(EXEEXT)
	$(AM_V_CCLD)$(LINK) $(lib585_OBJECTS) $(lib585_LDADD) $(LIBS)

3538
3539
3540
3541
3542
3543
3544







3545
3546
3547
3548
3549
3550
3551
@AMDEP_TRUE@@am__include@ @am__quote@../../lib/$(DEPDIR)/lib1907-warnless.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@../../lib/$(DEPDIR)/lib1908-warnless.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@../../lib/$(DEPDIR)/lib1910-warnless.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@../../lib/$(DEPDIR)/lib1911-warnless.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@../../lib/$(DEPDIR)/lib1912-warnless.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@../../lib/$(DEPDIR)/lib1913-warnless.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@../../lib/$(DEPDIR)/lib1915-warnless.Po@am__quote@ # am--include-marker







@AMDEP_TRUE@@am__include@ @am__quote@../../lib/$(DEPDIR)/lib3010-warnless.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@../../lib/$(DEPDIR)/lib500-curl_multibyte.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@../../lib/$(DEPDIR)/lib502-warnless.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@../../lib/$(DEPDIR)/lib503-warnless.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@../../lib/$(DEPDIR)/lib504-warnless.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@../../lib/$(DEPDIR)/lib505-curl_multibyte.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@../../lib/$(DEPDIR)/lib507-warnless.Po@am__quote@ # am--include-marker







>
>
>
>
>
>
>







3702
3703
3704
3705
3706
3707
3708
3709
3710
3711
3712
3713
3714
3715
3716
3717
3718
3719
3720
3721
3722
@AMDEP_TRUE@@am__include@ @am__quote@../../lib/$(DEPDIR)/lib1907-warnless.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@../../lib/$(DEPDIR)/lib1908-warnless.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@../../lib/$(DEPDIR)/lib1910-warnless.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@../../lib/$(DEPDIR)/lib1911-warnless.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@../../lib/$(DEPDIR)/lib1912-warnless.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@../../lib/$(DEPDIR)/lib1913-warnless.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@../../lib/$(DEPDIR)/lib1915-warnless.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@../../lib/$(DEPDIR)/lib1916-warnless.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@../../lib/$(DEPDIR)/lib1917-warnless.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@../../lib/$(DEPDIR)/lib1918-warnless.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@../../lib/$(DEPDIR)/lib1933-warnless.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@../../lib/$(DEPDIR)/lib1934-warnless.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@../../lib/$(DEPDIR)/lib1935-warnless.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@../../lib/$(DEPDIR)/lib1936-warnless.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@../../lib/$(DEPDIR)/lib3010-warnless.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@../../lib/$(DEPDIR)/lib500-curl_multibyte.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@../../lib/$(DEPDIR)/lib502-warnless.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@../../lib/$(DEPDIR)/lib503-warnless.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@../../lib/$(DEPDIR)/lib504-warnless.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@../../lib/$(DEPDIR)/lib505-curl_multibyte.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@../../lib/$(DEPDIR)/lib507-warnless.Po@am__quote@ # am--include-marker
3656
3657
3658
3659
3660
3661
3662


3663
3664
3665
3666
3667
3668
3669
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lib1518-lib1518.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lib1520-first.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lib1520-lib1520.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lib1521-first.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lib1521-lib1521.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lib1522-first.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lib1522-lib1522.Po@am__quote@ # am--include-marker


@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lib1523-first.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lib1523-lib1523.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lib1525-first.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lib1525-lib1525.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lib1525-testutil.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lib1526-first.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lib1526-lib1526.Po@am__quote@ # am--include-marker







>
>







3827
3828
3829
3830
3831
3832
3833
3834
3835
3836
3837
3838
3839
3840
3841
3842
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lib1518-lib1518.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lib1520-first.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lib1520-lib1520.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lib1521-first.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lib1521-lib1521.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lib1522-first.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lib1522-lib1522.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lib1522-testtrace.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lib1522-testutil.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lib1523-first.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lib1523-lib1523.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lib1525-first.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lib1525-lib1525.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lib1525-testutil.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lib1526-first.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lib1526-lib1526.Po@am__quote@ # am--include-marker
3738
3739
3740
3741
3742
3743
3744


3745
3746
3747
3748
3749
3750
3751
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lib1564-lib1564.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lib1564-testutil.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lib1565-first.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lib1565-lib1565.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lib1565-testutil.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lib1567-first.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lib1567-lib1567.Po@am__quote@ # am--include-marker


@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lib1591-first.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lib1591-lib1591.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lib1591-testutil.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lib1592-first.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lib1592-lib1592.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lib1592-testutil.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lib1593.Po@am__quote@ # am--include-marker







>
>







3911
3912
3913
3914
3915
3916
3917
3918
3919
3920
3921
3922
3923
3924
3925
3926
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lib1564-lib1564.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lib1564-testutil.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lib1565-first.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lib1565-lib1565.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lib1565-testutil.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lib1567-first.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lib1567-lib1567.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lib1568-first.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lib1568-lib1568.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lib1591-first.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lib1591-lib1591.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lib1591-testutil.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lib1592-first.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lib1592-lib1592.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lib1592-testutil.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lib1593.Po@am__quote@ # am--include-marker
3776
3777
3778
3779
3780
3781
3782


















3783
3784
3785
3786
3787
3788
3789
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lib1912-testutil.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lib1913-first.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lib1913-lib1913.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lib1913-testutil.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lib1915-first.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lib1915-lib1915.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lib1915-testutil.Po@am__quote@ # am--include-marker


















@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lib3010-first.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lib3010-lib3010.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lib3010-testutil.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lib500-first.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lib500-lib500.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lib500-testtrace.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lib500-testutil.Po@am__quote@ # am--include-marker







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







3951
3952
3953
3954
3955
3956
3957
3958
3959
3960
3961
3962
3963
3964
3965
3966
3967
3968
3969
3970
3971
3972
3973
3974
3975
3976
3977
3978
3979
3980
3981
3982
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lib1912-testutil.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lib1913-first.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lib1913-lib1913.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lib1913-testutil.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lib1915-first.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lib1915-lib1915.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lib1915-testutil.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lib1916-first.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lib1916-lib1916.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lib1917-first.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lib1917-lib1916.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lib1918-first.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lib1918-lib1918.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lib1933-first.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lib1933-lib1933.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lib1933-testutil.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lib1934-first.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lib1934-lib1934.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lib1934-testutil.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lib1935-first.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lib1935-lib1935.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lib1935-testutil.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lib1936-first.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lib1936-lib1936.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lib1936-testutil.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lib3010-first.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lib3010-lib3010.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lib3010-testutil.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lib500-first.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lib500-lib500.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lib500-testtrace.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lib500-testutil.Po@am__quote@ # am--include-marker
3935
3936
3937
3938
3939
3940
3941


3942
3943
3944
3945
3946
3947
3948
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lib579-first.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lib579-lib579.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lib582-first.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lib582-lib582.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lib582-testutil.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lib583-first.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lib583-lib583.Po@am__quote@ # am--include-marker


@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lib585-first.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lib585-lib500.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lib585-testtrace.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lib585-testutil.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lib586-first.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lib586-lib586.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lib587-first.Po@am__quote@ # am--include-marker







>
>







4128
4129
4130
4131
4132
4133
4134
4135
4136
4137
4138
4139
4140
4141
4142
4143
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lib579-first.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lib579-lib579.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lib582-first.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lib582-lib582.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lib582-testutil.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lib583-first.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lib583-lib583.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lib584-first.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lib584-lib589.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lib585-first.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lib585-lib500.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lib585-testtrace.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lib585-testutil.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lib586-first.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lib586-lib586.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lib587-first.Po@am__quote@ # am--include-marker
5235
5236
5237
5238
5239
5240
5241




























5242
5243
5244
5245
5246
5247
5248
lib1522-first.obj: first.c
@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib1522_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib1522-first.obj -MD -MP -MF $(DEPDIR)/lib1522-first.Tpo -c -o lib1522-first.obj `if test -f 'first.c'; then $(CYGPATH_W) 'first.c'; else $(CYGPATH_W) '$(srcdir)/first.c'; fi`
@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/lib1522-first.Tpo $(DEPDIR)/lib1522-first.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='first.c' object='lib1522-first.obj' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib1522_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib1522-first.obj `if test -f 'first.c'; then $(CYGPATH_W) 'first.c'; else $(CYGPATH_W) '$(srcdir)/first.c'; fi`





























lib1523-lib1523.o: lib1523.c
@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib1523_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib1523-lib1523.o -MD -MP -MF $(DEPDIR)/lib1523-lib1523.Tpo -c -o lib1523-lib1523.o `test -f 'lib1523.c' || echo '$(srcdir)/'`lib1523.c
@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/lib1523-lib1523.Tpo $(DEPDIR)/lib1523-lib1523.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='lib1523.c' object='lib1523-lib1523.o' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib1523_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib1523-lib1523.o `test -f 'lib1523.c' || echo '$(srcdir)/'`lib1523.c








>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







5430
5431
5432
5433
5434
5435
5436
5437
5438
5439
5440
5441
5442
5443
5444
5445
5446
5447
5448
5449
5450
5451
5452
5453
5454
5455
5456
5457
5458
5459
5460
5461
5462
5463
5464
5465
5466
5467
5468
5469
5470
5471
lib1522-first.obj: first.c
@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib1522_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib1522-first.obj -MD -MP -MF $(DEPDIR)/lib1522-first.Tpo -c -o lib1522-first.obj `if test -f 'first.c'; then $(CYGPATH_W) 'first.c'; else $(CYGPATH_W) '$(srcdir)/first.c'; fi`
@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/lib1522-first.Tpo $(DEPDIR)/lib1522-first.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='first.c' object='lib1522-first.obj' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib1522_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib1522-first.obj `if test -f 'first.c'; then $(CYGPATH_W) 'first.c'; else $(CYGPATH_W) '$(srcdir)/first.c'; fi`

lib1522-testutil.o: testutil.c
@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib1522_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib1522-testutil.o -MD -MP -MF $(DEPDIR)/lib1522-testutil.Tpo -c -o lib1522-testutil.o `test -f 'testutil.c' || echo '$(srcdir)/'`testutil.c
@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/lib1522-testutil.Tpo $(DEPDIR)/lib1522-testutil.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='testutil.c' object='lib1522-testutil.o' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib1522_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib1522-testutil.o `test -f 'testutil.c' || echo '$(srcdir)/'`testutil.c

lib1522-testutil.obj: testutil.c
@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib1522_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib1522-testutil.obj -MD -MP -MF $(DEPDIR)/lib1522-testutil.Tpo -c -o lib1522-testutil.obj `if test -f 'testutil.c'; then $(CYGPATH_W) 'testutil.c'; else $(CYGPATH_W) '$(srcdir)/testutil.c'; fi`
@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/lib1522-testutil.Tpo $(DEPDIR)/lib1522-testutil.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='testutil.c' object='lib1522-testutil.obj' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib1522_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib1522-testutil.obj `if test -f 'testutil.c'; then $(CYGPATH_W) 'testutil.c'; else $(CYGPATH_W) '$(srcdir)/testutil.c'; fi`

lib1522-testtrace.o: testtrace.c
@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib1522_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib1522-testtrace.o -MD -MP -MF $(DEPDIR)/lib1522-testtrace.Tpo -c -o lib1522-testtrace.o `test -f 'testtrace.c' || echo '$(srcdir)/'`testtrace.c
@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/lib1522-testtrace.Tpo $(DEPDIR)/lib1522-testtrace.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='testtrace.c' object='lib1522-testtrace.o' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib1522_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib1522-testtrace.o `test -f 'testtrace.c' || echo '$(srcdir)/'`testtrace.c

lib1522-testtrace.obj: testtrace.c
@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib1522_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib1522-testtrace.obj -MD -MP -MF $(DEPDIR)/lib1522-testtrace.Tpo -c -o lib1522-testtrace.obj `if test -f 'testtrace.c'; then $(CYGPATH_W) 'testtrace.c'; else $(CYGPATH_W) '$(srcdir)/testtrace.c'; fi`
@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/lib1522-testtrace.Tpo $(DEPDIR)/lib1522-testtrace.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='testtrace.c' object='lib1522-testtrace.obj' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib1522_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib1522-testtrace.obj `if test -f 'testtrace.c'; then $(CYGPATH_W) 'testtrace.c'; else $(CYGPATH_W) '$(srcdir)/testtrace.c'; fi`

lib1523-lib1523.o: lib1523.c
@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib1523_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib1523-lib1523.o -MD -MP -MF $(DEPDIR)/lib1523-lib1523.Tpo -c -o lib1523-lib1523.o `test -f 'lib1523.c' || echo '$(srcdir)/'`lib1523.c
@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/lib1523-lib1523.Tpo $(DEPDIR)/lib1523-lib1523.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='lib1523.c' object='lib1523-lib1523.o' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib1523_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib1523-lib1523.o `test -f 'lib1523.c' || echo '$(srcdir)/'`lib1523.c

6635
6636
6637
6638
6639
6640
6641




























6642
6643
6644
6645
6646
6647
6648
lib1567-first.obj: first.c
@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib1567_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib1567-first.obj -MD -MP -MF $(DEPDIR)/lib1567-first.Tpo -c -o lib1567-first.obj `if test -f 'first.c'; then $(CYGPATH_W) 'first.c'; else $(CYGPATH_W) '$(srcdir)/first.c'; fi`
@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/lib1567-first.Tpo $(DEPDIR)/lib1567-first.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='first.c' object='lib1567-first.obj' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib1567_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib1567-first.obj `if test -f 'first.c'; then $(CYGPATH_W) 'first.c'; else $(CYGPATH_W) '$(srcdir)/first.c'; fi`





























lib1591-lib1591.o: lib1591.c
@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib1591_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib1591-lib1591.o -MD -MP -MF $(DEPDIR)/lib1591-lib1591.Tpo -c -o lib1591-lib1591.o `test -f 'lib1591.c' || echo '$(srcdir)/'`lib1591.c
@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/lib1591-lib1591.Tpo $(DEPDIR)/lib1591-lib1591.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='lib1591.c' object='lib1591-lib1591.o' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib1591_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib1591-lib1591.o `test -f 'lib1591.c' || echo '$(srcdir)/'`lib1591.c








>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







6858
6859
6860
6861
6862
6863
6864
6865
6866
6867
6868
6869
6870
6871
6872
6873
6874
6875
6876
6877
6878
6879
6880
6881
6882
6883
6884
6885
6886
6887
6888
6889
6890
6891
6892
6893
6894
6895
6896
6897
6898
6899
lib1567-first.obj: first.c
@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib1567_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib1567-first.obj -MD -MP -MF $(DEPDIR)/lib1567-first.Tpo -c -o lib1567-first.obj `if test -f 'first.c'; then $(CYGPATH_W) 'first.c'; else $(CYGPATH_W) '$(srcdir)/first.c'; fi`
@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/lib1567-first.Tpo $(DEPDIR)/lib1567-first.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='first.c' object='lib1567-first.obj' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib1567_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib1567-first.obj `if test -f 'first.c'; then $(CYGPATH_W) 'first.c'; else $(CYGPATH_W) '$(srcdir)/first.c'; fi`

lib1568-lib1568.o: lib1568.c
@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib1568_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib1568-lib1568.o -MD -MP -MF $(DEPDIR)/lib1568-lib1568.Tpo -c -o lib1568-lib1568.o `test -f 'lib1568.c' || echo '$(srcdir)/'`lib1568.c
@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/lib1568-lib1568.Tpo $(DEPDIR)/lib1568-lib1568.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='lib1568.c' object='lib1568-lib1568.o' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib1568_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib1568-lib1568.o `test -f 'lib1568.c' || echo '$(srcdir)/'`lib1568.c

lib1568-lib1568.obj: lib1568.c
@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib1568_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib1568-lib1568.obj -MD -MP -MF $(DEPDIR)/lib1568-lib1568.Tpo -c -o lib1568-lib1568.obj `if test -f 'lib1568.c'; then $(CYGPATH_W) 'lib1568.c'; else $(CYGPATH_W) '$(srcdir)/lib1568.c'; fi`
@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/lib1568-lib1568.Tpo $(DEPDIR)/lib1568-lib1568.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='lib1568.c' object='lib1568-lib1568.obj' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib1568_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib1568-lib1568.obj `if test -f 'lib1568.c'; then $(CYGPATH_W) 'lib1568.c'; else $(CYGPATH_W) '$(srcdir)/lib1568.c'; fi`

lib1568-first.o: first.c
@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib1568_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib1568-first.o -MD -MP -MF $(DEPDIR)/lib1568-first.Tpo -c -o lib1568-first.o `test -f 'first.c' || echo '$(srcdir)/'`first.c
@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/lib1568-first.Tpo $(DEPDIR)/lib1568-first.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='first.c' object='lib1568-first.o' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib1568_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib1568-first.o `test -f 'first.c' || echo '$(srcdir)/'`first.c

lib1568-first.obj: first.c
@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib1568_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib1568-first.obj -MD -MP -MF $(DEPDIR)/lib1568-first.Tpo -c -o lib1568-first.obj `if test -f 'first.c'; then $(CYGPATH_W) 'first.c'; else $(CYGPATH_W) '$(srcdir)/first.c'; fi`
@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/lib1568-first.Tpo $(DEPDIR)/lib1568-first.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='first.c' object='lib1568-first.obj' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib1568_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib1568-first.obj `if test -f 'first.c'; then $(CYGPATH_W) 'first.c'; else $(CYGPATH_W) '$(srcdir)/first.c'; fi`

lib1591-lib1591.o: lib1591.c
@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib1591_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib1591-lib1591.o -MD -MP -MF $(DEPDIR)/lib1591-lib1591.Tpo -c -o lib1591-lib1591.o `test -f 'lib1591.c' || echo '$(srcdir)/'`lib1591.c
@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/lib1591-lib1591.Tpo $(DEPDIR)/lib1591-lib1591.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='lib1591.c' object='lib1591-lib1591.o' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib1591_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib1591-lib1591.o `test -f 'lib1591.c' || echo '$(srcdir)/'`lib1591.c

7307
7308
7309
7310
7311
7312
7313






























































































































































































































































































































































7314
7315
7316
7317
7318
7319
7320
../../lib/lib1915-warnless.obj: ../../lib/warnless.c
@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib1915_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ../../lib/lib1915-warnless.obj -MD -MP -MF ../../lib/$(DEPDIR)/lib1915-warnless.Tpo -c -o ../../lib/lib1915-warnless.obj `if test -f '../../lib/warnless.c'; then $(CYGPATH_W) '../../lib/warnless.c'; else $(CYGPATH_W) '$(srcdir)/../../lib/warnless.c'; fi`
@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) ../../lib/$(DEPDIR)/lib1915-warnless.Tpo ../../lib/$(DEPDIR)/lib1915-warnless.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='../../lib/warnless.c' object='../../lib/lib1915-warnless.obj' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib1915_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ../../lib/lib1915-warnless.obj `if test -f '../../lib/warnless.c'; then $(CYGPATH_W) '../../lib/warnless.c'; else $(CYGPATH_W) '$(srcdir)/../../lib/warnless.c'; fi`































































































































































































































































































































































lib3010-lib3010.o: lib3010.c
@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib3010_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib3010-lib3010.o -MD -MP -MF $(DEPDIR)/lib3010-lib3010.Tpo -c -o lib3010-lib3010.o `test -f 'lib3010.c' || echo '$(srcdir)/'`lib3010.c
@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/lib3010-lib3010.Tpo $(DEPDIR)/lib3010-lib3010.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='lib3010.c' object='lib3010-lib3010.o' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib3010_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib3010-lib3010.o `test -f 'lib3010.c' || echo '$(srcdir)/'`lib3010.c








>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







7558
7559
7560
7561
7562
7563
7564
7565
7566
7567
7568
7569
7570
7571
7572
7573
7574
7575
7576
7577
7578
7579
7580
7581
7582
7583
7584
7585
7586
7587
7588
7589
7590
7591
7592
7593
7594
7595
7596
7597
7598
7599
7600
7601
7602
7603
7604
7605
7606
7607
7608
7609
7610
7611
7612
7613
7614
7615
7616
7617
7618
7619
7620
7621
7622
7623
7624
7625
7626
7627
7628
7629
7630
7631
7632
7633
7634
7635
7636
7637
7638
7639
7640
7641
7642
7643
7644
7645
7646
7647
7648
7649
7650
7651
7652
7653
7654
7655
7656
7657
7658
7659
7660
7661
7662
7663
7664
7665
7666
7667
7668
7669
7670
7671
7672
7673
7674
7675
7676
7677
7678
7679
7680
7681
7682
7683
7684
7685
7686
7687
7688
7689
7690
7691
7692
7693
7694
7695
7696
7697
7698
7699
7700
7701
7702
7703
7704
7705
7706
7707
7708
7709
7710
7711
7712
7713
7714
7715
7716
7717
7718
7719
7720
7721
7722
7723
7724
7725
7726
7727
7728
7729
7730
7731
7732
7733
7734
7735
7736
7737
7738
7739
7740
7741
7742
7743
7744
7745
7746
7747
7748
7749
7750
7751
7752
7753
7754
7755
7756
7757
7758
7759
7760
7761
7762
7763
7764
7765
7766
7767
7768
7769
7770
7771
7772
7773
7774
7775
7776
7777
7778
7779
7780
7781
7782
7783
7784
7785
7786
7787
7788
7789
7790
7791
7792
7793
7794
7795
7796
7797
7798
7799
7800
7801
7802
7803
7804
7805
7806
7807
7808
7809
7810
7811
7812
7813
7814
7815
7816
7817
7818
7819
7820
7821
7822
7823
7824
7825
7826
7827
7828
7829
7830
7831
7832
7833
7834
7835
7836
7837
7838
7839
7840
7841
7842
7843
7844
7845
7846
7847
7848
7849
7850
7851
7852
7853
7854
7855
7856
7857
7858
7859
7860
7861
7862
7863
7864
7865
7866
7867
7868
7869
7870
7871
7872
7873
7874
7875
7876
7877
7878
7879
7880
7881
7882
7883
7884
7885
7886
7887
7888
7889
7890
7891
7892
7893
7894
7895
7896
7897
7898
7899
7900
7901
7902
7903
7904
7905
7906
7907
7908
7909
7910
7911
7912
7913
7914
7915
7916
7917
7918
7919
7920
7921
../../lib/lib1915-warnless.obj: ../../lib/warnless.c
@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib1915_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ../../lib/lib1915-warnless.obj -MD -MP -MF ../../lib/$(DEPDIR)/lib1915-warnless.Tpo -c -o ../../lib/lib1915-warnless.obj `if test -f '../../lib/warnless.c'; then $(CYGPATH_W) '../../lib/warnless.c'; else $(CYGPATH_W) '$(srcdir)/../../lib/warnless.c'; fi`
@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) ../../lib/$(DEPDIR)/lib1915-warnless.Tpo ../../lib/$(DEPDIR)/lib1915-warnless.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='../../lib/warnless.c' object='../../lib/lib1915-warnless.obj' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib1915_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ../../lib/lib1915-warnless.obj `if test -f '../../lib/warnless.c'; then $(CYGPATH_W) '../../lib/warnless.c'; else $(CYGPATH_W) '$(srcdir)/../../lib/warnless.c'; fi`

lib1916-lib1916.o: lib1916.c
@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib1916_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib1916-lib1916.o -MD -MP -MF $(DEPDIR)/lib1916-lib1916.Tpo -c -o lib1916-lib1916.o `test -f 'lib1916.c' || echo '$(srcdir)/'`lib1916.c
@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/lib1916-lib1916.Tpo $(DEPDIR)/lib1916-lib1916.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='lib1916.c' object='lib1916-lib1916.o' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib1916_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib1916-lib1916.o `test -f 'lib1916.c' || echo '$(srcdir)/'`lib1916.c

lib1916-lib1916.obj: lib1916.c
@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib1916_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib1916-lib1916.obj -MD -MP -MF $(DEPDIR)/lib1916-lib1916.Tpo -c -o lib1916-lib1916.obj `if test -f 'lib1916.c'; then $(CYGPATH_W) 'lib1916.c'; else $(CYGPATH_W) '$(srcdir)/lib1916.c'; fi`
@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/lib1916-lib1916.Tpo $(DEPDIR)/lib1916-lib1916.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='lib1916.c' object='lib1916-lib1916.obj' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib1916_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib1916-lib1916.obj `if test -f 'lib1916.c'; then $(CYGPATH_W) 'lib1916.c'; else $(CYGPATH_W) '$(srcdir)/lib1916.c'; fi`

lib1916-first.o: first.c
@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib1916_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib1916-first.o -MD -MP -MF $(DEPDIR)/lib1916-first.Tpo -c -o lib1916-first.o `test -f 'first.c' || echo '$(srcdir)/'`first.c
@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/lib1916-first.Tpo $(DEPDIR)/lib1916-first.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='first.c' object='lib1916-first.o' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib1916_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib1916-first.o `test -f 'first.c' || echo '$(srcdir)/'`first.c

lib1916-first.obj: first.c
@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib1916_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib1916-first.obj -MD -MP -MF $(DEPDIR)/lib1916-first.Tpo -c -o lib1916-first.obj `if test -f 'first.c'; then $(CYGPATH_W) 'first.c'; else $(CYGPATH_W) '$(srcdir)/first.c'; fi`
@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/lib1916-first.Tpo $(DEPDIR)/lib1916-first.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='first.c' object='lib1916-first.obj' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib1916_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib1916-first.obj `if test -f 'first.c'; then $(CYGPATH_W) 'first.c'; else $(CYGPATH_W) '$(srcdir)/first.c'; fi`

../../lib/lib1916-warnless.o: ../../lib/warnless.c
@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib1916_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ../../lib/lib1916-warnless.o -MD -MP -MF ../../lib/$(DEPDIR)/lib1916-warnless.Tpo -c -o ../../lib/lib1916-warnless.o `test -f '../../lib/warnless.c' || echo '$(srcdir)/'`../../lib/warnless.c
@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) ../../lib/$(DEPDIR)/lib1916-warnless.Tpo ../../lib/$(DEPDIR)/lib1916-warnless.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='../../lib/warnless.c' object='../../lib/lib1916-warnless.o' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib1916_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ../../lib/lib1916-warnless.o `test -f '../../lib/warnless.c' || echo '$(srcdir)/'`../../lib/warnless.c

../../lib/lib1916-warnless.obj: ../../lib/warnless.c
@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib1916_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ../../lib/lib1916-warnless.obj -MD -MP -MF ../../lib/$(DEPDIR)/lib1916-warnless.Tpo -c -o ../../lib/lib1916-warnless.obj `if test -f '../../lib/warnless.c'; then $(CYGPATH_W) '../../lib/warnless.c'; else $(CYGPATH_W) '$(srcdir)/../../lib/warnless.c'; fi`
@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) ../../lib/$(DEPDIR)/lib1916-warnless.Tpo ../../lib/$(DEPDIR)/lib1916-warnless.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='../../lib/warnless.c' object='../../lib/lib1916-warnless.obj' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib1916_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ../../lib/lib1916-warnless.obj `if test -f '../../lib/warnless.c'; then $(CYGPATH_W) '../../lib/warnless.c'; else $(CYGPATH_W) '$(srcdir)/../../lib/warnless.c'; fi`

lib1917-lib1916.o: lib1916.c
@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib1917_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib1917-lib1916.o -MD -MP -MF $(DEPDIR)/lib1917-lib1916.Tpo -c -o lib1917-lib1916.o `test -f 'lib1916.c' || echo '$(srcdir)/'`lib1916.c
@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/lib1917-lib1916.Tpo $(DEPDIR)/lib1917-lib1916.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='lib1916.c' object='lib1917-lib1916.o' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib1917_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib1917-lib1916.o `test -f 'lib1916.c' || echo '$(srcdir)/'`lib1916.c

lib1917-lib1916.obj: lib1916.c
@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib1917_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib1917-lib1916.obj -MD -MP -MF $(DEPDIR)/lib1917-lib1916.Tpo -c -o lib1917-lib1916.obj `if test -f 'lib1916.c'; then $(CYGPATH_W) 'lib1916.c'; else $(CYGPATH_W) '$(srcdir)/lib1916.c'; fi`
@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/lib1917-lib1916.Tpo $(DEPDIR)/lib1917-lib1916.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='lib1916.c' object='lib1917-lib1916.obj' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib1917_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib1917-lib1916.obj `if test -f 'lib1916.c'; then $(CYGPATH_W) 'lib1916.c'; else $(CYGPATH_W) '$(srcdir)/lib1916.c'; fi`

lib1917-first.o: first.c
@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib1917_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib1917-first.o -MD -MP -MF $(DEPDIR)/lib1917-first.Tpo -c -o lib1917-first.o `test -f 'first.c' || echo '$(srcdir)/'`first.c
@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/lib1917-first.Tpo $(DEPDIR)/lib1917-first.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='first.c' object='lib1917-first.o' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib1917_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib1917-first.o `test -f 'first.c' || echo '$(srcdir)/'`first.c

lib1917-first.obj: first.c
@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib1917_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib1917-first.obj -MD -MP -MF $(DEPDIR)/lib1917-first.Tpo -c -o lib1917-first.obj `if test -f 'first.c'; then $(CYGPATH_W) 'first.c'; else $(CYGPATH_W) '$(srcdir)/first.c'; fi`
@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/lib1917-first.Tpo $(DEPDIR)/lib1917-first.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='first.c' object='lib1917-first.obj' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib1917_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib1917-first.obj `if test -f 'first.c'; then $(CYGPATH_W) 'first.c'; else $(CYGPATH_W) '$(srcdir)/first.c'; fi`

../../lib/lib1917-warnless.o: ../../lib/warnless.c
@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib1917_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ../../lib/lib1917-warnless.o -MD -MP -MF ../../lib/$(DEPDIR)/lib1917-warnless.Tpo -c -o ../../lib/lib1917-warnless.o `test -f '../../lib/warnless.c' || echo '$(srcdir)/'`../../lib/warnless.c
@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) ../../lib/$(DEPDIR)/lib1917-warnless.Tpo ../../lib/$(DEPDIR)/lib1917-warnless.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='../../lib/warnless.c' object='../../lib/lib1917-warnless.o' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib1917_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ../../lib/lib1917-warnless.o `test -f '../../lib/warnless.c' || echo '$(srcdir)/'`../../lib/warnless.c

../../lib/lib1917-warnless.obj: ../../lib/warnless.c
@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib1917_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ../../lib/lib1917-warnless.obj -MD -MP -MF ../../lib/$(DEPDIR)/lib1917-warnless.Tpo -c -o ../../lib/lib1917-warnless.obj `if test -f '../../lib/warnless.c'; then $(CYGPATH_W) '../../lib/warnless.c'; else $(CYGPATH_W) '$(srcdir)/../../lib/warnless.c'; fi`
@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) ../../lib/$(DEPDIR)/lib1917-warnless.Tpo ../../lib/$(DEPDIR)/lib1917-warnless.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='../../lib/warnless.c' object='../../lib/lib1917-warnless.obj' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib1917_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ../../lib/lib1917-warnless.obj `if test -f '../../lib/warnless.c'; then $(CYGPATH_W) '../../lib/warnless.c'; else $(CYGPATH_W) '$(srcdir)/../../lib/warnless.c'; fi`

lib1918-lib1918.o: lib1918.c
@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib1918_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib1918-lib1918.o -MD -MP -MF $(DEPDIR)/lib1918-lib1918.Tpo -c -o lib1918-lib1918.o `test -f 'lib1918.c' || echo '$(srcdir)/'`lib1918.c
@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/lib1918-lib1918.Tpo $(DEPDIR)/lib1918-lib1918.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='lib1918.c' object='lib1918-lib1918.o' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib1918_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib1918-lib1918.o `test -f 'lib1918.c' || echo '$(srcdir)/'`lib1918.c

lib1918-lib1918.obj: lib1918.c
@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib1918_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib1918-lib1918.obj -MD -MP -MF $(DEPDIR)/lib1918-lib1918.Tpo -c -o lib1918-lib1918.obj `if test -f 'lib1918.c'; then $(CYGPATH_W) 'lib1918.c'; else $(CYGPATH_W) '$(srcdir)/lib1918.c'; fi`
@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/lib1918-lib1918.Tpo $(DEPDIR)/lib1918-lib1918.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='lib1918.c' object='lib1918-lib1918.obj' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib1918_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib1918-lib1918.obj `if test -f 'lib1918.c'; then $(CYGPATH_W) 'lib1918.c'; else $(CYGPATH_W) '$(srcdir)/lib1918.c'; fi`

lib1918-first.o: first.c
@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib1918_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib1918-first.o -MD -MP -MF $(DEPDIR)/lib1918-first.Tpo -c -o lib1918-first.o `test -f 'first.c' || echo '$(srcdir)/'`first.c
@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/lib1918-first.Tpo $(DEPDIR)/lib1918-first.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='first.c' object='lib1918-first.o' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib1918_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib1918-first.o `test -f 'first.c' || echo '$(srcdir)/'`first.c

lib1918-first.obj: first.c
@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib1918_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib1918-first.obj -MD -MP -MF $(DEPDIR)/lib1918-first.Tpo -c -o lib1918-first.obj `if test -f 'first.c'; then $(CYGPATH_W) 'first.c'; else $(CYGPATH_W) '$(srcdir)/first.c'; fi`
@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/lib1918-first.Tpo $(DEPDIR)/lib1918-first.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='first.c' object='lib1918-first.obj' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib1918_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib1918-first.obj `if test -f 'first.c'; then $(CYGPATH_W) 'first.c'; else $(CYGPATH_W) '$(srcdir)/first.c'; fi`

../../lib/lib1918-warnless.o: ../../lib/warnless.c
@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib1918_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ../../lib/lib1918-warnless.o -MD -MP -MF ../../lib/$(DEPDIR)/lib1918-warnless.Tpo -c -o ../../lib/lib1918-warnless.o `test -f '../../lib/warnless.c' || echo '$(srcdir)/'`../../lib/warnless.c
@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) ../../lib/$(DEPDIR)/lib1918-warnless.Tpo ../../lib/$(DEPDIR)/lib1918-warnless.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='../../lib/warnless.c' object='../../lib/lib1918-warnless.o' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib1918_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ../../lib/lib1918-warnless.o `test -f '../../lib/warnless.c' || echo '$(srcdir)/'`../../lib/warnless.c

../../lib/lib1918-warnless.obj: ../../lib/warnless.c
@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib1918_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ../../lib/lib1918-warnless.obj -MD -MP -MF ../../lib/$(DEPDIR)/lib1918-warnless.Tpo -c -o ../../lib/lib1918-warnless.obj `if test -f '../../lib/warnless.c'; then $(CYGPATH_W) '../../lib/warnless.c'; else $(CYGPATH_W) '$(srcdir)/../../lib/warnless.c'; fi`
@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) ../../lib/$(DEPDIR)/lib1918-warnless.Tpo ../../lib/$(DEPDIR)/lib1918-warnless.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='../../lib/warnless.c' object='../../lib/lib1918-warnless.obj' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib1918_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ../../lib/lib1918-warnless.obj `if test -f '../../lib/warnless.c'; then $(CYGPATH_W) '../../lib/warnless.c'; else $(CYGPATH_W) '$(srcdir)/../../lib/warnless.c'; fi`

lib1933-lib1933.o: lib1933.c
@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib1933_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib1933-lib1933.o -MD -MP -MF $(DEPDIR)/lib1933-lib1933.Tpo -c -o lib1933-lib1933.o `test -f 'lib1933.c' || echo '$(srcdir)/'`lib1933.c
@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/lib1933-lib1933.Tpo $(DEPDIR)/lib1933-lib1933.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='lib1933.c' object='lib1933-lib1933.o' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib1933_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib1933-lib1933.o `test -f 'lib1933.c' || echo '$(srcdir)/'`lib1933.c

lib1933-lib1933.obj: lib1933.c
@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib1933_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib1933-lib1933.obj -MD -MP -MF $(DEPDIR)/lib1933-lib1933.Tpo -c -o lib1933-lib1933.obj `if test -f 'lib1933.c'; then $(CYGPATH_W) 'lib1933.c'; else $(CYGPATH_W) '$(srcdir)/lib1933.c'; fi`
@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/lib1933-lib1933.Tpo $(DEPDIR)/lib1933-lib1933.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='lib1933.c' object='lib1933-lib1933.obj' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib1933_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib1933-lib1933.obj `if test -f 'lib1933.c'; then $(CYGPATH_W) 'lib1933.c'; else $(CYGPATH_W) '$(srcdir)/lib1933.c'; fi`

lib1933-first.o: first.c
@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib1933_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib1933-first.o -MD -MP -MF $(DEPDIR)/lib1933-first.Tpo -c -o lib1933-first.o `test -f 'first.c' || echo '$(srcdir)/'`first.c
@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/lib1933-first.Tpo $(DEPDIR)/lib1933-first.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='first.c' object='lib1933-first.o' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib1933_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib1933-first.o `test -f 'first.c' || echo '$(srcdir)/'`first.c

lib1933-first.obj: first.c
@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib1933_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib1933-first.obj -MD -MP -MF $(DEPDIR)/lib1933-first.Tpo -c -o lib1933-first.obj `if test -f 'first.c'; then $(CYGPATH_W) 'first.c'; else $(CYGPATH_W) '$(srcdir)/first.c'; fi`
@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/lib1933-first.Tpo $(DEPDIR)/lib1933-first.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='first.c' object='lib1933-first.obj' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib1933_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib1933-first.obj `if test -f 'first.c'; then $(CYGPATH_W) 'first.c'; else $(CYGPATH_W) '$(srcdir)/first.c'; fi`

lib1933-testutil.o: testutil.c
@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib1933_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib1933-testutil.o -MD -MP -MF $(DEPDIR)/lib1933-testutil.Tpo -c -o lib1933-testutil.o `test -f 'testutil.c' || echo '$(srcdir)/'`testutil.c
@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/lib1933-testutil.Tpo $(DEPDIR)/lib1933-testutil.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='testutil.c' object='lib1933-testutil.o' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib1933_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib1933-testutil.o `test -f 'testutil.c' || echo '$(srcdir)/'`testutil.c

lib1933-testutil.obj: testutil.c
@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib1933_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib1933-testutil.obj -MD -MP -MF $(DEPDIR)/lib1933-testutil.Tpo -c -o lib1933-testutil.obj `if test -f 'testutil.c'; then $(CYGPATH_W) 'testutil.c'; else $(CYGPATH_W) '$(srcdir)/testutil.c'; fi`
@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/lib1933-testutil.Tpo $(DEPDIR)/lib1933-testutil.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='testutil.c' object='lib1933-testutil.obj' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib1933_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib1933-testutil.obj `if test -f 'testutil.c'; then $(CYGPATH_W) 'testutil.c'; else $(CYGPATH_W) '$(srcdir)/testutil.c'; fi`

../../lib/lib1933-warnless.o: ../../lib/warnless.c
@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib1933_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ../../lib/lib1933-warnless.o -MD -MP -MF ../../lib/$(DEPDIR)/lib1933-warnless.Tpo -c -o ../../lib/lib1933-warnless.o `test -f '../../lib/warnless.c' || echo '$(srcdir)/'`../../lib/warnless.c
@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) ../../lib/$(DEPDIR)/lib1933-warnless.Tpo ../../lib/$(DEPDIR)/lib1933-warnless.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='../../lib/warnless.c' object='../../lib/lib1933-warnless.o' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib1933_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ../../lib/lib1933-warnless.o `test -f '../../lib/warnless.c' || echo '$(srcdir)/'`../../lib/warnless.c

../../lib/lib1933-warnless.obj: ../../lib/warnless.c
@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib1933_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ../../lib/lib1933-warnless.obj -MD -MP -MF ../../lib/$(DEPDIR)/lib1933-warnless.Tpo -c -o ../../lib/lib1933-warnless.obj `if test -f '../../lib/warnless.c'; then $(CYGPATH_W) '../../lib/warnless.c'; else $(CYGPATH_W) '$(srcdir)/../../lib/warnless.c'; fi`
@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) ../../lib/$(DEPDIR)/lib1933-warnless.Tpo ../../lib/$(DEPDIR)/lib1933-warnless.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='../../lib/warnless.c' object='../../lib/lib1933-warnless.obj' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib1933_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ../../lib/lib1933-warnless.obj `if test -f '../../lib/warnless.c'; then $(CYGPATH_W) '../../lib/warnless.c'; else $(CYGPATH_W) '$(srcdir)/../../lib/warnless.c'; fi`

lib1934-lib1934.o: lib1934.c
@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib1934_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib1934-lib1934.o -MD -MP -MF $(DEPDIR)/lib1934-lib1934.Tpo -c -o lib1934-lib1934.o `test -f 'lib1934.c' || echo '$(srcdir)/'`lib1934.c
@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/lib1934-lib1934.Tpo $(DEPDIR)/lib1934-lib1934.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='lib1934.c' object='lib1934-lib1934.o' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib1934_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib1934-lib1934.o `test -f 'lib1934.c' || echo '$(srcdir)/'`lib1934.c

lib1934-lib1934.obj: lib1934.c
@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib1934_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib1934-lib1934.obj -MD -MP -MF $(DEPDIR)/lib1934-lib1934.Tpo -c -o lib1934-lib1934.obj `if test -f 'lib1934.c'; then $(CYGPATH_W) 'lib1934.c'; else $(CYGPATH_W) '$(srcdir)/lib1934.c'; fi`
@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/lib1934-lib1934.Tpo $(DEPDIR)/lib1934-lib1934.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='lib1934.c' object='lib1934-lib1934.obj' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib1934_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib1934-lib1934.obj `if test -f 'lib1934.c'; then $(CYGPATH_W) 'lib1934.c'; else $(CYGPATH_W) '$(srcdir)/lib1934.c'; fi`

lib1934-first.o: first.c
@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib1934_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib1934-first.o -MD -MP -MF $(DEPDIR)/lib1934-first.Tpo -c -o lib1934-first.o `test -f 'first.c' || echo '$(srcdir)/'`first.c
@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/lib1934-first.Tpo $(DEPDIR)/lib1934-first.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='first.c' object='lib1934-first.o' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib1934_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib1934-first.o `test -f 'first.c' || echo '$(srcdir)/'`first.c

lib1934-first.obj: first.c
@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib1934_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib1934-first.obj -MD -MP -MF $(DEPDIR)/lib1934-first.Tpo -c -o lib1934-first.obj `if test -f 'first.c'; then $(CYGPATH_W) 'first.c'; else $(CYGPATH_W) '$(srcdir)/first.c'; fi`
@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/lib1934-first.Tpo $(DEPDIR)/lib1934-first.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='first.c' object='lib1934-first.obj' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib1934_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib1934-first.obj `if test -f 'first.c'; then $(CYGPATH_W) 'first.c'; else $(CYGPATH_W) '$(srcdir)/first.c'; fi`

lib1934-testutil.o: testutil.c
@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib1934_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib1934-testutil.o -MD -MP -MF $(DEPDIR)/lib1934-testutil.Tpo -c -o lib1934-testutil.o `test -f 'testutil.c' || echo '$(srcdir)/'`testutil.c
@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/lib1934-testutil.Tpo $(DEPDIR)/lib1934-testutil.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='testutil.c' object='lib1934-testutil.o' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib1934_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib1934-testutil.o `test -f 'testutil.c' || echo '$(srcdir)/'`testutil.c

lib1934-testutil.obj: testutil.c
@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib1934_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib1934-testutil.obj -MD -MP -MF $(DEPDIR)/lib1934-testutil.Tpo -c -o lib1934-testutil.obj `if test -f 'testutil.c'; then $(CYGPATH_W) 'testutil.c'; else $(CYGPATH_W) '$(srcdir)/testutil.c'; fi`
@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/lib1934-testutil.Tpo $(DEPDIR)/lib1934-testutil.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='testutil.c' object='lib1934-testutil.obj' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib1934_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib1934-testutil.obj `if test -f 'testutil.c'; then $(CYGPATH_W) 'testutil.c'; else $(CYGPATH_W) '$(srcdir)/testutil.c'; fi`

../../lib/lib1934-warnless.o: ../../lib/warnless.c
@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib1934_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ../../lib/lib1934-warnless.o -MD -MP -MF ../../lib/$(DEPDIR)/lib1934-warnless.Tpo -c -o ../../lib/lib1934-warnless.o `test -f '../../lib/warnless.c' || echo '$(srcdir)/'`../../lib/warnless.c
@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) ../../lib/$(DEPDIR)/lib1934-warnless.Tpo ../../lib/$(DEPDIR)/lib1934-warnless.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='../../lib/warnless.c' object='../../lib/lib1934-warnless.o' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib1934_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ../../lib/lib1934-warnless.o `test -f '../../lib/warnless.c' || echo '$(srcdir)/'`../../lib/warnless.c

../../lib/lib1934-warnless.obj: ../../lib/warnless.c
@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib1934_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ../../lib/lib1934-warnless.obj -MD -MP -MF ../../lib/$(DEPDIR)/lib1934-warnless.Tpo -c -o ../../lib/lib1934-warnless.obj `if test -f '../../lib/warnless.c'; then $(CYGPATH_W) '../../lib/warnless.c'; else $(CYGPATH_W) '$(srcdir)/../../lib/warnless.c'; fi`
@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) ../../lib/$(DEPDIR)/lib1934-warnless.Tpo ../../lib/$(DEPDIR)/lib1934-warnless.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='../../lib/warnless.c' object='../../lib/lib1934-warnless.obj' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib1934_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ../../lib/lib1934-warnless.obj `if test -f '../../lib/warnless.c'; then $(CYGPATH_W) '../../lib/warnless.c'; else $(CYGPATH_W) '$(srcdir)/../../lib/warnless.c'; fi`

lib1935-lib1935.o: lib1935.c
@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib1935_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib1935-lib1935.o -MD -MP -MF $(DEPDIR)/lib1935-lib1935.Tpo -c -o lib1935-lib1935.o `test -f 'lib1935.c' || echo '$(srcdir)/'`lib1935.c
@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/lib1935-lib1935.Tpo $(DEPDIR)/lib1935-lib1935.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='lib1935.c' object='lib1935-lib1935.o' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib1935_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib1935-lib1935.o `test -f 'lib1935.c' || echo '$(srcdir)/'`lib1935.c

lib1935-lib1935.obj: lib1935.c
@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib1935_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib1935-lib1935.obj -MD -MP -MF $(DEPDIR)/lib1935-lib1935.Tpo -c -o lib1935-lib1935.obj `if test -f 'lib1935.c'; then $(CYGPATH_W) 'lib1935.c'; else $(CYGPATH_W) '$(srcdir)/lib1935.c'; fi`
@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/lib1935-lib1935.Tpo $(DEPDIR)/lib1935-lib1935.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='lib1935.c' object='lib1935-lib1935.obj' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib1935_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib1935-lib1935.obj `if test -f 'lib1935.c'; then $(CYGPATH_W) 'lib1935.c'; else $(CYGPATH_W) '$(srcdir)/lib1935.c'; fi`

lib1935-first.o: first.c
@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib1935_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib1935-first.o -MD -MP -MF $(DEPDIR)/lib1935-first.Tpo -c -o lib1935-first.o `test -f 'first.c' || echo '$(srcdir)/'`first.c
@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/lib1935-first.Tpo $(DEPDIR)/lib1935-first.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='first.c' object='lib1935-first.o' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib1935_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib1935-first.o `test -f 'first.c' || echo '$(srcdir)/'`first.c

lib1935-first.obj: first.c
@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib1935_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib1935-first.obj -MD -MP -MF $(DEPDIR)/lib1935-first.Tpo -c -o lib1935-first.obj `if test -f 'first.c'; then $(CYGPATH_W) 'first.c'; else $(CYGPATH_W) '$(srcdir)/first.c'; fi`
@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/lib1935-first.Tpo $(DEPDIR)/lib1935-first.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='first.c' object='lib1935-first.obj' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib1935_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib1935-first.obj `if test -f 'first.c'; then $(CYGPATH_W) 'first.c'; else $(CYGPATH_W) '$(srcdir)/first.c'; fi`

lib1935-testutil.o: testutil.c
@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib1935_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib1935-testutil.o -MD -MP -MF $(DEPDIR)/lib1935-testutil.Tpo -c -o lib1935-testutil.o `test -f 'testutil.c' || echo '$(srcdir)/'`testutil.c
@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/lib1935-testutil.Tpo $(DEPDIR)/lib1935-testutil.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='testutil.c' object='lib1935-testutil.o' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib1935_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib1935-testutil.o `test -f 'testutil.c' || echo '$(srcdir)/'`testutil.c

lib1935-testutil.obj: testutil.c
@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib1935_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib1935-testutil.obj -MD -MP -MF $(DEPDIR)/lib1935-testutil.Tpo -c -o lib1935-testutil.obj `if test -f 'testutil.c'; then $(CYGPATH_W) 'testutil.c'; else $(CYGPATH_W) '$(srcdir)/testutil.c'; fi`
@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/lib1935-testutil.Tpo $(DEPDIR)/lib1935-testutil.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='testutil.c' object='lib1935-testutil.obj' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib1935_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib1935-testutil.obj `if test -f 'testutil.c'; then $(CYGPATH_W) 'testutil.c'; else $(CYGPATH_W) '$(srcdir)/testutil.c'; fi`

../../lib/lib1935-warnless.o: ../../lib/warnless.c
@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib1935_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ../../lib/lib1935-warnless.o -MD -MP -MF ../../lib/$(DEPDIR)/lib1935-warnless.Tpo -c -o ../../lib/lib1935-warnless.o `test -f '../../lib/warnless.c' || echo '$(srcdir)/'`../../lib/warnless.c
@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) ../../lib/$(DEPDIR)/lib1935-warnless.Tpo ../../lib/$(DEPDIR)/lib1935-warnless.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='../../lib/warnless.c' object='../../lib/lib1935-warnless.o' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib1935_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ../../lib/lib1935-warnless.o `test -f '../../lib/warnless.c' || echo '$(srcdir)/'`../../lib/warnless.c

../../lib/lib1935-warnless.obj: ../../lib/warnless.c
@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib1935_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ../../lib/lib1935-warnless.obj -MD -MP -MF ../../lib/$(DEPDIR)/lib1935-warnless.Tpo -c -o ../../lib/lib1935-warnless.obj `if test -f '../../lib/warnless.c'; then $(CYGPATH_W) '../../lib/warnless.c'; else $(CYGPATH_W) '$(srcdir)/../../lib/warnless.c'; fi`
@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) ../../lib/$(DEPDIR)/lib1935-warnless.Tpo ../../lib/$(DEPDIR)/lib1935-warnless.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='../../lib/warnless.c' object='../../lib/lib1935-warnless.obj' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib1935_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ../../lib/lib1935-warnless.obj `if test -f '../../lib/warnless.c'; then $(CYGPATH_W) '../../lib/warnless.c'; else $(CYGPATH_W) '$(srcdir)/../../lib/warnless.c'; fi`

lib1936-lib1936.o: lib1936.c
@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib1936_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib1936-lib1936.o -MD -MP -MF $(DEPDIR)/lib1936-lib1936.Tpo -c -o lib1936-lib1936.o `test -f 'lib1936.c' || echo '$(srcdir)/'`lib1936.c
@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/lib1936-lib1936.Tpo $(DEPDIR)/lib1936-lib1936.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='lib1936.c' object='lib1936-lib1936.o' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib1936_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib1936-lib1936.o `test -f 'lib1936.c' || echo '$(srcdir)/'`lib1936.c

lib1936-lib1936.obj: lib1936.c
@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib1936_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib1936-lib1936.obj -MD -MP -MF $(DEPDIR)/lib1936-lib1936.Tpo -c -o lib1936-lib1936.obj `if test -f 'lib1936.c'; then $(CYGPATH_W) 'lib1936.c'; else $(CYGPATH_W) '$(srcdir)/lib1936.c'; fi`
@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/lib1936-lib1936.Tpo $(DEPDIR)/lib1936-lib1936.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='lib1936.c' object='lib1936-lib1936.obj' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib1936_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib1936-lib1936.obj `if test -f 'lib1936.c'; then $(CYGPATH_W) 'lib1936.c'; else $(CYGPATH_W) '$(srcdir)/lib1936.c'; fi`

lib1936-first.o: first.c
@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib1936_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib1936-first.o -MD -MP -MF $(DEPDIR)/lib1936-first.Tpo -c -o lib1936-first.o `test -f 'first.c' || echo '$(srcdir)/'`first.c
@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/lib1936-first.Tpo $(DEPDIR)/lib1936-first.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='first.c' object='lib1936-first.o' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib1936_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib1936-first.o `test -f 'first.c' || echo '$(srcdir)/'`first.c

lib1936-first.obj: first.c
@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib1936_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib1936-first.obj -MD -MP -MF $(DEPDIR)/lib1936-first.Tpo -c -o lib1936-first.obj `if test -f 'first.c'; then $(CYGPATH_W) 'first.c'; else $(CYGPATH_W) '$(srcdir)/first.c'; fi`
@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/lib1936-first.Tpo $(DEPDIR)/lib1936-first.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='first.c' object='lib1936-first.obj' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib1936_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib1936-first.obj `if test -f 'first.c'; then $(CYGPATH_W) 'first.c'; else $(CYGPATH_W) '$(srcdir)/first.c'; fi`

lib1936-testutil.o: testutil.c
@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib1936_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib1936-testutil.o -MD -MP -MF $(DEPDIR)/lib1936-testutil.Tpo -c -o lib1936-testutil.o `test -f 'testutil.c' || echo '$(srcdir)/'`testutil.c
@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/lib1936-testutil.Tpo $(DEPDIR)/lib1936-testutil.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='testutil.c' object='lib1936-testutil.o' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib1936_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib1936-testutil.o `test -f 'testutil.c' || echo '$(srcdir)/'`testutil.c

lib1936-testutil.obj: testutil.c
@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib1936_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib1936-testutil.obj -MD -MP -MF $(DEPDIR)/lib1936-testutil.Tpo -c -o lib1936-testutil.obj `if test -f 'testutil.c'; then $(CYGPATH_W) 'testutil.c'; else $(CYGPATH_W) '$(srcdir)/testutil.c'; fi`
@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/lib1936-testutil.Tpo $(DEPDIR)/lib1936-testutil.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='testutil.c' object='lib1936-testutil.obj' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib1936_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib1936-testutil.obj `if test -f 'testutil.c'; then $(CYGPATH_W) 'testutil.c'; else $(CYGPATH_W) '$(srcdir)/testutil.c'; fi`

../../lib/lib1936-warnless.o: ../../lib/warnless.c
@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib1936_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ../../lib/lib1936-warnless.o -MD -MP -MF ../../lib/$(DEPDIR)/lib1936-warnless.Tpo -c -o ../../lib/lib1936-warnless.o `test -f '../../lib/warnless.c' || echo '$(srcdir)/'`../../lib/warnless.c
@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) ../../lib/$(DEPDIR)/lib1936-warnless.Tpo ../../lib/$(DEPDIR)/lib1936-warnless.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='../../lib/warnless.c' object='../../lib/lib1936-warnless.o' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib1936_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ../../lib/lib1936-warnless.o `test -f '../../lib/warnless.c' || echo '$(srcdir)/'`../../lib/warnless.c

../../lib/lib1936-warnless.obj: ../../lib/warnless.c
@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib1936_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ../../lib/lib1936-warnless.obj -MD -MP -MF ../../lib/$(DEPDIR)/lib1936-warnless.Tpo -c -o ../../lib/lib1936-warnless.obj `if test -f '../../lib/warnless.c'; then $(CYGPATH_W) '../../lib/warnless.c'; else $(CYGPATH_W) '$(srcdir)/../../lib/warnless.c'; fi`
@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) ../../lib/$(DEPDIR)/lib1936-warnless.Tpo ../../lib/$(DEPDIR)/lib1936-warnless.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='../../lib/warnless.c' object='../../lib/lib1936-warnless.obj' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib1936_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ../../lib/lib1936-warnless.obj `if test -f '../../lib/warnless.c'; then $(CYGPATH_W) '../../lib/warnless.c'; else $(CYGPATH_W) '$(srcdir)/../../lib/warnless.c'; fi`

lib3010-lib3010.o: lib3010.c
@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib3010_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib3010-lib3010.o -MD -MP -MF $(DEPDIR)/lib3010-lib3010.Tpo -c -o lib3010-lib3010.o `test -f 'lib3010.c' || echo '$(srcdir)/'`lib3010.c
@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/lib3010-lib3010.Tpo $(DEPDIR)/lib3010-lib3010.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='lib3010.c' object='lib3010-lib3010.o' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib3010_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib3010-lib3010.o `test -f 'lib3010.c' || echo '$(srcdir)/'`lib3010.c

10065
10066
10067
10068
10069
10070
10071




























10072
10073
10074
10075
10076
10077
10078
lib583-first.obj: first.c
@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib583_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib583-first.obj -MD -MP -MF $(DEPDIR)/lib583-first.Tpo -c -o lib583-first.obj `if test -f 'first.c'; then $(CYGPATH_W) 'first.c'; else $(CYGPATH_W) '$(srcdir)/first.c'; fi`
@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/lib583-first.Tpo $(DEPDIR)/lib583-first.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='first.c' object='lib583-first.obj' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib583_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib583-first.obj `if test -f 'first.c'; then $(CYGPATH_W) 'first.c'; else $(CYGPATH_W) '$(srcdir)/first.c'; fi`





























lib585-lib500.o: lib500.c
@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib585_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib585-lib500.o -MD -MP -MF $(DEPDIR)/lib585-lib500.Tpo -c -o lib585-lib500.o `test -f 'lib500.c' || echo '$(srcdir)/'`lib500.c
@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/lib585-lib500.Tpo $(DEPDIR)/lib585-lib500.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='lib500.c' object='lib585-lib500.o' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib585_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib585-lib500.o `test -f 'lib500.c' || echo '$(srcdir)/'`lib500.c








>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







10666
10667
10668
10669
10670
10671
10672
10673
10674
10675
10676
10677
10678
10679
10680
10681
10682
10683
10684
10685
10686
10687
10688
10689
10690
10691
10692
10693
10694
10695
10696
10697
10698
10699
10700
10701
10702
10703
10704
10705
10706
10707
lib583-first.obj: first.c
@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib583_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib583-first.obj -MD -MP -MF $(DEPDIR)/lib583-first.Tpo -c -o lib583-first.obj `if test -f 'first.c'; then $(CYGPATH_W) 'first.c'; else $(CYGPATH_W) '$(srcdir)/first.c'; fi`
@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/lib583-first.Tpo $(DEPDIR)/lib583-first.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='first.c' object='lib583-first.obj' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib583_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib583-first.obj `if test -f 'first.c'; then $(CYGPATH_W) 'first.c'; else $(CYGPATH_W) '$(srcdir)/first.c'; fi`

lib584-lib589.o: lib589.c
@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib584_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib584-lib589.o -MD -MP -MF $(DEPDIR)/lib584-lib589.Tpo -c -o lib584-lib589.o `test -f 'lib589.c' || echo '$(srcdir)/'`lib589.c
@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/lib584-lib589.Tpo $(DEPDIR)/lib584-lib589.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='lib589.c' object='lib584-lib589.o' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib584_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib584-lib589.o `test -f 'lib589.c' || echo '$(srcdir)/'`lib589.c

lib584-lib589.obj: lib589.c
@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib584_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib584-lib589.obj -MD -MP -MF $(DEPDIR)/lib584-lib589.Tpo -c -o lib584-lib589.obj `if test -f 'lib589.c'; then $(CYGPATH_W) 'lib589.c'; else $(CYGPATH_W) '$(srcdir)/lib589.c'; fi`
@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/lib584-lib589.Tpo $(DEPDIR)/lib584-lib589.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='lib589.c' object='lib584-lib589.obj' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib584_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib584-lib589.obj `if test -f 'lib589.c'; then $(CYGPATH_W) 'lib589.c'; else $(CYGPATH_W) '$(srcdir)/lib589.c'; fi`

lib584-first.o: first.c
@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib584_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib584-first.o -MD -MP -MF $(DEPDIR)/lib584-first.Tpo -c -o lib584-first.o `test -f 'first.c' || echo '$(srcdir)/'`first.c
@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/lib584-first.Tpo $(DEPDIR)/lib584-first.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='first.c' object='lib584-first.o' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib584_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib584-first.o `test -f 'first.c' || echo '$(srcdir)/'`first.c

lib584-first.obj: first.c
@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib584_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib584-first.obj -MD -MP -MF $(DEPDIR)/lib584-first.Tpo -c -o lib584-first.obj `if test -f 'first.c'; then $(CYGPATH_W) 'first.c'; else $(CYGPATH_W) '$(srcdir)/first.c'; fi`
@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/lib584-first.Tpo $(DEPDIR)/lib584-first.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='first.c' object='lib584-first.obj' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib584_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib584-first.obj `if test -f 'first.c'; then $(CYGPATH_W) 'first.c'; else $(CYGPATH_W) '$(srcdir)/first.c'; fi`

lib585-lib500.o: lib500.c
@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib585_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib585-lib500.o -MD -MP -MF $(DEPDIR)/lib585-lib500.Tpo -c -o lib585-lib500.o `test -f 'lib500.c' || echo '$(srcdir)/'`lib500.c
@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/lib585-lib500.Tpo $(DEPDIR)/lib585-lib500.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='lib500.c' object='lib585-lib500.o' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib585_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib585-lib500.o `test -f 'lib500.c' || echo '$(srcdir)/'`lib500.c

11528
11529
11530
11531
11532
11533
11534







11535
11536
11537
11538
11539
11540
11541
	-rm -f ../../lib/$(DEPDIR)/lib1907-warnless.Po
	-rm -f ../../lib/$(DEPDIR)/lib1908-warnless.Po
	-rm -f ../../lib/$(DEPDIR)/lib1910-warnless.Po
	-rm -f ../../lib/$(DEPDIR)/lib1911-warnless.Po
	-rm -f ../../lib/$(DEPDIR)/lib1912-warnless.Po
	-rm -f ../../lib/$(DEPDIR)/lib1913-warnless.Po
	-rm -f ../../lib/$(DEPDIR)/lib1915-warnless.Po







	-rm -f ../../lib/$(DEPDIR)/lib3010-warnless.Po
	-rm -f ../../lib/$(DEPDIR)/lib500-curl_multibyte.Po
	-rm -f ../../lib/$(DEPDIR)/lib502-warnless.Po
	-rm -f ../../lib/$(DEPDIR)/lib503-warnless.Po
	-rm -f ../../lib/$(DEPDIR)/lib504-warnless.Po
	-rm -f ../../lib/$(DEPDIR)/lib505-curl_multibyte.Po
	-rm -f ../../lib/$(DEPDIR)/lib507-warnless.Po







>
>
>
>
>
>
>







12157
12158
12159
12160
12161
12162
12163
12164
12165
12166
12167
12168
12169
12170
12171
12172
12173
12174
12175
12176
12177
	-rm -f ../../lib/$(DEPDIR)/lib1907-warnless.Po
	-rm -f ../../lib/$(DEPDIR)/lib1908-warnless.Po
	-rm -f ../../lib/$(DEPDIR)/lib1910-warnless.Po
	-rm -f ../../lib/$(DEPDIR)/lib1911-warnless.Po
	-rm -f ../../lib/$(DEPDIR)/lib1912-warnless.Po
	-rm -f ../../lib/$(DEPDIR)/lib1913-warnless.Po
	-rm -f ../../lib/$(DEPDIR)/lib1915-warnless.Po
	-rm -f ../../lib/$(DEPDIR)/lib1916-warnless.Po
	-rm -f ../../lib/$(DEPDIR)/lib1917-warnless.Po
	-rm -f ../../lib/$(DEPDIR)/lib1918-warnless.Po
	-rm -f ../../lib/$(DEPDIR)/lib1933-warnless.Po
	-rm -f ../../lib/$(DEPDIR)/lib1934-warnless.Po
	-rm -f ../../lib/$(DEPDIR)/lib1935-warnless.Po
	-rm -f ../../lib/$(DEPDIR)/lib1936-warnless.Po
	-rm -f ../../lib/$(DEPDIR)/lib3010-warnless.Po
	-rm -f ../../lib/$(DEPDIR)/lib500-curl_multibyte.Po
	-rm -f ../../lib/$(DEPDIR)/lib502-warnless.Po
	-rm -f ../../lib/$(DEPDIR)/lib503-warnless.Po
	-rm -f ../../lib/$(DEPDIR)/lib504-warnless.Po
	-rm -f ../../lib/$(DEPDIR)/lib505-curl_multibyte.Po
	-rm -f ../../lib/$(DEPDIR)/lib507-warnless.Po
11646
11647
11648
11649
11650
11651
11652


11653
11654
11655
11656
11657
11658
11659
	-rm -f ./$(DEPDIR)/lib1518-lib1518.Po
	-rm -f ./$(DEPDIR)/lib1520-first.Po
	-rm -f ./$(DEPDIR)/lib1520-lib1520.Po
	-rm -f ./$(DEPDIR)/lib1521-first.Po
	-rm -f ./$(DEPDIR)/lib1521-lib1521.Po
	-rm -f ./$(DEPDIR)/lib1522-first.Po
	-rm -f ./$(DEPDIR)/lib1522-lib1522.Po


	-rm -f ./$(DEPDIR)/lib1523-first.Po
	-rm -f ./$(DEPDIR)/lib1523-lib1523.Po
	-rm -f ./$(DEPDIR)/lib1525-first.Po
	-rm -f ./$(DEPDIR)/lib1525-lib1525.Po
	-rm -f ./$(DEPDIR)/lib1525-testutil.Po
	-rm -f ./$(DEPDIR)/lib1526-first.Po
	-rm -f ./$(DEPDIR)/lib1526-lib1526.Po







>
>







12282
12283
12284
12285
12286
12287
12288
12289
12290
12291
12292
12293
12294
12295
12296
12297
	-rm -f ./$(DEPDIR)/lib1518-lib1518.Po
	-rm -f ./$(DEPDIR)/lib1520-first.Po
	-rm -f ./$(DEPDIR)/lib1520-lib1520.Po
	-rm -f ./$(DEPDIR)/lib1521-first.Po
	-rm -f ./$(DEPDIR)/lib1521-lib1521.Po
	-rm -f ./$(DEPDIR)/lib1522-first.Po
	-rm -f ./$(DEPDIR)/lib1522-lib1522.Po
	-rm -f ./$(DEPDIR)/lib1522-testtrace.Po
	-rm -f ./$(DEPDIR)/lib1522-testutil.Po
	-rm -f ./$(DEPDIR)/lib1523-first.Po
	-rm -f ./$(DEPDIR)/lib1523-lib1523.Po
	-rm -f ./$(DEPDIR)/lib1525-first.Po
	-rm -f ./$(DEPDIR)/lib1525-lib1525.Po
	-rm -f ./$(DEPDIR)/lib1525-testutil.Po
	-rm -f ./$(DEPDIR)/lib1526-first.Po
	-rm -f ./$(DEPDIR)/lib1526-lib1526.Po
11728
11729
11730
11731
11732
11733
11734


11735
11736
11737
11738
11739
11740
11741
	-rm -f ./$(DEPDIR)/lib1564-lib1564.Po
	-rm -f ./$(DEPDIR)/lib1564-testutil.Po
	-rm -f ./$(DEPDIR)/lib1565-first.Po
	-rm -f ./$(DEPDIR)/lib1565-lib1565.Po
	-rm -f ./$(DEPDIR)/lib1565-testutil.Po
	-rm -f ./$(DEPDIR)/lib1567-first.Po
	-rm -f ./$(DEPDIR)/lib1567-lib1567.Po


	-rm -f ./$(DEPDIR)/lib1591-first.Po
	-rm -f ./$(DEPDIR)/lib1591-lib1591.Po
	-rm -f ./$(DEPDIR)/lib1591-testutil.Po
	-rm -f ./$(DEPDIR)/lib1592-first.Po
	-rm -f ./$(DEPDIR)/lib1592-lib1592.Po
	-rm -f ./$(DEPDIR)/lib1592-testutil.Po
	-rm -f ./$(DEPDIR)/lib1593.Po







>
>







12366
12367
12368
12369
12370
12371
12372
12373
12374
12375
12376
12377
12378
12379
12380
12381
	-rm -f ./$(DEPDIR)/lib1564-lib1564.Po
	-rm -f ./$(DEPDIR)/lib1564-testutil.Po
	-rm -f ./$(DEPDIR)/lib1565-first.Po
	-rm -f ./$(DEPDIR)/lib1565-lib1565.Po
	-rm -f ./$(DEPDIR)/lib1565-testutil.Po
	-rm -f ./$(DEPDIR)/lib1567-first.Po
	-rm -f ./$(DEPDIR)/lib1567-lib1567.Po
	-rm -f ./$(DEPDIR)/lib1568-first.Po
	-rm -f ./$(DEPDIR)/lib1568-lib1568.Po
	-rm -f ./$(DEPDIR)/lib1591-first.Po
	-rm -f ./$(DEPDIR)/lib1591-lib1591.Po
	-rm -f ./$(DEPDIR)/lib1591-testutil.Po
	-rm -f ./$(DEPDIR)/lib1592-first.Po
	-rm -f ./$(DEPDIR)/lib1592-lib1592.Po
	-rm -f ./$(DEPDIR)/lib1592-testutil.Po
	-rm -f ./$(DEPDIR)/lib1593.Po
11766
11767
11768
11769
11770
11771
11772


















11773
11774
11775
11776
11777
11778
11779
	-rm -f ./$(DEPDIR)/lib1912-testutil.Po
	-rm -f ./$(DEPDIR)/lib1913-first.Po
	-rm -f ./$(DEPDIR)/lib1913-lib1913.Po
	-rm -f ./$(DEPDIR)/lib1913-testutil.Po
	-rm -f ./$(DEPDIR)/lib1915-first.Po
	-rm -f ./$(DEPDIR)/lib1915-lib1915.Po
	-rm -f ./$(DEPDIR)/lib1915-testutil.Po


















	-rm -f ./$(DEPDIR)/lib3010-first.Po
	-rm -f ./$(DEPDIR)/lib3010-lib3010.Po
	-rm -f ./$(DEPDIR)/lib3010-testutil.Po
	-rm -f ./$(DEPDIR)/lib500-first.Po
	-rm -f ./$(DEPDIR)/lib500-lib500.Po
	-rm -f ./$(DEPDIR)/lib500-testtrace.Po
	-rm -f ./$(DEPDIR)/lib500-testutil.Po







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







12406
12407
12408
12409
12410
12411
12412
12413
12414
12415
12416
12417
12418
12419
12420
12421
12422
12423
12424
12425
12426
12427
12428
12429
12430
12431
12432
12433
12434
12435
12436
12437
	-rm -f ./$(DEPDIR)/lib1912-testutil.Po
	-rm -f ./$(DEPDIR)/lib1913-first.Po
	-rm -f ./$(DEPDIR)/lib1913-lib1913.Po
	-rm -f ./$(DEPDIR)/lib1913-testutil.Po
	-rm -f ./$(DEPDIR)/lib1915-first.Po
	-rm -f ./$(DEPDIR)/lib1915-lib1915.Po
	-rm -f ./$(DEPDIR)/lib1915-testutil.Po
	-rm -f ./$(DEPDIR)/lib1916-first.Po
	-rm -f ./$(DEPDIR)/lib1916-lib1916.Po
	-rm -f ./$(DEPDIR)/lib1917-first.Po
	-rm -f ./$(DEPDIR)/lib1917-lib1916.Po
	-rm -f ./$(DEPDIR)/lib1918-first.Po
	-rm -f ./$(DEPDIR)/lib1918-lib1918.Po
	-rm -f ./$(DEPDIR)/lib1933-first.Po
	-rm -f ./$(DEPDIR)/lib1933-lib1933.Po
	-rm -f ./$(DEPDIR)/lib1933-testutil.Po
	-rm -f ./$(DEPDIR)/lib1934-first.Po
	-rm -f ./$(DEPDIR)/lib1934-lib1934.Po
	-rm -f ./$(DEPDIR)/lib1934-testutil.Po
	-rm -f ./$(DEPDIR)/lib1935-first.Po
	-rm -f ./$(DEPDIR)/lib1935-lib1935.Po
	-rm -f ./$(DEPDIR)/lib1935-testutil.Po
	-rm -f ./$(DEPDIR)/lib1936-first.Po
	-rm -f ./$(DEPDIR)/lib1936-lib1936.Po
	-rm -f ./$(DEPDIR)/lib1936-testutil.Po
	-rm -f ./$(DEPDIR)/lib3010-first.Po
	-rm -f ./$(DEPDIR)/lib3010-lib3010.Po
	-rm -f ./$(DEPDIR)/lib3010-testutil.Po
	-rm -f ./$(DEPDIR)/lib500-first.Po
	-rm -f ./$(DEPDIR)/lib500-lib500.Po
	-rm -f ./$(DEPDIR)/lib500-testtrace.Po
	-rm -f ./$(DEPDIR)/lib500-testutil.Po
11925
11926
11927
11928
11929
11930
11931


11932
11933
11934
11935
11936
11937
11938
	-rm -f ./$(DEPDIR)/lib579-first.Po
	-rm -f ./$(DEPDIR)/lib579-lib579.Po
	-rm -f ./$(DEPDIR)/lib582-first.Po
	-rm -f ./$(DEPDIR)/lib582-lib582.Po
	-rm -f ./$(DEPDIR)/lib582-testutil.Po
	-rm -f ./$(DEPDIR)/lib583-first.Po
	-rm -f ./$(DEPDIR)/lib583-lib583.Po


	-rm -f ./$(DEPDIR)/lib585-first.Po
	-rm -f ./$(DEPDIR)/lib585-lib500.Po
	-rm -f ./$(DEPDIR)/lib585-testtrace.Po
	-rm -f ./$(DEPDIR)/lib585-testutil.Po
	-rm -f ./$(DEPDIR)/lib586-first.Po
	-rm -f ./$(DEPDIR)/lib586-lib586.Po
	-rm -f ./$(DEPDIR)/lib587-first.Po







>
>







12583
12584
12585
12586
12587
12588
12589
12590
12591
12592
12593
12594
12595
12596
12597
12598
	-rm -f ./$(DEPDIR)/lib579-first.Po
	-rm -f ./$(DEPDIR)/lib579-lib579.Po
	-rm -f ./$(DEPDIR)/lib582-first.Po
	-rm -f ./$(DEPDIR)/lib582-lib582.Po
	-rm -f ./$(DEPDIR)/lib582-testutil.Po
	-rm -f ./$(DEPDIR)/lib583-first.Po
	-rm -f ./$(DEPDIR)/lib583-lib583.Po
	-rm -f ./$(DEPDIR)/lib584-first.Po
	-rm -f ./$(DEPDIR)/lib584-lib589.Po
	-rm -f ./$(DEPDIR)/lib585-first.Po
	-rm -f ./$(DEPDIR)/lib585-lib500.Po
	-rm -f ./$(DEPDIR)/lib585-testtrace.Po
	-rm -f ./$(DEPDIR)/lib585-testutil.Po
	-rm -f ./$(DEPDIR)/lib586-first.Po
	-rm -f ./$(DEPDIR)/lib586-lib586.Po
	-rm -f ./$(DEPDIR)/lib587-first.Po
12103
12104
12105
12106
12107
12108
12109







12110
12111
12112
12113
12114
12115
12116
	-rm -f ../../lib/$(DEPDIR)/lib1907-warnless.Po
	-rm -f ../../lib/$(DEPDIR)/lib1908-warnless.Po
	-rm -f ../../lib/$(DEPDIR)/lib1910-warnless.Po
	-rm -f ../../lib/$(DEPDIR)/lib1911-warnless.Po
	-rm -f ../../lib/$(DEPDIR)/lib1912-warnless.Po
	-rm -f ../../lib/$(DEPDIR)/lib1913-warnless.Po
	-rm -f ../../lib/$(DEPDIR)/lib1915-warnless.Po







	-rm -f ../../lib/$(DEPDIR)/lib3010-warnless.Po
	-rm -f ../../lib/$(DEPDIR)/lib500-curl_multibyte.Po
	-rm -f ../../lib/$(DEPDIR)/lib502-warnless.Po
	-rm -f ../../lib/$(DEPDIR)/lib503-warnless.Po
	-rm -f ../../lib/$(DEPDIR)/lib504-warnless.Po
	-rm -f ../../lib/$(DEPDIR)/lib505-curl_multibyte.Po
	-rm -f ../../lib/$(DEPDIR)/lib507-warnless.Po







>
>
>
>
>
>
>







12763
12764
12765
12766
12767
12768
12769
12770
12771
12772
12773
12774
12775
12776
12777
12778
12779
12780
12781
12782
12783
	-rm -f ../../lib/$(DEPDIR)/lib1907-warnless.Po
	-rm -f ../../lib/$(DEPDIR)/lib1908-warnless.Po
	-rm -f ../../lib/$(DEPDIR)/lib1910-warnless.Po
	-rm -f ../../lib/$(DEPDIR)/lib1911-warnless.Po
	-rm -f ../../lib/$(DEPDIR)/lib1912-warnless.Po
	-rm -f ../../lib/$(DEPDIR)/lib1913-warnless.Po
	-rm -f ../../lib/$(DEPDIR)/lib1915-warnless.Po
	-rm -f ../../lib/$(DEPDIR)/lib1916-warnless.Po
	-rm -f ../../lib/$(DEPDIR)/lib1917-warnless.Po
	-rm -f ../../lib/$(DEPDIR)/lib1918-warnless.Po
	-rm -f ../../lib/$(DEPDIR)/lib1933-warnless.Po
	-rm -f ../../lib/$(DEPDIR)/lib1934-warnless.Po
	-rm -f ../../lib/$(DEPDIR)/lib1935-warnless.Po
	-rm -f ../../lib/$(DEPDIR)/lib1936-warnless.Po
	-rm -f ../../lib/$(DEPDIR)/lib3010-warnless.Po
	-rm -f ../../lib/$(DEPDIR)/lib500-curl_multibyte.Po
	-rm -f ../../lib/$(DEPDIR)/lib502-warnless.Po
	-rm -f ../../lib/$(DEPDIR)/lib503-warnless.Po
	-rm -f ../../lib/$(DEPDIR)/lib504-warnless.Po
	-rm -f ../../lib/$(DEPDIR)/lib505-curl_multibyte.Po
	-rm -f ../../lib/$(DEPDIR)/lib507-warnless.Po
12221
12222
12223
12224
12225
12226
12227


12228
12229
12230
12231
12232
12233
12234
	-rm -f ./$(DEPDIR)/lib1518-lib1518.Po
	-rm -f ./$(DEPDIR)/lib1520-first.Po
	-rm -f ./$(DEPDIR)/lib1520-lib1520.Po
	-rm -f ./$(DEPDIR)/lib1521-first.Po
	-rm -f ./$(DEPDIR)/lib1521-lib1521.Po
	-rm -f ./$(DEPDIR)/lib1522-first.Po
	-rm -f ./$(DEPDIR)/lib1522-lib1522.Po


	-rm -f ./$(DEPDIR)/lib1523-first.Po
	-rm -f ./$(DEPDIR)/lib1523-lib1523.Po
	-rm -f ./$(DEPDIR)/lib1525-first.Po
	-rm -f ./$(DEPDIR)/lib1525-lib1525.Po
	-rm -f ./$(DEPDIR)/lib1525-testutil.Po
	-rm -f ./$(DEPDIR)/lib1526-first.Po
	-rm -f ./$(DEPDIR)/lib1526-lib1526.Po







>
>







12888
12889
12890
12891
12892
12893
12894
12895
12896
12897
12898
12899
12900
12901
12902
12903
	-rm -f ./$(DEPDIR)/lib1518-lib1518.Po
	-rm -f ./$(DEPDIR)/lib1520-first.Po
	-rm -f ./$(DEPDIR)/lib1520-lib1520.Po
	-rm -f ./$(DEPDIR)/lib1521-first.Po
	-rm -f ./$(DEPDIR)/lib1521-lib1521.Po
	-rm -f ./$(DEPDIR)/lib1522-first.Po
	-rm -f ./$(DEPDIR)/lib1522-lib1522.Po
	-rm -f ./$(DEPDIR)/lib1522-testtrace.Po
	-rm -f ./$(DEPDIR)/lib1522-testutil.Po
	-rm -f ./$(DEPDIR)/lib1523-first.Po
	-rm -f ./$(DEPDIR)/lib1523-lib1523.Po
	-rm -f ./$(DEPDIR)/lib1525-first.Po
	-rm -f ./$(DEPDIR)/lib1525-lib1525.Po
	-rm -f ./$(DEPDIR)/lib1525-testutil.Po
	-rm -f ./$(DEPDIR)/lib1526-first.Po
	-rm -f ./$(DEPDIR)/lib1526-lib1526.Po
12303
12304
12305
12306
12307
12308
12309


12310
12311
12312
12313
12314
12315
12316
	-rm -f ./$(DEPDIR)/lib1564-lib1564.Po
	-rm -f ./$(DEPDIR)/lib1564-testutil.Po
	-rm -f ./$(DEPDIR)/lib1565-first.Po
	-rm -f ./$(DEPDIR)/lib1565-lib1565.Po
	-rm -f ./$(DEPDIR)/lib1565-testutil.Po
	-rm -f ./$(DEPDIR)/lib1567-first.Po
	-rm -f ./$(DEPDIR)/lib1567-lib1567.Po


	-rm -f ./$(DEPDIR)/lib1591-first.Po
	-rm -f ./$(DEPDIR)/lib1591-lib1591.Po
	-rm -f ./$(DEPDIR)/lib1591-testutil.Po
	-rm -f ./$(DEPDIR)/lib1592-first.Po
	-rm -f ./$(DEPDIR)/lib1592-lib1592.Po
	-rm -f ./$(DEPDIR)/lib1592-testutil.Po
	-rm -f ./$(DEPDIR)/lib1593.Po







>
>







12972
12973
12974
12975
12976
12977
12978
12979
12980
12981
12982
12983
12984
12985
12986
12987
	-rm -f ./$(DEPDIR)/lib1564-lib1564.Po
	-rm -f ./$(DEPDIR)/lib1564-testutil.Po
	-rm -f ./$(DEPDIR)/lib1565-first.Po
	-rm -f ./$(DEPDIR)/lib1565-lib1565.Po
	-rm -f ./$(DEPDIR)/lib1565-testutil.Po
	-rm -f ./$(DEPDIR)/lib1567-first.Po
	-rm -f ./$(DEPDIR)/lib1567-lib1567.Po
	-rm -f ./$(DEPDIR)/lib1568-first.Po
	-rm -f ./$(DEPDIR)/lib1568-lib1568.Po
	-rm -f ./$(DEPDIR)/lib1591-first.Po
	-rm -f ./$(DEPDIR)/lib1591-lib1591.Po
	-rm -f ./$(DEPDIR)/lib1591-testutil.Po
	-rm -f ./$(DEPDIR)/lib1592-first.Po
	-rm -f ./$(DEPDIR)/lib1592-lib1592.Po
	-rm -f ./$(DEPDIR)/lib1592-testutil.Po
	-rm -f ./$(DEPDIR)/lib1593.Po
12341
12342
12343
12344
12345
12346
12347


















12348
12349
12350
12351
12352
12353
12354
	-rm -f ./$(DEPDIR)/lib1912-testutil.Po
	-rm -f ./$(DEPDIR)/lib1913-first.Po
	-rm -f ./$(DEPDIR)/lib1913-lib1913.Po
	-rm -f ./$(DEPDIR)/lib1913-testutil.Po
	-rm -f ./$(DEPDIR)/lib1915-first.Po
	-rm -f ./$(DEPDIR)/lib1915-lib1915.Po
	-rm -f ./$(DEPDIR)/lib1915-testutil.Po


















	-rm -f ./$(DEPDIR)/lib3010-first.Po
	-rm -f ./$(DEPDIR)/lib3010-lib3010.Po
	-rm -f ./$(DEPDIR)/lib3010-testutil.Po
	-rm -f ./$(DEPDIR)/lib500-first.Po
	-rm -f ./$(DEPDIR)/lib500-lib500.Po
	-rm -f ./$(DEPDIR)/lib500-testtrace.Po
	-rm -f ./$(DEPDIR)/lib500-testutil.Po







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







13012
13013
13014
13015
13016
13017
13018
13019
13020
13021
13022
13023
13024
13025
13026
13027
13028
13029
13030
13031
13032
13033
13034
13035
13036
13037
13038
13039
13040
13041
13042
13043
	-rm -f ./$(DEPDIR)/lib1912-testutil.Po
	-rm -f ./$(DEPDIR)/lib1913-first.Po
	-rm -f ./$(DEPDIR)/lib1913-lib1913.Po
	-rm -f ./$(DEPDIR)/lib1913-testutil.Po
	-rm -f ./$(DEPDIR)/lib1915-first.Po
	-rm -f ./$(DEPDIR)/lib1915-lib1915.Po
	-rm -f ./$(DEPDIR)/lib1915-testutil.Po
	-rm -f ./$(DEPDIR)/lib1916-first.Po
	-rm -f ./$(DEPDIR)/lib1916-lib1916.Po
	-rm -f ./$(DEPDIR)/lib1917-first.Po
	-rm -f ./$(DEPDIR)/lib1917-lib1916.Po
	-rm -f ./$(DEPDIR)/lib1918-first.Po
	-rm -f ./$(DEPDIR)/lib1918-lib1918.Po
	-rm -f ./$(DEPDIR)/lib1933-first.Po
	-rm -f ./$(DEPDIR)/lib1933-lib1933.Po
	-rm -f ./$(DEPDIR)/lib1933-testutil.Po
	-rm -f ./$(DEPDIR)/lib1934-first.Po
	-rm -f ./$(DEPDIR)/lib1934-lib1934.Po
	-rm -f ./$(DEPDIR)/lib1934-testutil.Po
	-rm -f ./$(DEPDIR)/lib1935-first.Po
	-rm -f ./$(DEPDIR)/lib1935-lib1935.Po
	-rm -f ./$(DEPDIR)/lib1935-testutil.Po
	-rm -f ./$(DEPDIR)/lib1936-first.Po
	-rm -f ./$(DEPDIR)/lib1936-lib1936.Po
	-rm -f ./$(DEPDIR)/lib1936-testutil.Po
	-rm -f ./$(DEPDIR)/lib3010-first.Po
	-rm -f ./$(DEPDIR)/lib3010-lib3010.Po
	-rm -f ./$(DEPDIR)/lib3010-testutil.Po
	-rm -f ./$(DEPDIR)/lib500-first.Po
	-rm -f ./$(DEPDIR)/lib500-lib500.Po
	-rm -f ./$(DEPDIR)/lib500-testtrace.Po
	-rm -f ./$(DEPDIR)/lib500-testutil.Po
12500
12501
12502
12503
12504
12505
12506


12507
12508
12509
12510
12511
12512
12513
	-rm -f ./$(DEPDIR)/lib579-first.Po
	-rm -f ./$(DEPDIR)/lib579-lib579.Po
	-rm -f ./$(DEPDIR)/lib582-first.Po
	-rm -f ./$(DEPDIR)/lib582-lib582.Po
	-rm -f ./$(DEPDIR)/lib582-testutil.Po
	-rm -f ./$(DEPDIR)/lib583-first.Po
	-rm -f ./$(DEPDIR)/lib583-lib583.Po


	-rm -f ./$(DEPDIR)/lib585-first.Po
	-rm -f ./$(DEPDIR)/lib585-lib500.Po
	-rm -f ./$(DEPDIR)/lib585-testtrace.Po
	-rm -f ./$(DEPDIR)/lib585-testutil.Po
	-rm -f ./$(DEPDIR)/lib586-first.Po
	-rm -f ./$(DEPDIR)/lib586-lib586.Po
	-rm -f ./$(DEPDIR)/lib587-first.Po







>
>







13189
13190
13191
13192
13193
13194
13195
13196
13197
13198
13199
13200
13201
13202
13203
13204
	-rm -f ./$(DEPDIR)/lib579-first.Po
	-rm -f ./$(DEPDIR)/lib579-lib579.Po
	-rm -f ./$(DEPDIR)/lib582-first.Po
	-rm -f ./$(DEPDIR)/lib582-lib582.Po
	-rm -f ./$(DEPDIR)/lib582-testutil.Po
	-rm -f ./$(DEPDIR)/lib583-first.Po
	-rm -f ./$(DEPDIR)/lib583-lib583.Po
	-rm -f ./$(DEPDIR)/lib584-first.Po
	-rm -f ./$(DEPDIR)/lib584-lib589.Po
	-rm -f ./$(DEPDIR)/lib585-first.Po
	-rm -f ./$(DEPDIR)/lib585-lib500.Po
	-rm -f ./$(DEPDIR)/lib585-testtrace.Po
	-rm -f ./$(DEPDIR)/lib585-testutil.Po
	-rm -f ./$(DEPDIR)/lib586-first.Po
	-rm -f ./$(DEPDIR)/lib586-lib586.Po
	-rm -f ./$(DEPDIR)/lib587-first.Po
Changes to jni/curl/tests/libtest/Makefile.inc.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#***************************************************************************
#                                  _   _ ____  _
#  Project                     ___| | | |  _ \| |
#                             / __| | | | |_) | |
#                            | (__| |_| |  _ <| |___
#                             \___|\___/|_| \_\_____|
#
# Copyright (C) 1998 - 2020, 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 https://curl.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







|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#***************************************************************************
#                                  _   _ ____  _
#  Project                     ___| | | |  _ \| |
#                             / __| | | | |_) | |
#                            | (__| |_| |  _ <| |___
#                             \___|\___/|_| \_\_____|
#
# Copyright (C) 1998 - 2021, 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 https://curl.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
40
41
42
43
44
45
46
47

48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
 lib500 lib501 lib502 lib503 lib504 lib505 lib506 lib507 lib508 lib509   \
 lib510 lib511 lib512 lib513 lib514 lib515 lib516 lib517 lib518 lib519   \
 lib520 lib521 lib523 lib524 lib525 lib526 lib527 lib529        lib532   \
 lib533        lib537 lib539 lib540 lib541 lib542 lib543 lib544 lib545   \
 lib547 lib548 lib549 lib552 lib553 lib554 lib555 lib556 lib557 lib558   \
 lib559 lib560 lib562 lib564 lib565 lib566 lib567 lib568 lib569 lib570   \
 lib571 lib572 lib573 lib574 lib575 lib576        lib578 lib579 lib582   \
 lib583 lib585 lib586 lib587 lib589 lib590 lib591 lib597 lib598 lib599   \

 lib643 lib644 lib645 lib650 lib651 lib652 lib653 lib654 lib655 lib658   \
 lib659 lib661 lib666 lib667 lib668 \
 lib670 lib671 lib672 lib673 lib674 \
 lib1156 \
 lib1500 lib1501 lib1502 lib1503 lib1504 lib1505 lib1506 lib1507 lib1508 \
 lib1509 lib1510 lib1511 lib1512 lib1513 lib1514 lib1515         lib1517 \
 lib1518         lib1520 lib1521 lib1522 lib1523 \
 lib1525 lib1526 lib1527 lib1528 lib1529 lib1530 lib1531 lib1532 lib1533 \
 lib1534 lib1535 lib1536 lib1537 lib1538 lib1539 \
 lib1540         \
 lib1550 lib1551 lib1552 lib1553 lib1554 lib1555 lib1556 lib1557 \
 lib1558 lib1559 lib1560 lib1564 lib1565 lib1567 \
 lib1591 lib1592 lib1593 lib1594 lib1596 \
         lib1905 lib1906 lib1907 lib1908 lib1910 lib1911 lib1912 lib1913 \
         lib1915 \
         lib3010

chkdecimalpoint_SOURCES = chkdecimalpoint.c ../../lib/mprintf.c \
 ../../lib/curl_ctype.c  ../../lib/dynbuf.c ../../lib/strdup.c
chkdecimalpoint_LDADD =
chkdecimalpoint_CPPFLAGS = $(AM_CPPFLAGS) -DCURL_STATICLIB \
 -DCURLX_NO_MEMORY_CALLBACKS -DBUILDING_LIBCURL







|
>











|


|







40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
 lib500 lib501 lib502 lib503 lib504 lib505 lib506 lib507 lib508 lib509   \
 lib510 lib511 lib512 lib513 lib514 lib515 lib516 lib517 lib518 lib519   \
 lib520 lib521 lib523 lib524 lib525 lib526 lib527 lib529        lib532   \
 lib533        lib537 lib539 lib540 lib541 lib542 lib543 lib544 lib545   \
 lib547 lib548 lib549 lib552 lib553 lib554 lib555 lib556 lib557 lib558   \
 lib559 lib560 lib562 lib564 lib565 lib566 lib567 lib568 lib569 lib570   \
 lib571 lib572 lib573 lib574 lib575 lib576        lib578 lib579 lib582   \
 lib583 lib584 lib585 lib586 lib587 lib589 lib590 lib591 lib597 lib598   \
 lib599 \
 lib643 lib644 lib645 lib650 lib651 lib652 lib653 lib654 lib655 lib658   \
 lib659 lib661 lib666 lib667 lib668 \
 lib670 lib671 lib672 lib673 lib674 \
 lib1156 \
 lib1500 lib1501 lib1502 lib1503 lib1504 lib1505 lib1506 lib1507 lib1508 \
 lib1509 lib1510 lib1511 lib1512 lib1513 lib1514 lib1515         lib1517 \
 lib1518         lib1520 lib1521 lib1522 lib1523 \
 lib1525 lib1526 lib1527 lib1528 lib1529 lib1530 lib1531 lib1532 lib1533 \
 lib1534 lib1535 lib1536 lib1537 lib1538 lib1539 \
 lib1540         \
 lib1550 lib1551 lib1552 lib1553 lib1554 lib1555 lib1556 lib1557 \
 lib1558 lib1559 lib1560 lib1564 lib1565 lib1567 lib1568 \
 lib1591 lib1592 lib1593 lib1594 lib1596 \
         lib1905 lib1906 lib1907 lib1908 lib1910 lib1911 lib1912 lib1913 \
         lib1915 lib1916 lib1917 lib1918 lib1933 lib1934 lib1935 lib1936 \
         lib3010

chkdecimalpoint_SOURCES = chkdecimalpoint.c ../../lib/mprintf.c \
 ../../lib/curl_ctype.c  ../../lib/dynbuf.c ../../lib/strdup.c
chkdecimalpoint_LDADD =
chkdecimalpoint_CPPFLAGS = $(AM_CPPFLAGS) -DCURL_STATICLIB \
 -DCURLX_NO_MEMORY_CALLBACKS -DBUILDING_LIBCURL
297
298
299
300
301
302
303



304
305
306
307
308
309
310

lib582_SOURCES = lib582.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS) $(MULTIBYTE)
lib582_LDADD = $(TESTUTIL_LIBS)
lib582_CPPFLAGS = $(AM_CPPFLAGS)

lib583_SOURCES = lib583.c $(SUPPORTFILES)
lib583_CPPFLAGS = $(AM_CPPFLAGS)




lib585_SOURCES = lib500.c $(SUPPORTFILES) $(TESTUTIL) $(TSTTRACE) $(MULTIBYTE)
lib585_LDADD = $(TESTUTIL_LIBS)
lib585_CPPFLAGS = $(AM_CPPFLAGS) -DLIB585

lib586_SOURCES = lib586.c $(SUPPORTFILES)
lib586_CPPFLAGS = $(AM_CPPFLAGS)







>
>
>







298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314

lib582_SOURCES = lib582.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS) $(MULTIBYTE)
lib582_LDADD = $(TESTUTIL_LIBS)
lib582_CPPFLAGS = $(AM_CPPFLAGS)

lib583_SOURCES = lib583.c $(SUPPORTFILES)
lib583_CPPFLAGS = $(AM_CPPFLAGS)

lib584_SOURCES = lib589.c $(SUPPORTFILES)
lib584_CPPFLAGS = $(AM_CPPFLAGS) -DLIB584

lib585_SOURCES = lib500.c $(SUPPORTFILES) $(TESTUTIL) $(TSTTRACE) $(MULTIBYTE)
lib585_LDADD = $(TESTUTIL_LIBS)
lib585_CPPFLAGS = $(AM_CPPFLAGS) -DLIB585

lib586_SOURCES = lib586.c $(SUPPORTFILES)
lib586_CPPFLAGS = $(AM_CPPFLAGS)
477
478
479
480
481
482
483
484

485
486
487
488
489
490
491

lib1520_SOURCES = lib1520.c $(SUPPORTFILES)
lib1520_CPPFLAGS = $(AM_CPPFLAGS) -DLIB1520

nodist_lib1521_SOURCES = lib1521.c $(SUPPORTFILES)
lib1521_CPPFLAGS = $(AM_CPPFLAGS) -I$(srcdir)

lib1522_SOURCES = lib1522.c $(SUPPORTFILES)

lib1522_CPPFLAGS = $(AM_CPPFLAGS)

lib1523_SOURCES = lib1523.c $(SUPPORTFILES)
lib1523_CPPFLAGS = $(AM_CPPFLAGS)

lib1525_SOURCES = lib1525.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS)
lib1525_LDADD = $(TESTUTIL_LIBS)







|
>







481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496

lib1520_SOURCES = lib1520.c $(SUPPORTFILES)
lib1520_CPPFLAGS = $(AM_CPPFLAGS) -DLIB1520

nodist_lib1521_SOURCES = lib1521.c $(SUPPORTFILES)
lib1521_CPPFLAGS = $(AM_CPPFLAGS) -I$(srcdir)

lib1522_SOURCES = lib1522.c $(SUPPORTFILES) $(TESTUTIL) $(TSTTRACE) 
lib1522_LDADD = $(TESTUTIL_LIBS)
lib1522_CPPFLAGS = $(AM_CPPFLAGS)

lib1523_SOURCES = lib1523.c $(SUPPORTFILES)
lib1523_CPPFLAGS = $(AM_CPPFLAGS)

lib1525_SOURCES = lib1525.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS)
lib1525_LDADD = $(TESTUTIL_LIBS)
595
596
597
598
599
600
601



602
603
604
605
606
607
608

lib1565_SOURCES = lib1565.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS)
lib1565_LDADD = $(TESTUTIL_LIBS)
lib1565_CPPFLAGS = $(AM_CPPFLAGS)

lib1567_SOURCES = lib1567.c $(SUPPORTFILES)
lib1567_CPPFLAGS = $(AM_CPPFLAGS)




lib1591_SOURCES = lib1591.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS)
lib1591_LDADD = $(TESTUTIL_LIBS)
lib1591_CPPFLAGS = $(AM_CPPFLAGS) -DLIB1591

lib1592_SOURCES = lib1592.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS)
lib1592_LDADD = $(TESTUTIL_LIBS)







>
>
>







600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616

lib1565_SOURCES = lib1565.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS)
lib1565_LDADD = $(TESTUTIL_LIBS)
lib1565_CPPFLAGS = $(AM_CPPFLAGS)

lib1567_SOURCES = lib1567.c $(SUPPORTFILES)
lib1567_CPPFLAGS = $(AM_CPPFLAGS)

lib1568_SOURCES = lib1568.c $(SUPPORTFILES)
lib1568_CPPFLAGS = $(AM_CPPFLAGS)

lib1591_SOURCES = lib1591.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS)
lib1591_LDADD = $(TESTUTIL_LIBS)
lib1591_CPPFLAGS = $(AM_CPPFLAGS) -DLIB1591

lib1592_SOURCES = lib1592.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS)
lib1592_LDADD = $(TESTUTIL_LIBS)
649
650
651
652
653
654
655

























656
657
658
659
lib1913_SOURCES = lib1913.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS)
lib1913_LDADD = $(TESTUTIL_LIBS)
lib1913_CPPFLAGS = $(AM_CPPFLAGS)

lib1915_SOURCES = lib1915.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS)
lib1915_LDADD = $(TESTUTIL_LIBS)
lib1915_CPPFLAGS = $(AM_CPPFLAGS)


























lib3010_SOURCES = lib3010.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS)
lib3010_LDADD = $(TESTUTIL_LIBS)
lib3010_CPPFLAGS = $(AM_CPPFLAGS)







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>




657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
lib1913_SOURCES = lib1913.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS)
lib1913_LDADD = $(TESTUTIL_LIBS)
lib1913_CPPFLAGS = $(AM_CPPFLAGS)

lib1915_SOURCES = lib1915.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS)
lib1915_LDADD = $(TESTUTIL_LIBS)
lib1915_CPPFLAGS = $(AM_CPPFLAGS)

lib1916_SOURCES = lib1916.c $(SUPPORTFILES) $(WARNLESS)
lib1916_CPPFLAGS = $(AM_CPPFLAGS)

lib1917_SOURCES = lib1916.c $(SUPPORTFILES) $(WARNLESS)
lib1917_CPPFLAGS = $(AM_CPPFLAGS) -DLIB1917

lib1918_SOURCES = lib1918.c $(SUPPORTFILES) $(WARNLESS)
lib1918_CPPFLAGS = $(AM_CPPFLAGS)

lib1933_SOURCES = lib1933.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS)
lib1933_LDADD = $(TESTUTIL_LIBS)
lib1933_CPPFLAGS = $(AM_CPPFLAGS)

lib1934_SOURCES = lib1934.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS)
lib1934_LDADD = $(TESTUTIL_LIBS)
lib1934_CPPFLAGS = $(AM_CPPFLAGS)

lib1935_SOURCES = lib1935.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS)
lib1935_LDADD = $(TESTUTIL_LIBS)
lib1935_CPPFLAGS = $(AM_CPPFLAGS)

lib1936_SOURCES = lib1936.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS)
lib1936_LDADD = $(TESTUTIL_LIBS)
lib1936_CPPFLAGS = $(AM_CPPFLAGS)

lib3010_SOURCES = lib3010.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS)
lib3010_LDADD = $(TESTUTIL_LIBS)
lib3010_CPPFLAGS = $(AM_CPPFLAGS)
Changes to jni/curl/tests/libtest/first.c.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2020, 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 https://curl.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







|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2021, 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 https://curl.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
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
#  endif
#endif

  memory_tracking_init();

  /*
   * Setup proper locale from environment. This is needed to enable locale-
   * specific behaviour by the C library in order to test for undesired side
   * effects that could cause in libcurl.
   */
#ifdef HAVE_SETLOCALE
  setlocale(LC_ALL, "");
#endif

  if(argc< 2) {







|







142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
#  endif
#endif

  memory_tracking_init();

  /*
   * Setup proper locale from environment. This is needed to enable locale-
   * specific behavior by the C library in order to test for undesired side
   * effects that could cause in libcurl.
   */
#ifdef HAVE_SETLOCALE
  setlocale(LC_ALL, "");
#endif

  if(argc< 2) {
Changes to jni/curl/tests/libtest/lib1502.c.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2020, 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 https://curl.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







|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2021, 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 https://curl.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
45
46
47
48
49
50
51





52
53
54
55
56
57
58
59
60

61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83

84
85
86
87
88
89
90
  int still_running;
  int res = 0;

  char redirect[160];

  /* DNS cache injection */
  struct curl_slist *dns_cache_list;






  msnprintf(redirect, sizeof(redirect), "google.com:%s:%s", libtest_arg2,
            libtest_arg3);

  start_test_timing();

  dns_cache_list = curl_slist_append(NULL, redirect);
  if(!dns_cache_list) {
    fprintf(stderr, "curl_slist_append() failed\n");

    return TEST_ERR_MAJOR_BAD;
  }

  res_global_init(CURL_GLOBAL_ALL);
  if(res) {
    curl_slist_free_all(dns_cache_list);
    return res;
  }

  easy_init(easy);

  easy_setopt(easy, CURLOPT_URL, URL);
  easy_setopt(easy, CURLOPT_HEADER, 1L);
  easy_setopt(easy, CURLOPT_RESOLVE, dns_cache_list);

  dup = curl_easy_duphandle(easy);
  if(dup) {
    curl_easy_cleanup(easy);
    easy = dup;
  }
  else {
    curl_slist_free_all(dns_cache_list);
    curl_easy_cleanup(easy);

    return CURLE_OUT_OF_MEMORY;
  }

  multi_init(multi);

  multi_add_handle(multi, easy);








>
>
>
>
>









>



<
<
<
<
<
<














>







45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69






70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
  int still_running;
  int res = 0;

  char redirect[160];

  /* DNS cache injection */
  struct curl_slist *dns_cache_list;

  res_global_init(CURL_GLOBAL_ALL);
  if(res) {
    return res;
  }

  msnprintf(redirect, sizeof(redirect), "google.com:%s:%s", libtest_arg2,
            libtest_arg3);

  start_test_timing();

  dns_cache_list = curl_slist_append(NULL, redirect);
  if(!dns_cache_list) {
    fprintf(stderr, "curl_slist_append() failed\n");
    curl_global_cleanup();
    return TEST_ERR_MAJOR_BAD;
  }







  easy_init(easy);

  easy_setopt(easy, CURLOPT_URL, URL);
  easy_setopt(easy, CURLOPT_HEADER, 1L);
  easy_setopt(easy, CURLOPT_RESOLVE, dns_cache_list);

  dup = curl_easy_duphandle(easy);
  if(dup) {
    curl_easy_cleanup(easy);
    easy = dup;
  }
  else {
    curl_slist_free_all(dns_cache_list);
    curl_easy_cleanup(easy);
    curl_global_cleanup();
    return CURLE_OUT_OF_MEMORY;
  }

  multi_init(multi);

  multi_add_handle(multi, easy);

Changes to jni/curl/tests/libtest/lib1507.c.
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
#define USERNAME "user@example.com"
#define PASSWORD "123qwerty"
#define RECIPIENT "<1507-recipient@example.com>"
#define MAILFROM "<1507-realuser@example.com>"

#define MULTI_PERFORM_HANG_TIMEOUT 60 * 1000

static size_t read_callback(void *ptr, size_t size, size_t nmemb, void *userp)
{
  (void)ptr;
  (void)size;
  (void)nmemb;
  (void)userp;
  return CURL_READFUNC_ABORT;
}







|







31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
#define USERNAME "user@example.com"
#define PASSWORD "123qwerty"
#define RECIPIENT "<1507-recipient@example.com>"
#define MAILFROM "<1507-realuser@example.com>"

#define MULTI_PERFORM_HANG_TIMEOUT 60 * 1000

static size_t read_callback(char *ptr, size_t size, size_t nmemb, void *userp)
{
  (void)ptr;
  (void)size;
  (void)nmemb;
  (void)userp;
  return CURL_READFUNC_ABORT;
}
Changes to jni/curl/tests/libtest/lib1514.c.
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
static char data[]="dummy";

struct WriteThis {
  char *readptr;
  size_t sizeleft;
};

static size_t read_callback(void *ptr, size_t size, size_t nmemb, void *userp)
{
  struct WriteThis *pooh = (struct WriteThis *)userp;

  if(size*nmemb < 1)
    return 0;

  if(pooh->sizeleft) {
    *(char *)ptr = pooh->readptr[0]; /* copy one single byte */
    pooh->readptr++;                 /* advance pointer */
    pooh->sizeleft--;                /* less data left */
    return 1;                        /* we return 1 byte at a time! */
  }

  return 0;                         /* no more data left to deliver */
}







|







|







31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
static char data[]="dummy";

struct WriteThis {
  char *readptr;
  size_t sizeleft;
};

static size_t read_callback(char *ptr, size_t size, size_t nmemb, void *userp)
{
  struct WriteThis *pooh = (struct WriteThis *)userp;

  if(size*nmemb < 1)
    return 0;

  if(pooh->sizeleft) {
    *ptr = pooh->readptr[0]; /* copy one single byte */
    pooh->readptr++;                 /* advance pointer */
    pooh->sizeleft--;                /* less data left */
    return 1;                        /* we return 1 byte at a time! */
  }

  return 0;                         /* no more data left to deliver */
}
Changes to jni/curl/tests/libtest/lib1517.c.
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
static char data[]="this is what we post to the silly web server\n";

struct WriteThis {
  char *readptr;
  size_t sizeleft;
};

static size_t read_callback(void *ptr, size_t size, size_t nmemb, void *userp)
{
  struct WriteThis *pooh = (struct WriteThis *)userp;
  size_t tocopy = size * nmemb;

  /* Wait one second before return POST data          *
   * so libcurl will wait before sending request body */
  wait_ms(1000);







|







26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
static char data[]="this is what we post to the silly web server\n";

struct WriteThis {
  char *readptr;
  size_t sizeleft;
};

static size_t read_callback(char *ptr, size_t size, size_t nmemb, void *userp)
{
  struct WriteThis *pooh = (struct WriteThis *)userp;
  size_t tocopy = size * nmemb;

  /* Wait one second before return POST data          *
   * so libcurl will wait before sending request body */
  wait_ms(1000);
Changes to jni/curl/tests/libtest/lib1520.c.
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
  NULL
};

struct upload_status {
  int lines_read;
};

static size_t read_callback(void *ptr, size_t size, size_t nmemb, void *userp)
{
  struct upload_status *upload_ctx = (struct upload_status *)userp;
  const char *data;

  if((size == 0) || (nmemb == 0) || ((size*nmemb) < 1)) {
    return 0;
  }







|







43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
  NULL
};

struct upload_status {
  int lines_read;
};

static size_t read_callback(char *ptr, size_t size, size_t nmemb, void *userp)
{
  struct upload_status *upload_ctx = (struct upload_status *)userp;
  const char *data;

  if((size == 0) || (nmemb == 0) || ((size*nmemb) < 1)) {
    return 0;
  }
Changes to jni/curl/tests/libtest/lib1522.c.
19
20
21
22
23
24
25

26
27
28
29
30
31
32
 * KIND, either express or implied.
 *
 ***************************************************************************/
#include "test.h"

/* test case and code based on https://github.com/curl/curl/issues/2847 */


#include "testutil.h"
#include "warnless.h"
#include "memdebug.h"

static char g_Data[40 * 1024]; /* POST 40KB */

static int sockopt_callback(void *clientp, curl_socket_t curlfd,







>







19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
 * KIND, either express or implied.
 *
 ***************************************************************************/
#include "test.h"

/* test case and code based on https://github.com/curl/curl/issues/2847 */

#include "testtrace.h"
#include "testutil.h"
#include "warnless.h"
#include "memdebug.h"

static char g_Data[40 * 1024]; /* POST 40KB */

static int sockopt_callback(void *clientp, curl_socket_t curlfd,
45
46
47
48
49
50
51

52
53
54
55
56
57
58
59






60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78

79
80
81
82
83
84
85
86
87
88
89
90
#endif
  return CURL_SOCKOPT_OK;
}

int test(char *URL)
{
  CURLcode code;

  struct curl_slist *pHeaderList = NULL;
  CURL *pCurl = curl_easy_init();
  memset(g_Data, 'A', sizeof(g_Data)); /* send As! */

  curl_easy_setopt(pCurl, CURLOPT_SOCKOPTFUNCTION, sockopt_callback);
  curl_easy_setopt(pCurl, CURLOPT_URL, URL);
  curl_easy_setopt(pCurl, CURLOPT_POSTFIELDS, g_Data);
  curl_easy_setopt(pCurl, CURLOPT_POSTFIELDSIZE, (long)sizeof(g_Data));







  /* Remove "Expect: 100-continue" */
  pHeaderList = curl_slist_append(pHeaderList, "Expect:");

  curl_easy_setopt(pCurl, CURLOPT_HTTPHEADER, pHeaderList);

  code = curl_easy_perform(pCurl);

  if(code == CURLE_OK) {
    curl_off_t uploadSize;
    curl_easy_getinfo(pCurl, CURLINFO_SIZE_UPLOAD_T, &uploadSize);

    printf("uploadSize = %ld\n", (long)uploadSize);

    if((size_t) uploadSize == sizeof(g_Data)) {
      printf("!!!!!!!!!! PASS\n");
    }
    else {
      printf("!!!!!!!!!! FAIL\n");

    }
  }
  else {
    printf("curl_easy_perform() failed. e = %d\n", code);
  }

  curl_slist_free_all(pHeaderList);
  curl_easy_cleanup(pCurl);
  curl_global_cleanup();

  return 0;
}







>

|


|
|
|
|
>
>
>
>
>
>




|

|



|







|
>





|

|




46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
#endif
  return CURL_SOCKOPT_OK;
}

int test(char *URL)
{
  CURLcode code;
  CURLcode res;
  struct curl_slist *pHeaderList = NULL;
  CURL *curl = curl_easy_init();
  memset(g_Data, 'A', sizeof(g_Data)); /* send As! */

  curl_easy_setopt(curl, CURLOPT_SOCKOPTFUNCTION, sockopt_callback);
  curl_easy_setopt(curl, CURLOPT_URL, URL);
  curl_easy_setopt(curl, CURLOPT_POSTFIELDS, g_Data);
  curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, (long)sizeof(g_Data));

  libtest_debug_config.nohex = 1;
  libtest_debug_config.tracetime = 1;
  test_setopt(curl, CURLOPT_DEBUGDATA, &libtest_debug_config);
  test_setopt(curl, CURLOPT_DEBUGFUNCTION, libtest_debug_cb);
  test_setopt(curl, CURLOPT_VERBOSE, 1L);

  /* Remove "Expect: 100-continue" */
  pHeaderList = curl_slist_append(pHeaderList, "Expect:");

  curl_easy_setopt(curl, CURLOPT_HTTPHEADER, pHeaderList);

  code = curl_easy_perform(curl);

  if(code == CURLE_OK) {
    curl_off_t uploadSize;
    curl_easy_getinfo(curl, CURLINFO_SIZE_UPLOAD_T, &uploadSize);

    printf("uploadSize = %ld\n", (long)uploadSize);

    if((size_t) uploadSize == sizeof(g_Data)) {
      printf("!!!!!!!!!! PASS\n");
    }
    else {
      printf("sent %d, libcurl says %d\n",
             (int)sizeof(g_Data), (int)uploadSize);
    }
  }
  else {
    printf("curl_easy_perform() failed. e = %d\n", code);
  }
  test_cleanup:
  curl_slist_free_all(pHeaderList);
  curl_easy_cleanup(curl);
  curl_global_cleanup();

  return 0;
}
Changes to jni/curl/tests/libtest/lib1525.c.
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42

#include "test.h"

#include "memdebug.h"

static char data [] = "Hello Cloud!\n";

static size_t read_callback(void *ptr, size_t size, size_t nmemb, void *stream)
{
  size_t  amount = nmemb * size; /* Total bytes curl wants */
  if(amount < strlen(data)) {
    return strlen(data);
  }
  (void)stream;
  memcpy(ptr, data, strlen(data));







|







28
29
30
31
32
33
34
35
36
37
38
39
40
41
42

#include "test.h"

#include "memdebug.h"

static char data [] = "Hello Cloud!\n";

static size_t read_callback(char *ptr, size_t size, size_t nmemb, void *stream)
{
  size_t  amount = nmemb * size; /* Total bytes curl wants */
  if(amount < strlen(data)) {
    return strlen(data);
  }
  (void)stream;
  memcpy(ptr, data, strlen(data));
Changes to jni/curl/tests/libtest/lib1526.c.
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41

#include "test.h"

#include "memdebug.h"

static char data [] = "Hello Cloud!\n";

static size_t read_callback(void *ptr, size_t size, size_t nmemb, void *stream)
{
  size_t  amount = nmemb * size; /* Total bytes curl wants */
  if(amount < strlen(data)) {
    return strlen(data);
  }
  (void)stream;
  memcpy(ptr, data, strlen(data));







|







27
28
29
30
31
32
33
34
35
36
37
38
39
40
41

#include "test.h"

#include "memdebug.h"

static char data [] = "Hello Cloud!\n";

static size_t read_callback(char *ptr, size_t size, size_t nmemb, void *stream)
{
  size_t  amount = nmemb * size; /* Total bytes curl wants */
  if(amount < strlen(data)) {
    return strlen(data);
  }
  (void)stream;
  memcpy(ptr, data, strlen(data));
Changes to jni/curl/tests/libtest/lib1527.c.
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41

#include "test.h"

#include "memdebug.h"

static char data [] = "Hello Cloud!\n";

static size_t read_callback(void *ptr, size_t size, size_t nmemb, void *stream)
{
  size_t  amount = nmemb * size; /* Total bytes curl wants */
  if(amount < strlen(data)) {
    return strlen(data);
  }
  (void)stream;
  memcpy(ptr, data, strlen(data));







|







27
28
29
30
31
32
33
34
35
36
37
38
39
40
41

#include "test.h"

#include "memdebug.h"

static char data [] = "Hello Cloud!\n";

static size_t read_callback(char *ptr, size_t size, size_t nmemb, void *stream)
{
  size_t  amount = nmemb * size; /* Total bytes curl wants */
  if(amount < strlen(data)) {
    return strlen(data);
  }
  (void)stream;
  memcpy(ptr, data, strlen(data));
Changes to jni/curl/tests/libtest/lib1533.c.
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
  data->easy_handle = curl;
  data->response_received = 0;
  data->paused = 0;
  data->remaining_bytes = 3;
}


static size_t read_callback(void *ptr, size_t size, size_t nitems,
                            void *userdata)
{
  struct cb_data *data = (struct cb_data *)userdata;

  /* wait until the server has sent all response headers */
  if(data->response_received) {
    size_t totalsize = nitems * size;







|







44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
  data->easy_handle = curl;
  data->response_received = 0;
  data->paused = 0;
  data->remaining_bytes = 3;
}


static size_t read_callback(char *ptr, size_t size, size_t nitems,
                            void *userdata)
{
  struct cb_data *data = (struct cb_data *)userdata;

  /* wait until the server has sent all response headers */
  if(data->response_received) {
    size_t totalsize = nitems * size;
Changes to jni/curl/tests/libtest/lib1564.c.
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
    goto test_cleanup;
  }

  abort_on_test_timeout();

  /* try a single wakeup */

  multi_wakeup(multi);

  time_before_wait = tutil_tvnow();
  multi_poll(multi, NULL, 0, 1000, &numfds);
  time_after_wait = tutil_tvnow();

  if(tutil_tvdiff(time_after_wait, time_before_wait) > 500) {
    fprintf(stderr, "%s:%d curl_multi_poll returned too late\n",







|







57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
    goto test_cleanup;
  }

  abort_on_test_timeout();

  /* try a single wakeup */

  res_multi_wakeup(multi);

  time_before_wait = tutil_tvnow();
  multi_poll(multi, NULL, 0, 1000, &numfds);
  time_after_wait = tutil_tvnow();

  if(tutil_tvdiff(time_after_wait, time_before_wait) > 500) {
    fprintf(stderr, "%s:%d curl_multi_poll returned too late\n",
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
  }

  abort_on_test_timeout();

  /* try lots of wakeup */

  for(i = 0; i < WAKEUP_NUM; ++i)
    multi_wakeup(multi);

  time_before_wait = tutil_tvnow();
  multi_poll(multi, NULL, 0, 1000, &numfds);
  time_after_wait = tutil_tvnow();

  if(tutil_tvdiff(time_after_wait, time_before_wait) > 500) {
    fprintf(stderr, "%s:%d curl_multi_poll returned too late\n",







|







90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
  }

  abort_on_test_timeout();

  /* try lots of wakeup */

  for(i = 0; i < WAKEUP_NUM; ++i)
    res_multi_wakeup(multi);

  time_before_wait = tutil_tvnow();
  multi_poll(multi, NULL, 0, 1000, &numfds);
  time_after_wait = tutil_tvnow();

  if(tutil_tvdiff(time_after_wait, time_before_wait) > 500) {
    fprintf(stderr, "%s:%d curl_multi_poll returned too late\n",
Changes to jni/curl/tests/libtest/lib1565.c.
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80

    pending_handles[pending_num] = easy;
    pending_num++;
    easy = NULL;

    pthread_mutex_unlock(&lock);

    multi_wakeup(multi);
  }

test_cleanup:

  curl_easy_cleanup(easy);

  pthread_mutex_lock(&lock);







|







66
67
68
69
70
71
72
73
74
75
76
77
78
79
80

    pending_handles[pending_num] = easy;
    pending_num++;
    easy = NULL;

    pthread_mutex_unlock(&lock);

    res_multi_wakeup(multi);
  }

test_cleanup:

  curl_easy_cleanup(easy);

  pthread_mutex_lock(&lock);
Added jni/curl/tests/libtest/lib1568.c.






































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 2021, 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 https://curl.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 "test.h"

#include "testtrace.h"
#include "memdebug.h"

int test(char *URL)
{
  CURLcode ret;
  CURL *hnd;
  curl_global_init(CURL_GLOBAL_ALL);

  hnd = curl_easy_init();
  curl_easy_setopt(hnd, CURLOPT_URL, URL);
  curl_easy_setopt(hnd, CURLOPT_VERBOSE, 1L);
  curl_easy_setopt(hnd, CURLOPT_HEADER, 1L);
  curl_easy_setopt(hnd, CURLOPT_USERPWD, "testuser:testpass");
  curl_easy_setopt(hnd, CURLOPT_USERAGENT, "lib1568");
  curl_easy_setopt(hnd, CURLOPT_HTTPAUTH, (long)CURLAUTH_DIGEST);
  curl_easy_setopt(hnd, CURLOPT_MAXREDIRS, 50L);
  curl_easy_setopt(hnd, CURLOPT_PORT, (long)atoi(libtest_arg2));

  ret = curl_easy_perform(hnd);

  curl_easy_cleanup(hnd);
  hnd = NULL;

  curl_global_cleanup();
  return (int)ret;
}

Changes to jni/curl/tests/libtest/lib1591.c.
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
#include "test.h"
#include <stdio.h>
#include "memdebug.h"

static char data [] = "Hello Cloud!\r\n";
static size_t consumed = 0;

static size_t read_callback(void *ptr, size_t size, size_t nmemb, void *stream)
{
  size_t  amount = nmemb * size; /* Total bytes curl wants */

  if(consumed == strlen(data)) {
    return 0;
  }








|







28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
#include "test.h"
#include <stdio.h>
#include "memdebug.h"

static char data [] = "Hello Cloud!\r\n";
static size_t consumed = 0;

static size_t read_callback(char *ptr, size_t size, size_t nmemb, void *stream)
{
  size_t  amount = nmemb * size; /* Total bytes curl wants */

  if(consumed == strlen(data)) {
    return 0;
  }

Changes to jni/curl/tests/libtest/lib1905.c.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 2019 - 2020, 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 https://curl.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







|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 2019 - 2021, 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 https://curl.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
26
27
28
29
30
31
32

33


34
35

36

37
38
39
40
41
42
43
#include "memdebug.h"

int test(char *URL)
{
  CURLSH *sh = NULL;
  CURL *ch = NULL;
  int unfinished;




  CURLM *cm = curl_multi_init();
  if(!cm)

    return 1;

  sh = curl_share_init();
  if(!sh)
    goto cleanup;

  curl_share_setopt(sh, CURLSHOPT_SHARE, CURL_LOCK_DATA_COOKIE);
  curl_share_setopt(sh, CURLSHOPT_SHARE, CURL_LOCK_DATA_COOKIE);








>

>
>
|
|
>

>







26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
#include "memdebug.h"

int test(char *URL)
{
  CURLSH *sh = NULL;
  CURL *ch = NULL;
  int unfinished;
  CURLM *cm;

  curl_global_init(CURL_GLOBAL_ALL);

  cm = curl_multi_init();
  if(!cm) {
    curl_global_cleanup();
    return 1;
  }
  sh = curl_share_init();
  if(!sh)
    goto cleanup;

  curl_share_setopt(sh, CURLSHOPT_SHARE, CURL_LOCK_DATA_COOKIE);
  curl_share_setopt(sh, CURLSHOPT_SHARE, CURL_LOCK_DATA_COOKIE);

Changes to jni/curl/tests/libtest/lib1911.c.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2020, 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 https://curl.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







|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2021, 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 https://curl.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
36
37
38
39
40
41
42
43

44

45
46
47
48
49
50
51
  const struct curl_easyoption *o;
  CURL *easy;
  int error = 0;
  (void)URL;

  curl_global_init(CURL_GLOBAL_ALL);
  easy = curl_easy_init();
  if(!easy)

    return 1;


  /* make it a zero terminated C string with just As */
  memset(buffer, 'A', MAX_INPUT_LENGTH + 1);
  buffer[MAX_INPUT_LENGTH + 1] = 0;

  printf("string length: %d\n", (int)strlen(buffer));








|
>

>







36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
  const struct curl_easyoption *o;
  CURL *easy;
  int error = 0;
  (void)URL;

  curl_global_init(CURL_GLOBAL_ALL);
  easy = curl_easy_init();
  if(!easy) {
    curl_global_cleanup();
    return 1;
  }

  /* make it a zero terminated C string with just As */
  memset(buffer, 'A', MAX_INPUT_LENGTH + 1);
  buffer[MAX_INPUT_LENGTH + 1] = 0;

  printf("string length: %d\n", (int)strlen(buffer));

Added jni/curl/tests/libtest/lib1916.c.












































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 2020, 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 https://curl.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 "test.h"

#include "warnless.h"
#include "memdebug.h"

int test(char *URL)
{
  CURL *curl;
  CURLcode res = CURLE_OK;

  if(curl_global_init(CURL_GLOBAL_ALL) != CURLE_OK) {
    fprintf(stderr, "curl_global_init() failed\n");
    return TEST_ERR_MAJOR_BAD;
  }

  curl = curl_easy_init();
  if(curl) {
    curl_easy_setopt(curl, CURLOPT_URL, URL);
#ifdef LIB1917
    /* without any postfields set! */
    curl_easy_setopt(curl, CURLOPT_POST, 1L);
#else
    curl_easy_setopt(curl, CURLOPT_POSTFIELDS, "");
#endif
    res = curl_easy_perform(curl);
    if(res) {
      printf("res: %d\n", res);
    }
    curl_easy_cleanup(curl);
  }
  curl_global_cleanup();
  return (int)res;
}
Added jni/curl/tests/libtest/lib1918.c.














































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2021, 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 https://curl.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 "test.h"

#include "testutil.h"
#include "warnless.h"
#include "memdebug.h"

int test(char *URL)
{
  const struct curl_easyoption *o;
  int error = 0;
  (void)URL;

  curl_global_init(CURL_GLOBAL_ALL);

  for(o = curl_easy_option_next(NULL);
      o;
      o = curl_easy_option_next(o)) {
    const struct curl_easyoption *ename =
      curl_easy_option_by_name(o->name);
    const struct curl_easyoption *eid =
      curl_easy_option_by_id(o->id);

    if(ename->id != o->id) {
      printf("name lookup id %d doesn't match %d\n",
             ename->id, o->id);
    }
    else if(eid->id != o->id) {
      printf("ID lookup %d doesn't match %d\n",
             ename->id, o->id);
    }
  }
  curl_global_cleanup();
  return error;
}
Added jni/curl/tests/libtest/lib1933.c.
























































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2021, 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 https://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 "test.h"

#include "memdebug.h"

int test(char *URL)
{
  CURL *curl;
  CURLcode res = TEST_ERR_MAJOR_BAD;
  struct curl_slist *list = NULL;

  if(curl_global_init(CURL_GLOBAL_ALL) != CURLE_OK) {
    fprintf(stderr, "curl_global_init() failed\n");
    return TEST_ERR_MAJOR_BAD;
  }

  curl = curl_easy_init();
  if(!curl) {
    fprintf(stderr, "curl_easy_init() failed\n");
    curl_global_cleanup();
    return TEST_ERR_MAJOR_BAD;
  }

  test_setopt(curl, CURLOPT_VERBOSE, 1L);
  test_setopt(curl, CURLOPT_AWS_SIGV4, "xxx");
  test_setopt(curl, CURLOPT_HEADER, 0L);
  test_setopt(curl, CURLOPT_URL, URL);
  list = curl_slist_append(list, "Content-Type: application/json");
  test_setopt(curl, CURLOPT_HTTPHEADER, list);

  res = curl_easy_perform(curl);

test_cleanup:

  curl_slist_free_all(list);
  curl_easy_cleanup(curl);
  curl_global_cleanup();

  return res;
}
Added jni/curl/tests/libtest/lib1934.c.


























































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2021, 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 https://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 "test.h"

#include "memdebug.h"

int test(char *URL)
{
  CURL *curl;
  CURLcode res = TEST_ERR_MAJOR_BAD;
  struct curl_slist *list = NULL;

  if(curl_global_init(CURL_GLOBAL_ALL) != CURLE_OK) {
    fprintf(stderr, "curl_global_init() failed\n");
    return TEST_ERR_MAJOR_BAD;
  }

  curl = curl_easy_init();
  if(!curl) {
    fprintf(stderr, "curl_easy_init() failed\n");
    curl_global_cleanup();
    return TEST_ERR_MAJOR_BAD;
  }

  test_setopt(curl, CURLOPT_VERBOSE, 1L);
  test_setopt(curl, CURLOPT_AWS_SIGV4, "xxx:yyy");
  test_setopt(curl, CURLOPT_USERPWD, "xxx:yyy");
  test_setopt(curl, CURLOPT_HEADER, 0L);
  test_setopt(curl, CURLOPT_URL, URL);
  list = curl_slist_append(list, "Content-Type: application/json");
  test_setopt(curl, CURLOPT_HTTPHEADER, list);

  res = curl_easy_perform(curl);

test_cleanup:

  curl_slist_free_all(list);
  curl_easy_cleanup(curl);
  curl_global_cleanup();

  return res;
}
Added jni/curl/tests/libtest/lib1935.c.


























































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2021, 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 https://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 "test.h"

#include "memdebug.h"

int test(char *URL)
{
  CURL *curl;
  CURLcode res = TEST_ERR_MAJOR_BAD;
  struct curl_slist *list = NULL;

  if(curl_global_init(CURL_GLOBAL_ALL) != CURLE_OK) {
    fprintf(stderr, "curl_global_init() failed\n");
    return TEST_ERR_MAJOR_BAD;
  }

  curl = curl_easy_init();
  if(!curl) {
    fprintf(stderr, "curl_easy_init() failed\n");
    curl_global_cleanup();
    return TEST_ERR_MAJOR_BAD;
  }

  test_setopt(curl, CURLOPT_VERBOSE, 1L);
  test_setopt(curl, CURLOPT_AWS_SIGV4, "xxx:yyy:rrr");
  test_setopt(curl, CURLOPT_USERPWD, "xxx:yyy");
  test_setopt(curl, CURLOPT_HEADER, 0L);
  test_setopt(curl, CURLOPT_URL, URL);
  list = curl_slist_append(list, "Content-Type: application/json");
  test_setopt(curl, CURLOPT_HTTPHEADER, list);

  res = curl_easy_perform(curl);

test_cleanup:

  curl_slist_free_all(list);
  curl_easy_cleanup(curl);
  curl_global_cleanup();

  return res;
}
Added jni/curl/tests/libtest/lib1936.c.


























































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2021, 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 https://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 "test.h"

#include "memdebug.h"

int test(char *URL)
{
  CURL *curl;
  CURLcode res = TEST_ERR_MAJOR_BAD;
  struct curl_slist *list = NULL;

  if(curl_global_init(CURL_GLOBAL_ALL) != CURLE_OK) {
    fprintf(stderr, "curl_global_init() failed\n");
    return TEST_ERR_MAJOR_BAD;
  }

  curl = curl_easy_init();
  if(!curl) {
    fprintf(stderr, "curl_easy_init() failed\n");
    curl_global_cleanup();
    return TEST_ERR_MAJOR_BAD;
  }

  test_setopt(curl, CURLOPT_VERBOSE, 1L);
  test_setopt(curl, CURLOPT_AWS_SIGV4, "xxx:yyy:rrr:sss");
  test_setopt(curl, CURLOPT_USERPWD, "xxx:yyy");
  test_setopt(curl, CURLOPT_HEADER, 0L);
  test_setopt(curl, CURLOPT_URL, URL);
  list = curl_slist_append(list, "Content-Type: application/json");
  test_setopt(curl, CURLOPT_HTTPHEADER, list);

  res = curl_easy_perform(curl);

test_cleanup:

  curl_slist_free_all(list);
  curl_easy_cleanup(curl);
  curl_global_cleanup();

  return res;
}
Changes to jni/curl/tests/libtest/lib508.c.
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
static char data[]="this is what we post to the silly web server\n";

struct WriteThis {
  char *readptr;
  size_t sizeleft;
};

static size_t read_callback(void *ptr, size_t size, size_t nmemb, void *userp)
{
  struct WriteThis *pooh = (struct WriteThis *)userp;

  if(size*nmemb < 1)
    return 0;

  if(pooh->sizeleft) {
    *(char *)ptr = pooh->readptr[0]; /* copy one single byte */
    pooh->readptr++;                 /* advance pointer */
    pooh->sizeleft--;                /* less data left */
    return 1;                        /* we return 1 byte at a time! */
  }

  return 0;                         /* no more data left to deliver */
}







|







|







26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
static char data[]="this is what we post to the silly web server\n";

struct WriteThis {
  char *readptr;
  size_t sizeleft;
};

static size_t read_callback(char *ptr, size_t size, size_t nmemb, void *userp)
{
  struct WriteThis *pooh = (struct WriteThis *)userp;

  if(size*nmemb < 1)
    return 0;

  if(pooh->sizeleft) {
    *ptr = pooh->readptr[0]; /* copy one single byte */
    pooh->readptr++;                 /* advance pointer */
    pooh->sizeleft--;                /* less data left */
    return 1;                        /* we return 1 byte at a time! */
  }

  return 0;                         /* no more data left to deliver */
}
Changes to jni/curl/tests/libtest/lib510.c.
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
};


struct WriteThis {
  int counter;
};

static size_t read_callback(void *ptr, size_t size, size_t nmemb, void *userp)
{
  struct WriteThis *pooh = (struct WriteThis *)userp;
  const char *data;

  if(size*nmemb < 1)
    return 0;








|







32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
};


struct WriteThis {
  int counter;
};

static size_t read_callback(char *ptr, size_t size, size_t nmemb, void *userp)
{
  struct WriteThis *pooh = (struct WriteThis *)userp;
  const char *data;

  if(size*nmemb < 1)
    return 0;

Changes to jni/curl/tests/libtest/lib513.c.
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
 * KIND, either express or implied.
 *
 ***************************************************************************/
#include "test.h"

#include "memdebug.h"

static size_t read_callback(void *ptr, size_t size, size_t nmemb, void *userp)
{
  (void)ptr;
  (void)size;
  (void)nmemb;
  (void)userp;
  return CURL_READFUNC_ABORT;
}







|







19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
 * KIND, either express or implied.
 *
 ***************************************************************************/
#include "test.h"

#include "memdebug.h"

static size_t read_callback(char *ptr, size_t size, size_t nmemb, void *userp)
{
  (void)ptr;
  (void)size;
  (void)nmemb;
  (void)userp;
  return CURL_READFUNC_ABORT;
}
Changes to jni/curl/tests/libtest/lib543.c.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2020, 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 https://curl.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







|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2021, 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 https://curl.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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68

69
70
71
72
  CURLcode res = CURLE_OK;
  (void)URL;

  global_init(CURL_GLOBAL_ALL);
  easy = curl_easy_init();
  if(!easy) {
    fprintf(stderr, "curl_easy_init() failed\n");
    return TEST_ERR_MAJOR_BAD;
  }

  asize = (int)sizeof(a);

  s = curl_easy_escape(easy, (const char *)a, asize);

  if(s) {
    printf("%s\n", s);
    curl_free(s);
  }

  s = curl_easy_escape(easy, "", 0);
  if(s) {
    printf("IN: '' OUT: '%s'\n", s);
    curl_free(s);
  }
  s = curl_easy_escape(easy, " 123", 3);
  if(s) {
    printf("IN: ' 12' OUT: '%s'\n", s);
    curl_free(s);
  }

  curl_easy_cleanup(easy);

  curl_global_cleanup();

  return 0;
}







|

|
|

|

|
|
|
|

|
|
|
|
|
|
|
|
|
|

|
>


|

38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
  CURLcode res = CURLE_OK;
  (void)URL;

  global_init(CURL_GLOBAL_ALL);
  easy = curl_easy_init();
  if(!easy) {
    fprintf(stderr, "curl_easy_init() failed\n");
    res = TEST_ERR_MAJOR_BAD;
  }
  else {
    asize = (int)sizeof(a);

    s = curl_easy_escape(easy, (const char *)a, asize);

    if(s) {
      printf("%s\n", s);
      curl_free(s);
    }

    s = curl_easy_escape(easy, "", 0);
    if(s) {
      printf("IN: '' OUT: '%s'\n", s);
      curl_free(s);
    }
    s = curl_easy_escape(easy, " 123", 3);
    if(s) {
      printf("IN: ' 12' OUT: '%s'\n", s);
      curl_free(s);
    }

    curl_easy_cleanup(easy);
  }
  curl_global_cleanup();

  return (int)res;
}
Changes to jni/curl/tests/libtest/lib547.c.
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
                     "\x6c\x75\x72\x62\x20\x77\x65\x20\x77\x61\x6e\x74\x20" \
                     "\x74\x6f\x20\x75\x70\x6c\x6f\x61\x64\x0a"
#else
#  define UPLOADTHIS "this is the blurb we want to upload\n"
#endif

#ifndef LIB548
static size_t readcallback(void  *ptr,
                           size_t size,
                           size_t nmemb,
                           void *clientp)
{
  int *counter = (int *)clientp;

  if(*counter) {







|







34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
                     "\x6c\x75\x72\x62\x20\x77\x65\x20\x77\x61\x6e\x74\x20" \
                     "\x74\x6f\x20\x75\x70\x6c\x6f\x61\x64\x0a"
#else
#  define UPLOADTHIS "this is the blurb we want to upload\n"
#endif

#ifndef LIB548
static size_t readcallback(char  *ptr,
                           size_t size,
                           size_t nmemb,
                           void *clientp)
{
  int *counter = (int *)clientp;

  if(*counter) {
Changes to jni/curl/tests/libtest/lib552.c.
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
}


static size_t current_offset = 0;
static char databuf[70000]; /* MUST be more than 64k OR
                               MAX_INITIAL_POST_SIZE */

static size_t read_callback(void *ptr, size_t size, size_t nmemb, void *stream)
{
  size_t  amount = nmemb * size; /* Total bytes curl wants */
  size_t  available = sizeof(databuf) - current_offset; /* What we have to
                                                           give */
  size_t  given = amount < available ? amount : available; /* What is given */
  (void)stream;
  memcpy(ptr, databuf + current_offset, given);







|







123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
}


static size_t current_offset = 0;
static char databuf[70000]; /* MUST be more than 64k OR
                               MAX_INITIAL_POST_SIZE */

static size_t read_callback(char *ptr, size_t size, size_t nmemb, void *stream)
{
  size_t  amount = nmemb * size; /* Total bytes curl wants */
  size_t  available = sizeof(databuf) - current_offset; /* What we have to
                                                           give */
  size_t  given = amount < available ? amount : available; /* What is given */
  (void)stream;
  memcpy(ptr, databuf + current_offset, given);
Changes to jni/curl/tests/libtest/lib553.c.
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40

#include "test.h"

#include "memdebug.h"

#define POSTLEN 40960

static size_t myreadfunc(void *ptr, size_t size, size_t nmemb, void *stream)
{
  static size_t total = POSTLEN;
  static char buf[1024];
  (void)stream;

  memset(buf, 'A', sizeof(buf));








|







26
27
28
29
30
31
32
33
34
35
36
37
38
39
40

#include "test.h"

#include "memdebug.h"

#define POSTLEN 40960

static size_t myreadfunc(char *ptr, size_t size, size_t nmemb, void *stream)
{
  static size_t total = POSTLEN;
  static char buf[1024];
  (void)stream;

  memset(buf, 'A', sizeof(buf));

Changes to jni/curl/tests/libtest/lib554.c.
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
#endif

struct WriteThis {
  char *readptr;
  size_t sizeleft;
};

static size_t read_callback(void *ptr, size_t size, size_t nmemb, void *userp)
{
#ifdef LIB587
  (void)ptr;
  (void)size;
  (void)nmemb;
  (void)userp;
  return CURL_READFUNC_ABORT;
#else

  struct WriteThis *pooh = (struct WriteThis *)userp;

  if(size*nmemb < 1)
    return 0;

  if(pooh->sizeleft) {
    *(char *)ptr = pooh->readptr[0]; /* copy one single byte */
    pooh->readptr++;                 /* advance pointer */
    pooh->sizeleft--;                /* less data left */
    return 1;                        /* we return 1 byte at a time! */
  }

  return 0;                         /* no more data left to deliver */
#endif







|















|







34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
#endif

struct WriteThis {
  char *readptr;
  size_t sizeleft;
};

static size_t read_callback(char *ptr, size_t size, size_t nmemb, void *userp)
{
#ifdef LIB587
  (void)ptr;
  (void)size;
  (void)nmemb;
  (void)userp;
  return CURL_READFUNC_ABORT;
#else

  struct WriteThis *pooh = (struct WriteThis *)userp;

  if(size*nmemb < 1)
    return 0;

  if(pooh->sizeleft) {
    *ptr = pooh->readptr[0]; /* copy one single byte */
    pooh->readptr++;                 /* advance pointer */
    pooh->sizeleft--;                /* less data left */
    return 1;                        /* we return 1 byte at a time! */
  }

  return 0;                         /* no more data left to deliver */
#endif
Changes to jni/curl/tests/libtest/lib555.c.
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
  "\x74\x68\x69\x73\x20\x69\x73\x20\x74\x68\x65\x20\x62\x6c\x75\x72"
  "\x62\x20\x77\x65\x20\x77\x61\x6e\x74\x20\x74\x6f\x20\x75\x70\x6c"
  "\x6f\x61\x64\x0a";
#else
  "this is the blurb we want to upload\n";
#endif

static size_t readcallback(void  *ptr,
                           size_t size,
                           size_t nmemb,
                           void *clientp)
{
  int *counter = (int *)clientp;

  if(*counter) {







|







41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
  "\x74\x68\x69\x73\x20\x69\x73\x20\x74\x68\x65\x20\x62\x6c\x75\x72"
  "\x62\x20\x77\x65\x20\x77\x61\x6e\x74\x20\x74\x6f\x20\x75\x70\x6c"
  "\x6f\x61\x64\x0a";
#else
  "this is the blurb we want to upload\n";
#endif

static size_t readcallback(char  *ptr,
                           size_t size,
                           size_t nmemb,
                           void *clientp)
{
  int *counter = (int *)clientp;

  if(*counter) {
Changes to jni/curl/tests/libtest/lib579.c.
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
    }
    prev_ulnow = (int) ulnow;
    prev_ultotal = (int) ultotal;
  }
  return 0;
}

static size_t read_callback(void *ptr, size_t size, size_t nmemb, void *userp)
{
  struct WriteThis *pooh = (struct WriteThis *)userp;
  const char *data;

  if(size*nmemb < 1)
    return 0;








|







60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
    }
    prev_ulnow = (int) ulnow;
    prev_ultotal = (int) ultotal;
  }
  return 0;
}

static size_t read_callback(char *ptr, size_t size, size_t nmemb, void *userp)
{
  struct WriteThis *pooh = (struct WriteThis *)userp;
  const char *data;

  if(size*nmemb < 1)
    return 0;

Changes to jni/curl/tests/libtest/lib589.c.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2020, 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 https://curl.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







|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2021, 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 https://curl.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
38
39
40
41
42
43
44
45
46
47
48














49
50
51
52
53
54
55
56
57
58
59
    fprintf(stderr, "curl_easy_init() failed\n");
    curl_global_cleanup();
    return TEST_ERR_MAJOR_BAD;
  }

  /* First set the URL that is about to receive our POST. */
  test_setopt(curl, CURLOPT_URL, URL);
  test_setopt(curl, CURLOPT_MIMEPOST, NULL);
  test_setopt(curl, CURLOPT_VERBOSE, 1L); /* show verbose for debug */
  test_setopt(curl, CURLOPT_HEADER, 1L); /* include header */















  /* Now, we should be making a zero byte POST request */
  res = curl_easy_perform(curl);

test_cleanup:

  /* always cleanup */
  curl_easy_cleanup(curl);
  curl_global_cleanup();

  return (int)res;
}







<



>
>
>
>
>
>
>
>
>
>
>
>
>
>











38
39
40
41
42
43
44

45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
    fprintf(stderr, "curl_easy_init() failed\n");
    curl_global_cleanup();
    return TEST_ERR_MAJOR_BAD;
  }

  /* First set the URL that is about to receive our POST. */
  test_setopt(curl, CURLOPT_URL, URL);

  test_setopt(curl, CURLOPT_VERBOSE, 1L); /* show verbose for debug */
  test_setopt(curl, CURLOPT_HEADER, 1L); /* include header */

#ifdef LIB584
  {
    curl_mime *mime = curl_mime_init(curl);
    curl_mimepart *part = curl_mime_addpart(mime);
    curl_mime_name(part, "fake");
    curl_mime_data(part, "party", 5);
    test_setopt(curl, CURLOPT_MIMEPOST, mime);
    res = curl_easy_perform(curl);
    curl_mime_free(mime);
  }
#endif

  test_setopt(curl, CURLOPT_MIMEPOST, NULL);

  /* Now, we should be making a zero byte POST request */
  res = curl_easy_perform(curl);

test_cleanup:

  /* always cleanup */
  curl_easy_cleanup(curl);
  curl_global_cleanup();

  return (int)res;
}
jni/curl/tests/libtest/mk-lib1521.pl became executable.
jni/curl/tests/manpage-scan.pl became executable.
jni/curl/tests/mem-include-scan.pl became executable.
jni/curl/tests/nroff-scan.pl became executable.
Changes to jni/curl/tests/runtests.1.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH runtests.pl 1 "November 04, 2020" "Curl 7.74.0" "runtests"

.SH NAME
runtests.pl \- run one or more test cases
.SH SYNOPSIS
.B runtests.pl [options] [tests]
.SH DESCRIPTION
\fIruntests.pl\fP runs one, several or all the existing test cases in curl's







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH runtests.pl 1 "November 04, 2020" "Curl 7.75.0" "runtests"

.SH NAME
runtests.pl \- run one or more test cases
.SH SYNOPSIS
.B runtests.pl [options] [tests]
.SH DESCRIPTION
\fIruntests.pl\fP runs one, several or all the existing test cases in curl's
Changes to jni/curl/tests/runtests.pl.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#!/usr/bin/env perl
#***************************************************************************
#                                  _   _ ____  _
#  Project                     ___| | | |  _ \| |
#                             / __| | | | |_) | |
#                            | (__| |_| |  _ <| |___
#                             \___|\___/|_| \_\_____|
#
# Copyright (C) 1998 - 2020, 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 https://curl.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








|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#!/usr/bin/env perl
#***************************************************************************
#                                  _   _ ____  _
#  Project                     ___| | | |  _ \| |
#                             / __| | | | |_) | |
#                            | (__| |_| |  _ <| |___
#                             \___|\___/|_| \_\_____|
#
# Copyright (C) 1998 - 2021, 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 https://curl.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
147
148
149
150
151
152
153

154
155
156
157
158
159
160
my $IMAPPORT=$noport;    # IMAP
my $IMAP6PORT=$noport;   # IMAP IPv6 server port
my $SMTPPORT=$noport;    # SMTP
my $SMTP6PORT=$noport;   # SMTP IPv6 server port
my $RTSPPORT=$noport;    # RTSP
my $RTSP6PORT=$noport;   # RTSP IPv6 server port
my $GOPHERPORT=$noport;  # Gopher

my $GOPHER6PORT=$noport; # Gopher IPv6 server port
my $HTTPTLSPORT=$noport; # HTTP TLS (non-stunnel) server port
my $HTTPTLS6PORT=$noport; # HTTP TLS (non-stunnel) IPv6 server port
my $HTTPPROXYPORT=$noport; # HTTP proxy port, when using CONNECT
my $HTTP2PORT=$noport;   # HTTP/2 server port
my $DICTPORT=$noport;    # DICT server port
my $SMBPORT=$noport;     # SMB server port







>







147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
my $IMAPPORT=$noport;    # IMAP
my $IMAP6PORT=$noport;   # IMAP IPv6 server port
my $SMTPPORT=$noport;    # SMTP
my $SMTP6PORT=$noport;   # SMTP IPv6 server port
my $RTSPPORT=$noport;    # RTSP
my $RTSP6PORT=$noport;   # RTSP IPv6 server port
my $GOPHERPORT=$noport;  # Gopher
my $GOPHERSPORT=$noport; # Gophers
my $GOPHER6PORT=$noport; # Gopher IPv6 server port
my $HTTPTLSPORT=$noport; # HTTP TLS (non-stunnel) server port
my $HTTPTLS6PORT=$noport; # HTTP TLS (non-stunnel) IPv6 server port
my $HTTPPROXYPORT=$noport; # HTTP proxy port, when using CONNECT
my $HTTP2PORT=$noport;   # HTTP/2 server port
my $DICTPORT=$noport;    # DICT server port
my $SMBPORT=$noport;     # SMB server port
253
254
255
256
257
258
259
260
261
262
263
264

265
266
267
268
269
270
271
my $has_httpsproxy; # set if libcurl is built with HTTPS-proxy support
my $has_crypto;     # set if libcurl is built with cryptographic support
my $has_cares;      # set if built with c-ares
my $has_threadedres;# set if built with threaded resolver
my $has_psl;        # set if libcurl is built with PSL support
my $has_altsvc;     # set if libcurl is built with alt-svc support
my $has_hsts;       # set if libcurl is built with HSTS support
my $has_ldpreload;  # set if curl is built for systems supporting LD_PRELOAD
my $has_multissl;   # set if curl is build with MultiSSL support
my $has_manual;     # set if curl is built with built-in manual
my $has_win32;      # set if curl is built for Windows
my $has_mingw;      # set if curl is built with MinGW (as opposed to MinGW-w64)


# this version is decided by the particular nghttp2 library that is being used
my $h2cver = "h2c";

my $has_openssl;    # built with a lib using an OpenSSL-like API
my $has_gnutls;     # built with GnuTLS
my $has_nss;        # built with NSS







|
|
|
|
|
>







254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
my $has_httpsproxy; # set if libcurl is built with HTTPS-proxy support
my $has_crypto;     # set if libcurl is built with cryptographic support
my $has_cares;      # set if built with c-ares
my $has_threadedres;# set if built with threaded resolver
my $has_psl;        # set if libcurl is built with PSL support
my $has_altsvc;     # set if libcurl is built with alt-svc support
my $has_hsts;       # set if libcurl is built with HSTS support
my $has_ldpreload;  # set if built for systems supporting LD_PRELOAD
my $has_multissl;   # set if build with MultiSSL support
my $has_manual;     # set if built with built-in manual
my $has_win32;      # set if built for Windows
my $has_mingw;      # set if built with MinGW (as opposed to MinGW-w64)
my $has_hyper = 0;  # set if built with Hyper

# this version is decided by the particular nghttp2 library that is being used
my $h2cver = "h2c";

my $has_openssl;    # built with a lib using an OpenSSL-like API
my $has_gnutls;     # built with GnuTLS
my $has_nss;        # built with NSS
375
376
377
378
379
380
381

382
383
384
385
386
387
388
    }
}

# enable memory debugging if curl is compiled with it
$ENV{'CURL_MEMDEBUG'} = $memdump;
$ENV{'CURL_ENTROPY'}="12345678";
$ENV{'CURL_FORCETIME'}=1; # for debug NTLM magic

$ENV{'HOME'}=$pwd;
$ENV{'COLUMNS'}=79; # screen width!

sub catch_zap {
    my $signame = shift;
    logmsg "runtests.pl received SIG$signame, exiting\n";
    stopservers($verbose);







>







377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
    }
}

# enable memory debugging if curl is compiled with it
$ENV{'CURL_MEMDEBUG'} = $memdump;
$ENV{'CURL_ENTROPY'}="12345678";
$ENV{'CURL_FORCETIME'}=1; # for debug NTLM magic
$ENV{'CURL_GLOBAL_INIT'}=1; # debug curl_global_init/cleanup use
$ENV{'HOME'}=$pwd;
$ENV{'COLUMNS'}=79; # screen width!

sub catch_zap {
    my $signame = shift;
    logmsg "runtests.pl received SIG$signame, exiting\n";
    stopservers($verbose);
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
    # clear lowercase version
    delete $ENV{$proxy} if($ENV{$proxy});
    # clear uppercase version
    delete $ENV{uc($proxy)} if($ENV{uc($proxy)});
}

# make sure we don't get affected by other variables that control our
# behaviour

delete $ENV{'SSL_CERT_DIR'} if($ENV{'SSL_CERT_DIR'});
delete $ENV{'SSL_CERT_PATH'} if($ENV{'SSL_CERT_PATH'});
delete $ENV{'CURL_CA_BUNDLE'} if($ENV{'CURL_CA_BUNDLE'});

#######################################################################
# Load serverpidfile and serverportfile hashes with file names for all
# possible servers.
#
sub init_serverpidfile_hash {
  for my $proto (('ftp', 'http', 'imap', 'pop3', 'smtp', 'http/2')) {
    for my $ssl (('', 's')) {
      for my $ipvnum ((4, 6)) {
        for my $idnum ((1, 2, 3)) {
          my $serv = servername_id("$proto$ssl", $ipvnum, $idnum);
          my $pidf = server_pidfilename("$proto$ssl", $ipvnum, $idnum);
          $serverpidfile{$serv} = $pidf;
          my $portf = server_portfilename("$proto$ssl", $ipvnum, $idnum);
          $serverportfile{$serv} = $portf;
        }
      }
    }
  }
  for my $proto (('tftp', 'sftp', 'socks', 'ssh', 'rtsp', 'gopher', 'httptls',
                  'dict', 'smb', 'smbs', 'telnet', 'mqtt')) {
    for my $ipvnum ((4, 6)) {
      for my $idnum ((1, 2)) {
        my $serv = servername_id($proto, $ipvnum, $idnum);
        my $pidf = server_pidfilename($proto, $ipvnum, $idnum);
        $serverpidfile{$serv} = $pidf;
        my $portf = server_portfilename($proto, $ipvnum, $idnum);







|










|












|







404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
    # clear lowercase version
    delete $ENV{$proxy} if($ENV{$proxy});
    # clear uppercase version
    delete $ENV{uc($proxy)} if($ENV{uc($proxy)});
}

# make sure we don't get affected by other variables that control our
# behavior

delete $ENV{'SSL_CERT_DIR'} if($ENV{'SSL_CERT_DIR'});
delete $ENV{'SSL_CERT_PATH'} if($ENV{'SSL_CERT_PATH'});
delete $ENV{'CURL_CA_BUNDLE'} if($ENV{'CURL_CA_BUNDLE'});

#######################################################################
# Load serverpidfile and serverportfile hashes with file names for all
# possible servers.
#
sub init_serverpidfile_hash {
  for my $proto (('ftp', 'gopher', 'http', 'imap', 'pop3', 'smtp', 'http/2')) {
    for my $ssl (('', 's')) {
      for my $ipvnum ((4, 6)) {
        for my $idnum ((1, 2, 3)) {
          my $serv = servername_id("$proto$ssl", $ipvnum, $idnum);
          my $pidf = server_pidfilename("$proto$ssl", $ipvnum, $idnum);
          $serverpidfile{$serv} = $pidf;
          my $portf = server_portfilename("$proto$ssl", $ipvnum, $idnum);
          $serverportfile{$serv} = $portf;
        }
      }
    }
  }
  for my $proto (('tftp', 'sftp', 'socks', 'ssh', 'rtsp', 'httptls',
                  'dict', 'smb', 'smbs', 'telnet', 'mqtt')) {
    for my $ipvnum ((4, 6)) {
      for my $idnum ((1, 2)) {
        my $serv = servername_id($proto, $ipvnum, $idnum);
        my $pidf = server_pidfilename($proto, $ipvnum, $idnum);
        $serverpidfile{$serv} = $pidf;
        my $portf = server_portfilename($proto, $ipvnum, $idnum);
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
    return ($httppid, $pid2, $port);
}

#######################################################################
# start the https stunnel based server
#
sub runhttpsserver {
    my ($verbose, $ipv6, $proxy, $certfile) = @_;
    my $proto = 'https';
    my $ip = ($ipv6 && ($ipv6 =~ /6$/)) ? "$HOST6IP" : "$HOSTIP";
    my $ipvnum = ($ipv6 && ($ipv6 =~ /6$/)) ? 6 : 4;
    my $idnum = 1;
    my $server;
    my $srvrname;
    my $pidfile;
    my $logfile;
    my $flags = "";








|
<
|
|







1599
1600
1601
1602
1603
1604
1605
1606

1607
1608
1609
1610
1611
1612
1613
1614
1615
    return ($httppid, $pid2, $port);
}

#######################################################################
# start the https stunnel based server
#
sub runhttpsserver {
    my ($verbose, $proto, $proxy, $certfile) = @_;

    my $ip = $HOSTIP;
    my $ipvnum = 4;
    my $idnum = 1;
    my $server;
    my $srvrname;
    my $pidfile;
    my $logfile;
    my $flags = "";

1643
1644
1645
1646
1647
1648
1649



1650
1651
1652
1653
1654
1655
1656
1657

    $flags .= "--verbose " if($debugprotocol);
    $flags .= "--pidfile \"$pidfile\" --logfile \"$logfile\" ";
    $flags .= "--id $idnum " if($idnum > 1);
    $flags .= "--ipv$ipvnum --proto $proto ";
    $flags .= "--certfile \"$certfile\" " if($certfile ne 'stunnel.pem');
    $flags .= "--stunnel \"$stunnel\" --srcdir \"$srcdir\" ";



    if(!$proxy) {
        $flags .= "--connect $HTTPPORT";
    }
    else {
        # for HTTPS-proxy we connect to the HTTP proxy
        $flags .= "--connect $HTTPPROXYPORT";
    }








>
>
>
|







1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662

    $flags .= "--verbose " if($debugprotocol);
    $flags .= "--pidfile \"$pidfile\" --logfile \"$logfile\" ";
    $flags .= "--id $idnum " if($idnum > 1);
    $flags .= "--ipv$ipvnum --proto $proto ";
    $flags .= "--certfile \"$certfile\" " if($certfile ne 'stunnel.pem');
    $flags .= "--stunnel \"$stunnel\" --srcdir \"$srcdir\" ";
    if($proto eq "gophers") {
        $flags .= "--connect $GOPHERPORT";
    }
    elsif(!$proxy) {
        $flags .= "--connect $HTTPPORT";
    }
    else {
        # for HTTPS-proxy we connect to the HTTP proxy
        $flags .= "--connect $HTTPPROXYPORT";
    }

2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257

    logmsg "RUN: $srvrname on PID $pid2 port $wport\n" if($verbose);

    return ($pid2, $sshpid, $wport);
}

#######################################################################
# Start the socks server
#
sub runmqttserver {
    my ($id, $verbose, $ipv6) = @_;
    my $ip=$HOSTIP;
    my $port = $MQTTPORT;
    my $proto = 'mqtt';
    my $ipvnum = 4;







|







2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262

    logmsg "RUN: $srvrname on PID $pid2 port $wport\n" if($verbose);

    return ($pid2, $sshpid, $wport);
}

#######################################################################
# Start the MQTT server
#
sub runmqttserver {
    my ($id, $verbose, $ipv6) = @_;
    my $ip=$HOSTIP;
    my $port = $MQTTPORT;
    my $proto = 'mqtt';
    my $ipvnum = 4;
2758
2759
2760
2761
2762
2763
2764

2765
2766
2767
2768
2769
2770
2771
            logmsg "FAIL: $testnum - $testname - $subject\n";
        }
    }
    return $result;
}

sub setupfeatures {

    $feature{"c-ares"} = $has_cares;
    $feature{"alt-svc"} = $has_altsvc;
    $feature{"HSTS"} = $has_hsts;
    $feature{"brotli"} = $has_brotli;
    $feature{"crypto"} = $has_crypto;
    $feature{"debug"} = $debug_build;
    $feature{"getrlimit"} = $has_getrlimit;







>







2763
2764
2765
2766
2767
2768
2769
2770
2771
2772
2773
2774
2775
2776
2777
            logmsg "FAIL: $testnum - $testname - $subject\n";
        }
    }
    return $result;
}

sub setupfeatures {
    $feature{"hyper"} = $has_hyper;
    $feature{"c-ares"} = $has_cares;
    $feature{"alt-svc"} = $has_altsvc;
    $feature{"HSTS"} = $has_hsts;
    $feature{"brotli"} = $has_brotli;
    $feature{"crypto"} = $has_crypto;
    $feature{"debug"} = $debug_build;
    $feature{"getrlimit"} = $has_getrlimit;
2817
2818
2819
2820
2821
2822
2823

2824
2825
2826
2827
2828
2829
2830
    $feature{"Mime"} = 1;
    $feature{"netrc"} = 1;
    $feature{"parsedate"} = 1;
    $feature{"proxy"} = 1;
    $feature{"shuffle-dns"} = 1;
    $feature{"typecheck"} = 1;
    $feature{"verbose-strings"} = 1;


}

#######################################################################
# display information about curl and the host the test suite runs on
#
sub checksystem {







>







2823
2824
2825
2826
2827
2828
2829
2830
2831
2832
2833
2834
2835
2836
2837
    $feature{"Mime"} = 1;
    $feature{"netrc"} = 1;
    $feature{"parsedate"} = 1;
    $feature{"proxy"} = 1;
    $feature{"shuffle-dns"} = 1;
    $feature{"typecheck"} = 1;
    $feature{"verbose-strings"} = 1;
    $feature{"wakeup"} = 1;

}

#######################################################################
# display information about curl and the host the test suite runs on
#
sub checksystem {
2922
2923
2924
2925
2926
2927
2928



2929
2930
2931
2932
2933
2934
2935
           }
           if ($libcurl =~ /ares/i) {
               $has_cares=1;
               $resolver="c-ares";
           }
           if ($libcurl =~ /mesalink/i) {
               $has_mesalink=1;



           }
        }
        elsif($_ =~ /^Protocols: (.*)/i) {
            # these are the protocols compiled in to this libcurl
            @protocols = split(' ', lc($1));

            # Generate a "proto-ipv6" version of each protocol to match the







>
>
>







2929
2930
2931
2932
2933
2934
2935
2936
2937
2938
2939
2940
2941
2942
2943
2944
2945
           }
           if ($libcurl =~ /ares/i) {
               $has_cares=1;
               $resolver="c-ares";
           }
           if ($libcurl =~ /mesalink/i) {
               $has_mesalink=1;
           }
           if ($libcurl =~ /Hyper/i) {
               $has_hyper=1;
           }
        }
        elsif($_ =~ /^Protocols: (.*)/i) {
            # these are the protocols compiled in to this libcurl
            @protocols = split(' ', lc($1));

            # Generate a "proto-ipv6" version of each protocol to match the
3223
3224
3225
3226
3227
3228
3229

3230
3231
3232
3233
3234
3235
3236

    # test server ports
    $$thing =~ s/${prefix}FTP6PORT/$FTP6PORT/g;
    $$thing =~ s/${prefix}FTPSPORT/$FTPSPORT/g;
    $$thing =~ s/${prefix}FTPPORT/$FTPPORT/g;
    $$thing =~ s/${prefix}GOPHER6PORT/$GOPHER6PORT/g;
    $$thing =~ s/${prefix}GOPHERPORT/$GOPHERPORT/g;

    $$thing =~ s/${prefix}HTTPTLS6PORT/$HTTPTLS6PORT/g;
    $$thing =~ s/${prefix}HTTPTLSPORT/$HTTPTLSPORT/g;
    $$thing =~ s/${prefix}HTTP6PORT/$HTTP6PORT/g;
    $$thing =~ s/${prefix}HTTPSPORT/$HTTPSPORT/g;
    $$thing =~ s/${prefix}HTTPSPROXYPORT/$HTTPSPROXYPORT/g;
    $$thing =~ s/${prefix}HTTP2PORT/$HTTP2PORT/g;
    $$thing =~ s/${prefix}HTTPPORT/$HTTPPORT/g;







>







3233
3234
3235
3236
3237
3238
3239
3240
3241
3242
3243
3244
3245
3246
3247

    # test server ports
    $$thing =~ s/${prefix}FTP6PORT/$FTP6PORT/g;
    $$thing =~ s/${prefix}FTPSPORT/$FTPSPORT/g;
    $$thing =~ s/${prefix}FTPPORT/$FTPPORT/g;
    $$thing =~ s/${prefix}GOPHER6PORT/$GOPHER6PORT/g;
    $$thing =~ s/${prefix}GOPHERPORT/$GOPHERPORT/g;
    $$thing =~ s/${prefix}GOPHERSPORT/$GOPHERSPORT/g;
    $$thing =~ s/${prefix}HTTPTLS6PORT/$HTTPTLS6PORT/g;
    $$thing =~ s/${prefix}HTTPTLSPORT/$HTTPTLSPORT/g;
    $$thing =~ s/${prefix}HTTP6PORT/$HTTP6PORT/g;
    $$thing =~ s/${prefix}HTTPSPORT/$HTTPSPORT/g;
    $$thing =~ s/${prefix}HTTPSPROXYPORT/$HTTPSPROXYPORT/g;
    $$thing =~ s/${prefix}HTTP2PORT/$HTTP2PORT/g;
    $$thing =~ s/${prefix}HTTPPORT/$HTTPPORT/g;
3325
3326
3327
3328
3329
3330
3331

3332
3333
3334






3335
3336







3337






3338

3339
3340
3341
3342
3343
3344
3345
        my ($d, $n) = ($2, $1);
        $d =~ s/%([0-9A-Fa-f]{2})/chr(hex($1))/eg;
        my $all = $d x $n;
        $$thing =~ s/%%REPEAT%%/$all/;
    }
}


sub fixarray {
    my @in = @_;







    for(@in) {
        subVariables(\$_);







    }






    return @in;

}

#######################################################################
# Provide time stamps for single test skipped events
#
sub timestampskippedevents {
    my $testnum = $_[0];







>
|
|

>
>
>
>
>
>
|
<
>
>
>
>
>
>
>

>
>
>
>
>
>
|
>







3336
3337
3338
3339
3340
3341
3342
3343
3344
3345
3346
3347
3348
3349
3350
3351
3352
3353

3354
3355
3356
3357
3358
3359
3360
3361
3362
3363
3364
3365
3366
3367
3368
3369
3370
3371
3372
3373
3374
3375
3376
        my ($d, $n) = ($2, $1);
        $d =~ s/%([0-9A-Fa-f]{2})/chr(hex($1))/eg;
        my $all = $d x $n;
        $$thing =~ s/%%REPEAT%%/$all/;
    }
}

my $prevupdate;
sub subNewlines {
    my ($thing) = @_;

    # When curl is built with Hyper, it gets all response headers delivered as
    # name/value pairs and curl "invents" the newlines when it saves the
    # headers. Therefore, curl will always save headers with CRLF newlines
    # when built to use Hyper. By making sure we deliver all tests using CRLF
    # as well, all test comparisons will survive without knowing about this
    # little quirk.


    if(($$thing =~ /^HTTP\/(1.1|1.0|2) [1-5][^\x0d]*\z/) ||
       (($$thing =~ /^[a-z0-9_-]+: [^\x0d]*\z/i) &&
        # skip curl error messages
        ($$thing !~ /^curl: \(\d+\) /))) {
        # enforce CRLF newline
        $$thing =~ s/\x0a/\x0d\x0a/;
        $prevupdate = 1;
    }
    else {
        if(($$thing =~ /^\n\z/) && $prevupdate) {
            # if there's a blank link after a line we update, we hope it is
            # the empty line following headers
            $$thing =~ s/\x0a/\x0d\x0a/;
        }
        $prevupdate = 0;
    }
}

#######################################################################
# Provide time stamps for single test skipped events
#
sub timestampskippedevents {
    my $testnum = $_[0];
3383
3384
3385
3386
3387
3388
3389








































3390
3391
3392
3393
3394
3395
3396
            $timetoolend{$testnum} = $timeprepini{$testnum};
            $timetoolini{$testnum} = $timeprepini{$testnum};
            $timesrvrend{$testnum} = $timeprepini{$testnum};
            $timesrvrini{$testnum} = $timeprepini{$testnum};
        }
    }
}









































#######################################################################
# Run a single specified test case
#
sub singletest {
    my ($evbased, # 1 means switch on if possible (and "curl" is tested)
                  # returns "not a test" if it can't be used for this test







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







3414
3415
3416
3417
3418
3419
3420
3421
3422
3423
3424
3425
3426
3427
3428
3429
3430
3431
3432
3433
3434
3435
3436
3437
3438
3439
3440
3441
3442
3443
3444
3445
3446
3447
3448
3449
3450
3451
3452
3453
3454
3455
3456
3457
3458
3459
3460
3461
3462
3463
3464
3465
3466
3467
            $timetoolend{$testnum} = $timeprepini{$testnum};
            $timetoolini{$testnum} = $timeprepini{$testnum};
            $timesrvrend{$testnum} = $timeprepini{$testnum};
            $timesrvrini{$testnum} = $timeprepini{$testnum};
        }
    }
}

#
# 'prepro' processes the input array and replaces %-variables in the array
# etc. Returns the processed version of the array

sub prepro {
    my (@entiretest) = @_;
    my $show = 1;
    my @out;
    for my $s (@entiretest) {
        my $f = $s;
        if($s =~ /^ *%if (.*)/) {
            my $cond = $1;
            my $rev = 0;

            if($cond =~ /^!(.*)/) {
                $cond = $1;
                $rev = 1;
            }
            $rev ^= $feature{$cond} ? 1 : 0;
            $show = $rev;
            next;
        }
        elsif($s =~ /^ *%else/) {
            $show ^= 1;
            next;
        }
        elsif($s =~ /^ *%endif/) {
            $show = 1;
            next;
        }
        if($show) {
            subVariables(\$s, "%");
            subBase64(\$s);
            subNewlines(\$s) if($has_hyper);
            push @out, $s;
        }
    }
    return @out;
}

#######################################################################
# Run a single specified test case
#
sub singletest {
    my ($evbased, # 1 means switch on if possible (and "curl" is tested)
                  # returns "not a test" if it can't be used for this test
3542
3543
3544
3545
3546
3547
3548
3549
3550
3551
3552
3553
3554
3555
3556
3557


3558
3559
3560
3561
3562
3563
3564
3565
3566
3567
3568
3569
3570
3571
3572
3573
3574
3575
3576
3577
3578
3579
3580
3581
3582
3583
        $why = serverfortest($testnum);
    }

    # Save a preprocessed version of the entire test file. This allows more
    # "basic" test case readers to enjoy variable replacements.
    my @entiretest = fulltest();
    my $otest = "log/test$testnum";
    open(D, ">$otest");
    my $diff;
    for my $s (@entiretest) {
        my $f = $s;
        subVariables(\$s, "%");
        subBase64(\$s);
        if($f ne $s) {
            $diff++;
        }


        print D $s;
    }
    close(D);

    # remove the separate test file again if nothing was updated to keep
    # things simpler
    unlink($otest) if(!$diff);

    # in case the process changed the file, reload it
    loadtest("log/test${testnum}") if($diff);

    # timestamp required servers verification end
    $timesrvrend{$testnum} = Time::HiRes::time();

    my @setenv = getpart("client", "setenv");
    if(@setenv) {
        foreach my $s (@setenv) {
            chomp $s;
            subVariables(\$s);
            if($s =~ /([^=]*)=(.*)/) {
                my ($var, $content) = ($1, $2);
                # remember current setting, to restore it once test runs
                $oldenv{$var} = ($ENV{$var})?"$ENV{$var}":'notset';
                # set new value
                if(!$content) {
                    delete $ENV{$var} if($ENV{$var});







|
<
|
<
<
<
<
<
|
>
>
|
<


<
<
<
<

|








<







3613
3614
3615
3616
3617
3618
3619
3620

3621





3622
3623
3624
3625

3626
3627




3628
3629
3630
3631
3632
3633
3634
3635
3636
3637

3638
3639
3640
3641
3642
3643
3644
        $why = serverfortest($testnum);
    }

    # Save a preprocessed version of the entire test file. This allows more
    # "basic" test case readers to enjoy variable replacements.
    my @entiretest = fulltest();
    my $otest = "log/test$testnum";


    @entiretest = prepro(@entiretest);






    # save the new version
    open(D, ">$otest");
    print D @entiretest;

    close(D);





    # in case the process changed the file, reload it
    loadtest("log/test${testnum}");

    # timestamp required servers verification end
    $timesrvrend{$testnum} = Time::HiRes::time();

    my @setenv = getpart("client", "setenv");
    if(@setenv) {
        foreach my $s (@setenv) {
            chomp $s;

            if($s =~ /([^=]*)=(.*)/) {
                my ($var, $content) = ($1, $2);
                # remember current setting, to restore it once test runs
                $oldenv{$var} = ($ENV{$var})?"$ENV{$var}":'notset';
                # set new value
                if(!$content) {
                    delete $ENV{$var} if($ENV{$var});
3601
3602
3603
3604
3605
3606
3607
3608
3609
3610
3611
3612
3613
3614
3615
    }

    if(!$why) {
        my @precheck = getpart("client", "precheck");
        if(@precheck) {
            $cmd = $precheck[0];
            chomp $cmd;
            subVariables(\$cmd);
            if($cmd) {
                my @p = split(/ /, $cmd);
                if($p[0] !~ /\//) {
                    # the first word, the command, does not contain a slash so
                    # we will scan the "improved" PATH to find the command to
                    # be able to run it
                    my $fullp = checktestcmd($p[0]);







<







3662
3663
3664
3665
3666
3667
3668

3669
3670
3671
3672
3673
3674
3675
    }

    if(!$why) {
        my @precheck = getpart("client", "precheck");
        if(@precheck) {
            $cmd = $precheck[0];
            chomp $cmd;

            if($cmd) {
                my @p = split(/ /, $cmd);
                if($p[0] !~ /\//) {
                    # the first word, the command, does not contain a slash so
                    # we will scan the "improved" PATH to find the command to
                    # be able to run it
                    my $fullp = checktestcmd($p[0]);
3680
3681
3682
3683
3684
3685
3686
3687
3688
3689
3690
3691
3692
3693
3694
3695
3696
3697
3698
3699
3700
3701
3702
3703
3704
3705
3706
3707
3708
3709
3710
3711
3712
3713
3714
3715
3716
3717
3718
3719
3720
3721
3722
3723
        my $filemode=$replyattr{'mode'};
        if($filemode && ($filemode eq "text") && $has_textaware) {
            # text mode when running on windows: fix line endings
            map s/\r\n/\n/g, @reply;
            map s/\n/\r\n/g, @reply;
        }
    }
    for my $r (@reply) {
        subVariables(\$r);
    }

    # this is the valid protocol blurb curl should generate
    my @protocol= fixarray ( getpart("verify", "protocol") );

    # this is the valid protocol blurb curl should generate to a proxy
    my @proxyprot = fixarray ( getpart("verify", "proxy") );

    # redirected stdout/stderr to these files
    $STDOUT="$LOGDIR/stdout$testnum";
    $STDERR="$LOGDIR/stderr$testnum";

    # if this section exists, we verify that the stdout contained this:
    my @validstdout = fixarray ( getpart("verify", "stdout") );
    my @validstderr = fixarray ( getpart("verify", "stderr") );

    # if this section exists, we verify upload
    my @upload = getpart("verify", "upload");
    if(@upload) {
      my %hash = getpartattr("verify", "upload");
      if($hash{'nonewline'}) {
          # cut off the final newline from the final line of the upload data
          chomp($upload[$#upload]);
      }
    }

    # if this section exists, it might be FTP server instructions:
    my @ftpservercmd = fixarray ( getpart("reply", "servercmd") );

    my $CURLOUT="$LOGDIR/curl$testnum.out"; # curl output if not stdout

    # name of the test
    logmsg "[$testname]\n" if(!$short);

    if($listonly) {







<
<
|
<

|


|






|
|












|







3740
3741
3742
3743
3744
3745
3746


3747

3748
3749
3750
3751
3752
3753
3754
3755
3756
3757
3758
3759
3760
3761
3762
3763
3764
3765
3766
3767
3768
3769
3770
3771
3772
3773
3774
3775
3776
3777
3778
3779
3780
        my $filemode=$replyattr{'mode'};
        if($filemode && ($filemode eq "text") && $has_textaware) {
            # text mode when running on windows: fix line endings
            map s/\r\n/\n/g, @reply;
            map s/\n/\r\n/g, @reply;
        }
    }




    # this is the valid protocol blurb curl should generate
    my @protocol= getpart("verify", "protocol");

    # this is the valid protocol blurb curl should generate to a proxy
    my @proxyprot = getpart("verify", "proxy");

    # redirected stdout/stderr to these files
    $STDOUT="$LOGDIR/stdout$testnum";
    $STDERR="$LOGDIR/stderr$testnum";

    # if this section exists, we verify that the stdout contained this:
    my @validstdout = getpart("verify", "stdout");
    my @validstderr = getpart("verify", "stderr");

    # if this section exists, we verify upload
    my @upload = getpart("verify", "upload");
    if(@upload) {
      my %hash = getpartattr("verify", "upload");
      if($hash{'nonewline'}) {
          # cut off the final newline from the final line of the upload data
          chomp($upload[$#upload]);
      }
    }

    # if this section exists, it might be FTP server instructions:
    my @ftpservercmd = getpart("reply", "servercmd");

    my $CURLOUT="$LOGDIR/curl$testnum.out"; # curl output if not stdout

    # name of the test
    logmsg "[$testname]\n" if(!$short);

    if($listonly) {
3747
3748
3749
3750
3751
3752
3753
3754
3755
3756
3757
3758
3759
3760
3761
    my @blaha;
    ($cmd, @blaha)= getpart("client", "command");

    if($cmd) {
        # make some nice replace operations
        $cmd =~ s/\n//g; # no newlines please
        # substitute variables in the command line
        subVariables(\$cmd);
    }
    else {
        # there was no command given, use something silly
        $cmd="-";
    }
    if($has_memory_tracking) {
        unlink($memdump);







<







3804
3805
3806
3807
3808
3809
3810

3811
3812
3813
3814
3815
3816
3817
    my @blaha;
    ($cmd, @blaha)= getpart("client", "command");

    if($cmd) {
        # make some nice replace operations
        $cmd =~ s/\n//g; # no newlines please
        # substitute variables in the command line

    }
    else {
        # there was no command given, use something silly
        $cmd="-";
    }
    if($has_memory_tracking) {
        unlink($memdump);
3769
3770
3771
3772
3773
3774
3775
3776
3777
3778
3779
3780
3781
3782
3783
        if(@inputfile || $filename) {
            if(!$filename) {
                logmsg "ERROR: section client=>file has no name attribute\n";
                timestampskippedevents($testnum);
                return -1;
            }
            my $fileContent = join('', @inputfile);
            subVariables(\$fileContent);
            open(OUTFILE, ">$filename");
            binmode OUTFILE; # for crapage systems, use binary
            if($fileattr{'nonewline'}) {
                # cut off the final newline
                chomp($fileContent);
            }
            print OUTFILE $fileContent;







<







3825
3826
3827
3828
3829
3830
3831

3832
3833
3834
3835
3836
3837
3838
        if(@inputfile || $filename) {
            if(!$filename) {
                logmsg "ERROR: section client=>file has no name attribute\n";
                timestampskippedevents($testnum);
                return -1;
            }
            my $fileContent = join('', @inputfile);

            open(OUTFILE, ">$filename");
            binmode OUTFILE; # for crapage systems, use binary
            if($fileattr{'nonewline'}) {
                # cut off the final newline
                chomp($fileContent);
            }
            print OUTFILE $fileContent;
4041
4042
4043
4044
4045
4046
4047
4048
4049
4050
4051
4052
4053
4054
4055
    }

    # run the postcheck command
    my @postcheck= getpart("client", "postcheck");
    if(@postcheck) {
        $cmd = join("", @postcheck);
        chomp $cmd;
        subVariables(\$cmd);
        if($cmd) {
            logmsg "postcheck $cmd\n" if($verbose);
            my $rc = runclient("$cmd");
            # Must run the postcheck command in torture mode in order
            # to clean up, but the result can't be relied upon.
            if($rc != 0 && !$torture) {
                logmsg " postcheck FAILED\n";







<







4096
4097
4098
4099
4100
4101
4102

4103
4104
4105
4106
4107
4108
4109
    }

    # run the postcheck command
    my @postcheck= getpart("client", "postcheck");
    if(@postcheck) {
        $cmd = join("", @postcheck);
        chomp $cmd;

        if($cmd) {
            logmsg "postcheck $cmd\n" if($verbose);
            my $rc = runclient("$cmd");
            # Must run the postcheck command in torture mode in order
            # to clean up, but the result can't be relied upon.
            if($rc != 0 && !$torture) {
                logmsg " postcheck FAILED\n";
4101
4102
4103
4104
4105
4106
4107
4108
4109
4110
4111
4112
4113
4114
4115
4116
4117
                }
            }
            # this is to get rid of array entries that vanished (zero
            # length) because of replacements
            @actual = @newgen;
        }

        # variable-replace in the stdout we have from the test case file
        @validstdout = fixarray(@validstdout);

        # get all attributes
        my %hash = getpartattr("verify", "stdout");

        # get the mode attribute
        my $filemode=$hash{'mode'};
        if($filemode && ($filemode eq "text") && $has_textaware) {
            # text mode when running on windows: fix line endings







<
<
<







4155
4156
4157
4158
4159
4160
4161



4162
4163
4164
4165
4166
4167
4168
                }
            }
            # this is to get rid of array entries that vanished (zero
            # length) because of replacements
            @actual = @newgen;
        }




        # get all attributes
        my %hash = getpartattr("verify", "stdout");

        # get the mode attribute
        my $filemode=$hash{'mode'};
        if($filemode && ($filemode eq "text") && $has_textaware) {
            # text mode when running on windows: fix line endings
4152
4153
4154
4155
4156
4157
4158
4159
4160
4161
4162
4163
4164
4165
4166
4167
4168
                }
            }
            # this is to get rid of array entries that vanished (zero
            # length) because of replacements
            @actual = @newgen;
        }

        # variable-replace in the stderr we have from the test case file
        @validstderr = fixarray(@validstderr);

        # get all attributes
        my %hash = getpartattr("verify", "stderr");

        # get the mode attribute
        my $filemode=$hash{'mode'};
        if($filemode && ($filemode eq "text") && $has_textaware) {
            # text mode when running on windows: fix line endings







<
<
<







4203
4204
4205
4206
4207
4208
4209



4210
4211
4212
4213
4214
4215
4216
                }
            }
            # this is to get rid of array entries that vanished (zero
            # length) because of replacements
            @actual = @newgen;
        }




        # get all attributes
        my %hash = getpartattr("verify", "stderr");

        # get the mode attribute
        my $filemode=$hash{'mode'};
        if($filemode && ($filemode eq "text") && $has_textaware) {
            # text mode when running on windows: fix line endings
4210
4211
4212
4213
4214
4215
4216
4217
4218
4219
4220
4221
4222
4223
4224
            @out = striparray( $_, \@out);
            @protstrip= striparray( $_, \@protstrip);
        }

        # what parts to cut off from the protocol
        my @strippart = getpart("verify", "strippart");
        my $strip;
        @strippart = fixarray(@strippart);
        for $strip (@strippart) {
            chomp $strip;
            for(@out) {
                eval $strip;
            }
        }








|







4258
4259
4260
4261
4262
4263
4264
4265
4266
4267
4268
4269
4270
4271
4272
            @out = striparray( $_, \@out);
            @protstrip= striparray( $_, \@protstrip);
        }

        # what parts to cut off from the protocol
        my @strippart = getpart("verify", "strippart");
        my $strip;

        for $strip (@strippart) {
            chomp $strip;
            for(@out) {
                eval $strip;
            }
        }

4365
4366
4367
4368
4369
4370
4371
4372
4373
4374
4375
4376
4377
4378
4379
4380
                    }
                }
                # this is to get rid of array entries that vanished (zero
                # length) because of replacements
                @generated = @newgen;
            }

            @outfile = fixarray(@outfile);

            $res = compare($testnum, $testname, "output ($filename)",
                           \@generated, \@outfile);
            if($res) {
                return $errorreturncode;
            }

            $outputok = 1; # output checked







<
<







4413
4414
4415
4416
4417
4418
4419


4420
4421
4422
4423
4424
4425
4426
                    }
                }
                # this is to get rid of array entries that vanished (zero
                # length) because of replacements
                @generated = @newgen;
            }



            $res = compare($testnum, $testname, "output ($filename)",
                           \@generated, \@outfile);
            if($res) {
                return $errorreturncode;
            }

            $outputok = 1; # output checked
4574
4575
4576
4577
4578
4579
4580
4581
4582
4583
4584
4585
4586
4587
4588
    my ($pid, $pid2);
    for(@what) {
        my (@whatlist) = split(/\s+/,$_);
        my $what = lc($whatlist[0]);
        $what =~ s/[^a-z0-9\/-]//g;

        my $certfile;
        if($what =~ /^(ftp|http|imap|pop3|smtp)s((\d*)(-ipv6|-unix|))$/) {
            $certfile = ($whatlist[1]) ? $whatlist[1] : 'stunnel.pem';
        }

        if(($what eq "pop3") ||
           ($what eq "ftp") ||
           ($what eq "imap") ||
           ($what eq "smtp")) {







|







4620
4621
4622
4623
4624
4625
4626
4627
4628
4629
4630
4631
4632
4633
4634
    my ($pid, $pid2);
    for(@what) {
        my (@whatlist) = split(/\s+/,$_);
        my $what = lc($whatlist[0]);
        $what =~ s/[^a-z0-9\/-]//g;

        my $certfile;
        if($what =~ /^(ftp|gopher|http|imap|pop3|smtp)s((\d*)(-ipv6|-unix|))$/) {
            $certfile = ($whatlist[1]) ? $whatlist[1] : 'stunnel.pem';
        }

        if(($what eq "pop3") ||
           ($what eq "ftp") ||
           ($what eq "imap") ||
           ($what eq "smtp")) {
4791
4792
4793
4794
4795
4796
4797
4798
4799
4800
4801
4802
4803
4804
4805



































4806
4807
4808
4809
4810
4811
4812
                    return "failed starting HTTP server";
                }
                printf ("* pid http => %d %d\n", $pid, $pid2) if($verbose);
                $run{'http'}="$pid $pid2";
            }
            if(!$run{'https'}) {
                ($pid, $pid2, $HTTPSPORT) =
                    runhttpsserver($verbose, "", "", $certfile);
                if($pid <= 0) {
                    return "failed starting HTTPS server (stunnel)";
                }
                logmsg sprintf("* pid https => %d %d\n", $pid, $pid2)
                    if($verbose);
                $run{'https'}="$pid $pid2";
            }



































        }
        elsif($what eq "https-proxy") {
            if(!$stunnel) {
                # we can't run https-proxy tests without stunnel
                return "no stunnel";
            }
            if($runcert{'https-proxy'} &&







|







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







4837
4838
4839
4840
4841
4842
4843
4844
4845
4846
4847
4848
4849
4850
4851
4852
4853
4854
4855
4856
4857
4858
4859
4860
4861
4862
4863
4864
4865
4866
4867
4868
4869
4870
4871
4872
4873
4874
4875
4876
4877
4878
4879
4880
4881
4882
4883
4884
4885
4886
4887
4888
4889
4890
4891
4892
4893
                    return "failed starting HTTP server";
                }
                printf ("* pid http => %d %d\n", $pid, $pid2) if($verbose);
                $run{'http'}="$pid $pid2";
            }
            if(!$run{'https'}) {
                ($pid, $pid2, $HTTPSPORT) =
                    runhttpsserver($verbose, "https", "", $certfile);
                if($pid <= 0) {
                    return "failed starting HTTPS server (stunnel)";
                }
                logmsg sprintf("* pid https => %d %d\n", $pid, $pid2)
                    if($verbose);
                $run{'https'}="$pid $pid2";
            }
        }
        elsif($what eq "gophers") {
            if(!$stunnel) {
                # we can't run TLS tests without stunnel
                return "no stunnel";
            }
            if($runcert{'gophers'} && ($runcert{'gophers'} ne $certfile)) {
                # stop server when running and using a different cert
                stopserver('gophers');
            }
            if($torture && $run{'gopher'} &&
               !responsive_http_server("gopher", $verbose, 0, $GOPHERPORT)) {
                stopserver('gopher');
            }
            if(!$run{'gopher'}) {
                ($pid, $pid2, $GOPHERPORT) =
                    runhttpserver("gopher", $verbose, 0);
                if($pid <= 0) {
                    return "failed starting GOPHER server";
                }
                printf ("* pid gopher => %d %d\n", $pid, $pid2) if($verbose);
                print "GOPHERPORT => $GOPHERPORT\n" if($verbose);
                $run{'gopher'}="$pid $pid2";
            }
            if(!$run{'gophers'}) {
                ($pid, $pid2, $GOPHERSPORT) =
                    runhttpsserver($verbose, "gophers", "", $certfile);
                if($pid <= 0) {
                    return "failed starting GOPHERS server (stunnel)";
                }
                logmsg sprintf("* pid gophers => %d %d\n", $pid, $pid2)
                    if($verbose);
                print "GOPHERSPORT => $GOPHERSPORT\n" if($verbose);
                $run{'gophers'}="$pid $pid2";
            }
        }
        elsif($what eq "https-proxy") {
            if(!$stunnel) {
                # we can't run https-proxy tests without stunnel
                return "no stunnel";
            }
            if($runcert{'https-proxy'} &&
4820
4821
4822
4823
4824
4825
4826
4827
4828
4829
4830
4831
4832
4833
4834
            my $f = startservers("http-proxy");
            if($f) {
                return $f;1
            }

            if(!$run{'https-proxy'}) {
                ($pid, $pid2, $HTTPSPROXYPORT) =
                    runhttpsserver($verbose, "", "proxy", $certfile);
                if($pid <= 0) {
                    return "failed starting HTTPS-proxy (stunnel)";
                }
                logmsg sprintf("* pid https-proxy => %d %d\n", $pid, $pid2)
                    if($verbose);
                $run{'https-proxy'}="$pid $pid2";
            }







|







4901
4902
4903
4904
4905
4906
4907
4908
4909
4910
4911
4912
4913
4914
4915
            my $f = startservers("http-proxy");
            if($f) {
                return $f;1
            }

            if(!$run{'https-proxy'}) {
                ($pid, $pid2, $HTTPSPROXYPORT) =
                    runhttpsserver($verbose, "https", "proxy", $certfile);
                if($pid <= 0) {
                    return "failed starting HTTPS-proxy (stunnel)";
                }
                logmsg sprintf("* pid https-proxy => %d %d\n", $pid, $pid2)
                    if($verbose);
                $run{'https-proxy'}="$pid $pid2";
            }
5172
5173
5174
5175
5176
5177
5178
5179
5180
5181
5182
5183
5184
5185
5186
5187
5188
5189
5190
5191
        last if((not $fullstats) && (not $counter--));
        logmsg "$txt\n";
    }

    logmsg "\n";
}

# globally disabled tests
disabledtests("$TESTDIR/DISABLED");

# locally disabled tests, ignored by git etc
disabledtests("$TESTDIR/DISABLED.local");

#######################################################################
# Check options to this test program
#

# Special case for CMake: replace '$TFLAGS' by the contents of the
# environment variable (if any).
if(@ARGV && $ARGV[-1] eq '$TFLAGS') {







<
<
<
<
<
<







5253
5254
5255
5256
5257
5258
5259






5260
5261
5262
5263
5264
5265
5266
        last if((not $fullstats) && (not $counter--));
        logmsg "$txt\n";
    }

    logmsg "\n";
}







#######################################################################
# Check options to this test program
#

# Special case for CMake: replace '$TFLAGS' by the contents of the
# environment variable (if any).
if(@ARGV && $ARGV[-1] eq '$TFLAGS') {
5489
5490
5491
5492
5493
5494
5495



5496
5497
5498
5499
5500
5501

5502
5503
5504
5505
5506
5507
5508








5509
5510
5511
5512
5513
5514
5515
5516

5517



5518
5519

5520
5521
5522
5523
5524
5525
5526
# Output curl version and host info being tested
#

if(!$listonly) {
    checksystem();
}




#######################################################################
# Fetch all disabled tests, if there are any
#

sub disabledtests {
    my ($file) = @_;


    if(open(D, "<$file")) {
        while(<D>) {
            if(/^ *\#/) {
                # allow comments
                next;
            }








            if($_ =~ /(\d+)/) {
                my ($n) = $1;
                $disabled{$n}=$n; # disable this test number
                if(! -f "$srcdir/data/test$n") {
                    print STDERR "WARNING! Non-existing test $n in DISABLED!\n";
                    # fail hard to make user notice
                    exit 1;
                }

            }



        }
        close(D);

    }
}

#######################################################################
# If 'all' tests are requested, find out all test numbers
#








>
>
>






>







>
>
>
>
>
>
>
>
|



|



>

>
>
>
|
<
>







5564
5565
5566
5567
5568
5569
5570
5571
5572
5573
5574
5575
5576
5577
5578
5579
5580
5581
5582
5583
5584
5585
5586
5587
5588
5589
5590
5591
5592
5593
5594
5595
5596
5597
5598
5599
5600
5601
5602
5603
5604
5605
5606
5607
5608
5609

5610
5611
5612
5613
5614
5615
5616
5617
# Output curl version and host info being tested
#

if(!$listonly) {
    checksystem();
}

# globally disabled tests
disabledtests("$TESTDIR/DISABLED");

#######################################################################
# Fetch all disabled tests, if there are any
#

sub disabledtests {
    my ($file) = @_;
    my @input;

    if(open(D, "<$file")) {
        while(<D>) {
            if(/^ *\#/) {
                # allow comments
                next;
            }
            push @input, $_;
        }
        close(D);

        # preprocess the input to make conditionally disabled tests depending
        # on variables
        my @pp = prepro(@input);
        for my $t (@pp) {
            if($t =~ /(\d+)/) {
                my ($n) = $1;
                $disabled{$n}=$n; # disable this test number
                if(! -f "$srcdir/data/test$n") {
                    print STDERR "WARNING! Non-existing test $n in $file!\n";
                    # fail hard to make user notice
                    exit 1;
                }
                logmsg "DISABLED: test $n\n" if ($verbose);
            }
            else {
                print STDERR "$file: rubbish content: $t\n";
                exit 2;
            }

        }
    }
}

#######################################################################
# If 'all' tests are requested, find out all test numbers
#

Changes to jni/curl/tests/server/Makefile.in.
632
633
634
635
636
637
638

639
640
641
642
643
644
645
STRIP = @STRIP@
SUPPORT_FEATURES = @SUPPORT_FEATURES@
SUPPORT_PROTOCOLS = @SUPPORT_PROTOCOLS@
USE_ARES = @USE_ARES@
USE_BEARSSL = @USE_BEARSSL@
USE_GNUTLS = @USE_GNUTLS@
USE_GNUTLS_NETTLE = @USE_GNUTLS_NETTLE@

USE_LIBRTMP = @USE_LIBRTMP@
USE_LIBSSH = @USE_LIBSSH@
USE_LIBSSH2 = @USE_LIBSSH2@
USE_MBEDTLS = @USE_MBEDTLS@
USE_MESALINK = @USE_MESALINK@
USE_NGHTTP2 = @USE_NGHTTP2@
USE_NGHTTP3 = @USE_NGHTTP3@







>







632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
STRIP = @STRIP@
SUPPORT_FEATURES = @SUPPORT_FEATURES@
SUPPORT_PROTOCOLS = @SUPPORT_PROTOCOLS@
USE_ARES = @USE_ARES@
USE_BEARSSL = @USE_BEARSSL@
USE_GNUTLS = @USE_GNUTLS@
USE_GNUTLS_NETTLE = @USE_GNUTLS_NETTLE@
USE_HYPER = @USE_HYPER@
USE_LIBRTMP = @USE_LIBRTMP@
USE_LIBSSH = @USE_LIBSSH@
USE_LIBSSH2 = @USE_LIBSSH2@
USE_MBEDTLS = @USE_MBEDTLS@
USE_MESALINK = @USE_MESALINK@
USE_NGHTTP2 = @USE_NGHTTP2@
USE_NGHTTP3 = @USE_NGHTTP3@
jni/curl/tests/server/base64.pl became executable.
Changes to jni/curl/tests/server/disabled.c.
26
27
28
29
30
31
32

33
34
35
36
37
38
39
 * regular curl -V output.
 *
 * Disabled protocols are visible in curl_version_info() and are not included
 * in this table.
 */

#include "curl_setup.h"

#include <stdio.h>

static const char *disabled[]={
#ifdef CURL_DISABLE_COOKIES
  "cookies",
#endif
#ifdef CURL_DISABLE_CRYPTO_AUTH







>







26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
 * regular curl -V output.
 *
 * Disabled protocols are visible in curl_version_info() and are not included
 * in this table.
 */

#include "curl_setup.h"
#include "multihandle.h" /* for ENABLE_WAKEUP */
#include <stdio.h>

static const char *disabled[]={
#ifdef CURL_DISABLE_COOKIES
  "cookies",
#endif
#ifdef CURL_DISABLE_CRYPTO_AUTH
61
62
63
64
65
66
67



68
69
70
71
72
73
74
75
76
77
78
79
  "shuffle-dns",
#endif
#ifdef CURL_DISABLE_TYPECHECK
  "typecheck",
#endif
#ifdef CURL_DISABLE_VERBOSE_STRINGS
  "verbose-strings",



#endif
  NULL
};

int main(void)
{
  int i;
  for(i = 0; disabled[i]; i++)
    printf("%s\n", disabled[i]);

  return 0;
}







>
>
>












62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
  "shuffle-dns",
#endif
#ifdef CURL_DISABLE_TYPECHECK
  "typecheck",
#endif
#ifdef CURL_DISABLE_VERBOSE_STRINGS
  "verbose-strings",
#endif
#ifndef ENABLE_WAKEUP
  "wakeup",
#endif
  NULL
};

int main(void)
{
  int i;
  for(i = 0; disabled[i]; i++)
    printf("%s\n", disabled[i]);

  return 0;
}
Changes to jni/curl/tests/server/mqttd.c.
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
               rc - 12, payload_len);
        goto end;
      }
      else if((payload_len + 1) > MAX_CLIENT_ID_LENGTH) {
        logmsg("Too large client id");
        goto end;
      }
      memcpy(client_id, &buffer[14], payload_len);
      client_id[payload_len] = 0;

      logmsg("MQTT client connect accepted: %s", client_id);

      /* The first packet sent from the Server to the Client MUST be a
         CONNACK Packet */








|







533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
               rc - 12, payload_len);
        goto end;
      }
      else if((payload_len + 1) > MAX_CLIENT_ID_LENGTH) {
        logmsg("Too large client id");
        goto end;
      }
      memcpy(client_id, &buffer[12], payload_len);
      client_id[payload_len] = 0;

      logmsg("MQTT client connect accepted: %s", client_id);

      /* The first packet sent from the Server to the Client MUST be a
         CONNACK Packet */

Changes to jni/curl/tests/server/socksd.c.
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
 * "backend [IPv4]" - numerical IPv4 address of backend to connect to
 * "backendport [number:0]" - TCP port of backend to connect to. 0 means use
                              the client's specified port number.
 * "method [number: 0]" - connect method to respond with:
 *                        0 - no auth
 *                        1 - GSSAPI (not supported)
 *                        2 - user + password
 * "response [number]" - the decimal number to repsond to a connect
 *                       SOCKS5: 0 is OK, SOCKS4: 90 is ok
 *
 */

/* based on sockfilt.c */

#ifdef HAVE_SIGNAL_H







|







44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
 * "backend [IPv4]" - numerical IPv4 address of backend to connect to
 * "backendport [number:0]" - TCP port of backend to connect to. 0 means use
                              the client's specified port number.
 * "method [number: 0]" - connect method to respond with:
 *                        0 - no auth
 *                        1 - GSSAPI (not supported)
 *                        2 - user + password
 * "response [number]" - the decimal number to respond to a connect
 *                       SOCKS5: 0 is OK, SOCKS4: 90 is ok
 *
 */

/* based on sockfilt.c */

#ifdef HAVE_SIGNAL_H
Changes to jni/curl/tests/serverhelp.pm.
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
# Return server name string formatted for presentation purposes
#
sub servername_str {
    my ($proto, $ipver, $idnum) = @_;

    $proto = uc($proto) if($proto);
    die "unsupported protocol: '$proto'" unless($proto &&
        ($proto =~ /^(((FTP|HTTP|HTTP\/2|IMAP|POP3|SMTP|HTTP-PIPE)S?)|(TFTP|SFTP|SOCKS|SSH|RTSP|GOPHER|HTTPTLS|DICT|SMB|SMBS|TELNET|MQTT))$/));

    $ipver = (not $ipver) ? 'ipv4' : lc($ipver);
    die "unsupported IP version: '$ipver'" unless($ipver &&
        ($ipver =~ /^(4|6|ipv4|ipv6|-ipv4|-ipv6|unix)$/));
    $ipver = ($ipver =~ /6$/) ? '-IPv6' : (($ipver =~ /unix$/) ? '-unix' : '');

    $idnum = 1 if(not $idnum);







|







102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
# Return server name string formatted for presentation purposes
#
sub servername_str {
    my ($proto, $ipver, $idnum) = @_;

    $proto = uc($proto) if($proto);
    die "unsupported protocol: '$proto'" unless($proto &&
        ($proto =~ /^(((FTP|HTTP|HTTP\/2|IMAP|POP3|GOPHER|SMTP|HTTP-PIPE)S?)|(TFTP|SFTP|SOCKS|SSH|RTSP|HTTPTLS|DICT|SMB|SMBS|TELNET|MQTT))$/));

    $ipver = (not $ipver) ? 'ipv4' : lc($ipver);
    die "unsupported IP version: '$ipver'" unless($ipver &&
        ($ipver =~ /^(4|6|ipv4|ipv6|-ipv4|-ipv6|unix)$/));
    $ipver = ($ipver =~ /6$/) ? '-IPv6' : (($ipver =~ /unix$/) ? '-unix' : '');

    $idnum = 1 if(not $idnum);
jni/curl/tests/sshserver.pl became a regular file.
jni/curl/tests/symbol-scan.pl became executable.
Changes to jni/curl/tests/testcurl.1.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH testcurl.pl 1 "November 05, 2020" "Curl 7.74.0" "testcurl"

.SH NAME
testcurl.pl \- (automatically) test curl
.SH SYNOPSIS
.B testcurl.pl [options] [dir] > output
.SH DESCRIPTION
\fItestcurl.pl\fP is the master script to use for automatic testing of curl







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.\" * 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.
.\" *
.\" **************************************************************************
.\"
.TH testcurl.pl 1 "November 05, 2020" "Curl 7.75.0" "testcurl"

.SH NAME
testcurl.pl \- (automatically) test curl
.SH SYNOPSIS
.B testcurl.pl [options] [dir] > output
.SH DESCRIPTION
\fItestcurl.pl\fP is the master script to use for automatic testing of curl
Changes to jni/curl/tests/unit/Makefile.in.
688
689
690
691
692
693
694

695
696
697
698
699
700
701
STRIP = @STRIP@
SUPPORT_FEATURES = @SUPPORT_FEATURES@
SUPPORT_PROTOCOLS = @SUPPORT_PROTOCOLS@
USE_ARES = @USE_ARES@
USE_BEARSSL = @USE_BEARSSL@
USE_GNUTLS = @USE_GNUTLS@
USE_GNUTLS_NETTLE = @USE_GNUTLS_NETTLE@

USE_LIBRTMP = @USE_LIBRTMP@
USE_LIBSSH = @USE_LIBSSH@
USE_LIBSSH2 = @USE_LIBSSH2@
USE_MBEDTLS = @USE_MBEDTLS@
USE_MESALINK = @USE_MESALINK@
USE_NGHTTP2 = @USE_NGHTTP2@
USE_NGHTTP3 = @USE_NGHTTP3@







>







688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
STRIP = @STRIP@
SUPPORT_FEATURES = @SUPPORT_FEATURES@
SUPPORT_PROTOCOLS = @SUPPORT_PROTOCOLS@
USE_ARES = @USE_ARES@
USE_BEARSSL = @USE_BEARSSL@
USE_GNUTLS = @USE_GNUTLS@
USE_GNUTLS_NETTLE = @USE_GNUTLS_NETTLE@
USE_HYPER = @USE_HYPER@
USE_LIBRTMP = @USE_LIBRTMP@
USE_LIBSSH = @USE_LIBSSH@
USE_LIBSSH2 = @USE_LIBSSH2@
USE_MBEDTLS = @USE_MBEDTLS@
USE_MESALINK = @USE_MESALINK@
USE_NGHTTP2 = @USE_NGHTTP2@
USE_NGHTTP3 = @USE_NGHTTP3@
Changes to jni/curl/tests/unit/curlcheck.h.
18
19
20
21
22
23
24
25

26
27
28
29

30
31
32

33
34
35
36

37
38
39

40
41
42
43
44
45
46

47
48
49
50
51
52
53
54
55
56
57
58
59

60
61
62
63
64

65
66
67

68
69
70
71
72


73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
 * KIND, either express or implied.
 *
 ***************************************************************************/
#include "test.h"

/* The fail macros mark the current test step as failed, and continue */
#define fail_if(expr, msg)                              \

  if(expr) {                                            \
    fprintf(stderr, "%s:%d Assertion '%s' met: %s\n",   \
            __FILE__, __LINE__, #expr, msg);            \
    unitfail++;                                         \

  }

#define fail_unless(expr, msg)                           \

  if(!(expr)) {                                          \
    fprintf(stderr, "%s:%d Assertion '%s' failed: %s\n", \
            __FILE__, __LINE__, #expr, msg);             \
    unitfail++;                                          \

  }

#define verify_memory(dynamic, check, len)                                  \

  if(dynamic && memcmp(dynamic, check, len)) {                              \
    fprintf(stderr, "%s:%d Memory buffer mismatch size %d. '%s' is not\n",  \
            __FILE__, __LINE__, len,                                        \
            hexdump((const unsigned char *)check, len));                    \
    fprintf(stderr, "%s:%d the same as '%s'\n", __FILE__, __LINE__,         \
            hexdump((const unsigned char *)dynamic, len));                  \
    unitfail++;                                                             \

  }

/* fail() is for when the test case figured out by itself that a check
   proved a failure */
#define fail(msg) do {                                                 \
    fprintf(stderr, "%s:%d test failed: '%s'\n",                       \
            __FILE__, __LINE__, msg);                                  \
    unitfail++;                                                        \
  } while(0)


/* The abort macros mark the current test step as failed, and exit the test */
#define abort_if(expr, msg)                                   \

  if(expr) {                                                  \
    fprintf(stderr, "%s:%d Abort assertion '%s' met: %s\n",   \
            __FILE__, __LINE__, #expr, msg);                  \
    unitfail++;                                               \
    goto unit_test_abort;                                     \

  }

#define abort_unless(expr, msg)                                \

  if(!(expr)) {                                                \
    fprintf(stderr, "%s:%d Abort assertion '%s' failed: %s\n", \
            __FILE__, __LINE__, #expr, msg);                   \
    unitfail++;                                                \
    goto unit_test_abort;                                      \


  }

#define abort_test(msg) do {                                  \
    fprintf(stderr, "%s:%d test aborted: '%s'\n",             \
            __FILE__, __LINE__, msg);                         \
    unitfail++;                                               \
    goto unit_test_abort;                                     \
  } while(0)



extern int unitfail;

#define UNITTEST_START                          \
  int test(char *arg)                           \
  {                                             \







|
>
|
|
|
|
>
|

|
>
|
|
|
|
>
|

|
>
|
|
|
|
|
|
|
>
|











|
>
|
|
|
|
|
>
|

|
>
|
|
|
|
|
>
>
|
|
|





<







18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91

92
93
94
95
96
97
98
 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
 * KIND, either express or implied.
 *
 ***************************************************************************/
#include "test.h"

/* The fail macros mark the current test step as failed, and continue */
#define fail_if(expr, msg)                                \
  do {                                                    \
    if(expr) {                                            \
      fprintf(stderr, "%s:%d Assertion '%s' met: %s\n",   \
              __FILE__, __LINE__, #expr, msg);            \
      unitfail++;                                         \
    }                                                     \
  } while(0)

#define fail_unless(expr, msg)                             \
  do {                                                     \
    if(!(expr)) {                                          \
      fprintf(stderr, "%s:%d Assertion '%s' failed: %s\n", \
              __FILE__, __LINE__, #expr, msg);             \
      unitfail++;                                          \
    }                                                      \
  } while(0)

#define verify_memory(dynamic, check, len)                              \
  do {                                                                  \
    if(dynamic && memcmp(dynamic, check, len)) {                             \
      fprintf(stderr, "%s:%d Memory buffer mismatch size %d. '%s' is not\n", \
              __FILE__, __LINE__, len,                                  \
              hexdump((const unsigned char *)check, len));              \
      fprintf(stderr, "%s:%d the same as '%s'\n", __FILE__, __LINE__,   \
              hexdump((const unsigned char *)dynamic, len));            \
      unitfail++;                                                       \
    }                                                                   \
  } while(0)

/* fail() is for when the test case figured out by itself that a check
   proved a failure */
#define fail(msg) do {                                                 \
    fprintf(stderr, "%s:%d test failed: '%s'\n",                       \
            __FILE__, __LINE__, msg);                                  \
    unitfail++;                                                        \
  } while(0)


/* The abort macros mark the current test step as failed, and exit the test */
#define abort_if(expr, msg)                                     \
  do {                                                          \
    if(expr) {                                                  \
      fprintf(stderr, "%s:%d Abort assertion '%s' met: %s\n",   \
              __FILE__, __LINE__, #expr, msg);                  \
      unitfail++;                                               \
      goto unit_test_abort;                                     \
    }                                                           \
  } while(0)

#define abort_unless(expr, msg)                                         \
  do {                                                                  \
    if(!(expr)) {                                                       \
      fprintf(stderr, "%s:%d Abort assertion '%s' failed: %s\n",        \
              __FILE__, __LINE__, #expr, msg);                          \
      unitfail++;                                                       \
      goto unit_test_abort;                                             \
    }                                                                   \
  } while(0)

#define abort_test(msg)                                       \
  do {                                                        \
    fprintf(stderr, "%s:%d test aborted: '%s'\n",             \
            __FILE__, __LINE__, msg);                         \
    unitfail++;                                               \
    goto unit_test_abort;                                     \
  } while(0)



extern int unitfail;

#define UNITTEST_START                          \
  int test(char *arg)                           \
  {                                             \
Changes to jni/curl/tests/unit/unit1302.c.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2020, 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 https://curl.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







|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2021, 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 https://curl.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
30
31
32
33
34
35
36
37

38

39
40
41
42
43
44
45

static CURLcode unit_setup(void)
{
  int res = CURLE_OK;

  global_init(CURL_GLOBAL_ALL);
  data = curl_easy_init();
  if(!data)

    return CURLE_OUT_OF_MEMORY;

  return res;
}

static void unit_stop(void)
{
  curl_easy_cleanup(data);
  curl_global_cleanup();







|
>

>







30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47

static CURLcode unit_setup(void)
{
  int res = CURLE_OK;

  global_init(CURL_GLOBAL_ALL);
  data = curl_easy_init();
  if(!data) {
    curl_global_cleanup();
    return CURLE_OUT_OF_MEMORY;
  }
  return res;
}

static void unit_stop(void)
{
  curl_easy_cleanup(data);
  curl_global_cleanup();
Changes to jni/curl/tests/unit/unit1303.c.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2020, 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 https://curl.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







|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2021, 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 https://curl.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
29
30
31
32
33
34
35
36

37

38
39
40
41
42
43
44

static CURLcode unit_setup(void)
{
  int res = CURLE_OK;

  global_init(CURL_GLOBAL_ALL);
  data = curl_easy_init();
  if(!data)

    return CURLE_OUT_OF_MEMORY;

  return res;
}

static void unit_stop(void)
{
  curl_easy_cleanup(data);
  curl_global_cleanup();







|
>

>







29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46

static CURLcode unit_setup(void)
{
  int res = CURLE_OK;

  global_init(CURL_GLOBAL_ALL);
  data = curl_easy_init();
  if(!data) {
    curl_global_cleanup();
    return CURLE_OUT_OF_MEMORY;
  }
  return res;
}

static void unit_stop(void)
{
  curl_easy_cleanup(data);
  curl_global_cleanup();
Changes to jni/curl/tests/unit/unit1305.c.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2020, 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 https://curl.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







|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2021, 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 https://curl.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
44
45
46
47
48
49
50
51

52

53
54
55
56
57
58
59
static char *data_key;
static struct Curl_dns_entry *data_node;

static CURLcode unit_setup(void)
{
  int rc;
  data = curl_easy_init();
  if(!data)

    return CURLE_OUT_OF_MEMORY;


  rc = Curl_mk_dnscache(&hp);
  if(rc) {
    curl_easy_cleanup(data);
    curl_global_cleanup();
    return CURLE_OUT_OF_MEMORY;
  }







|
>

>







44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
static char *data_key;
static struct Curl_dns_entry *data_node;

static CURLcode unit_setup(void)
{
  int rc;
  data = curl_easy_init();
  if(!data) {
    curl_global_cleanup();
    return CURLE_OUT_OF_MEMORY;
  }

  rc = Curl_mk_dnscache(&hp);
  if(rc) {
    curl_easy_cleanup(data);
    curl_global_cleanup();
    return CURLE_OUT_OF_MEMORY;
  }
Changes to jni/curl/tests/unit/unit1600.c.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2020, 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 https://curl.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







|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2021, 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 https://curl.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
28
29
30
31
32
33
34
35

36

37
38
39
40
41
42
43

static CURLcode unit_setup(void)
{
  int res = CURLE_OK;

  global_init(CURL_GLOBAL_ALL);
  easy = curl_easy_init();
  if(!easy)

    return CURLE_OUT_OF_MEMORY;

  return res;
}

static void unit_stop(void)
{
  curl_easy_cleanup(easy);
  curl_global_cleanup();







|
>

>







28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45

static CURLcode unit_setup(void)
{
  int res = CURLE_OK;

  global_init(CURL_GLOBAL_ALL);
  easy = curl_easy_init();
  if(!easy) {
    curl_global_cleanup();
    return CURLE_OUT_OF_MEMORY;
  }
  return res;
}

static void unit_stop(void)
{
  curl_easy_cleanup(easy);
  curl_global_cleanup();
Changes to jni/curl/tests/unit/unit1605.c.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2020, 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 https://curl.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







|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2021, 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 https://curl.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
27
28
29
30
31
32
33
34

35

36
37
38
39
40
41
42

static CURLcode unit_setup(void)
{
  int res = CURLE_OK;

  global_init(CURL_GLOBAL_ALL);
  easy = curl_easy_init();
  if(!easy)

    return CURLE_OUT_OF_MEMORY;

  return res;
}

static void unit_stop(void)
{
  curl_easy_cleanup(easy);
  curl_global_cleanup();







|
>

>







27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44

static CURLcode unit_setup(void)
{
  int res = CURLE_OK;

  global_init(CURL_GLOBAL_ALL);
  easy = curl_easy_init();
  if(!easy) {
    curl_global_cleanup();
    return CURLE_OUT_OF_MEMORY;
  }
  return res;
}

static void unit_stop(void)
{
  curl_easy_cleanup(easy);
  curl_global_cleanup();
Changes to jni/curl/tests/unit/unit1606.c.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2020, 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 https://curl.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







|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2021, 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 https://curl.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
28
29
30
31
32
33
34
35

36

37
38
39
40
41
42
43

static CURLcode unit_setup(void)
{
  int res = CURLE_OK;

  global_init(CURL_GLOBAL_ALL);
  easy = curl_easy_init();
  if(!easy)

    return CURLE_OUT_OF_MEMORY;

  return res;
}

static void unit_stop(void)
{
  curl_easy_cleanup(easy);
  curl_global_cleanup();







|
>

>







28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45

static CURLcode unit_setup(void)
{
  int res = CURLE_OK;

  global_init(CURL_GLOBAL_ALL);
  easy = curl_easy_init();
  if(!easy) {
    curl_global_cleanup();
    return CURLE_OUT_OF_MEMORY;
  }
  return res;
}

static void unit_stop(void)
{
  curl_easy_cleanup(easy);
  curl_global_cleanup();
Changes to jni/curl/tests/unit/unit1607.c.
44
45
46
47
48
49
50



51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96



97
98
99
100
101
102
103
104
struct testcase {
  /* host:port:address[,address]... */
  const char *optval;

  /* lowercase host and port to retrieve the addresses from hostcache */
  const char *host;
  int port;




  /* 0 to 9 addresses expected from hostcache */
  const char *address[10];
};


/* In builds without IPv6 support CURLOPT_RESOLVE should skip over those
   addresses, so we have to do that as well. */
static const char skip = 0;
#ifdef ENABLE_IPV6
#define IPV6ONLY(x) x
#else
#define IPV6ONLY(x) &skip
#endif

/* CURLOPT_RESOLVE address parsing tests */
static const struct testcase tests[] = {
  /* spaces aren't allowed, for now */
  { "test.com:80:127.0.0.1, 127.0.0.2",
    "test.com", 80, { NULL, }
  },
  { "TEST.com:80:,,127.0.0.1,,,127.0.0.2,,,,::1,,,",
    "test.com", 80, { "127.0.0.1", "127.0.0.2", IPV6ONLY("::1"), }
  },
  { "test.com:80:::1,127.0.0.1",
    "test.com", 80, { IPV6ONLY("::1"), "127.0.0.1", }
  },
  { "test.com:80:[::1],127.0.0.1",
    "test.com", 80, { IPV6ONLY("::1"), "127.0.0.1", }
  },
  { "test.com:80:::1",
    "test.com", 80, { IPV6ONLY("::1"), }
  },
  { "test.com:80:[::1]",
    "test.com", 80, { IPV6ONLY("::1"), }
  },
  { "test.com:80:127.0.0.1",
    "test.com", 80, { "127.0.0.1", }
  },
  { "test.com:80:,127.0.0.1",
    "test.com", 80, { "127.0.0.1", }
  },
  { "test.com:80:127.0.0.1,",
    "test.com", 80, { "127.0.0.1", }
  },
  { "test.com:0:127.0.0.1",



    "test.com", 0, { "127.0.0.1", }
  },
};

UNITTEST_START
{
  int i;
  int testnum = sizeof(tests) / sizeof(struct testcase);







>
>
>



















|


|


|


|


|


|


|


|


|


>
>
>
|







44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
struct testcase {
  /* host:port:address[,address]... */
  const char *optval;

  /* lowercase host and port to retrieve the addresses from hostcache */
  const char *host;
  int port;

  /* whether we expect a permanent or non-permanent cache entry */
  bool permanent;

  /* 0 to 9 addresses expected from hostcache */
  const char *address[10];
};


/* In builds without IPv6 support CURLOPT_RESOLVE should skip over those
   addresses, so we have to do that as well. */
static const char skip = 0;
#ifdef ENABLE_IPV6
#define IPV6ONLY(x) x
#else
#define IPV6ONLY(x) &skip
#endif

/* CURLOPT_RESOLVE address parsing tests */
static const struct testcase tests[] = {
  /* spaces aren't allowed, for now */
  { "test.com:80:127.0.0.1, 127.0.0.2",
    "test.com", 80, TRUE, { NULL, }
  },
  { "TEST.com:80:,,127.0.0.1,,,127.0.0.2,,,,::1,,,",
    "test.com", 80, TRUE, { "127.0.0.1", "127.0.0.2", IPV6ONLY("::1"), }
  },
  { "test.com:80:::1,127.0.0.1",
    "test.com", 80, TRUE, { IPV6ONLY("::1"), "127.0.0.1", }
  },
  { "test.com:80:[::1],127.0.0.1",
    "test.com", 80, TRUE, { IPV6ONLY("::1"), "127.0.0.1", }
  },
  { "test.com:80:::1",
    "test.com", 80, TRUE, { IPV6ONLY("::1"), }
  },
  { "test.com:80:[::1]",
    "test.com", 80, TRUE, { IPV6ONLY("::1"), }
  },
  { "test.com:80:127.0.0.1",
    "test.com", 80, TRUE, { "127.0.0.1", }
  },
  { "test.com:80:,127.0.0.1",
    "test.com", 80, TRUE, { "127.0.0.1", }
  },
  { "test.com:80:127.0.0.1,",
    "test.com", 80, TRUE, { "127.0.0.1", }
  },
  { "test.com:0:127.0.0.1",
    "test.com", 0, TRUE, { "127.0.0.1", }
  },
  { "+test.com:80:127.0.0.1,",
    "test.com", 80, FALSE, { "127.0.0.1", }
  },
};

UNITTEST_START
{
  int i;
  int testnum = sizeof(tests) / sizeof(struct testcase);
184
185
186
187
188
189
190
191
192
193
194








195
196
197
198
199
200
201
        fprintf(stderr, "%s:%d tests[%d] failed. the retrieved port "
                "for tests[%d].address[%d] is %ld but tests[%d].port is %d.\n",
                __FILE__, __LINE__, i, i, j, port, i, tests[i].port);
        problem = true;
        break;
      }

      if(dns->timestamp != 0) {
        fprintf(stderr, "%s:%d tests[%d] failed. the timestamp is not zero. "
                "for tests[%d].address[%d\n",
                __FILE__, __LINE__, i, i, j);








        problem = true;
        break;
      }

      addr = addr->ai_next;
    }








|
|
|
|
>
>
>
>
>
>
>
>







190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
        fprintf(stderr, "%s:%d tests[%d] failed. the retrieved port "
                "for tests[%d].address[%d] is %ld but tests[%d].port is %d.\n",
                __FILE__, __LINE__, i, i, j, port, i, tests[i].port);
        problem = true;
        break;
      }

      if(dns->timestamp != 0 && tests[i].permanent) {
        fprintf(stderr, "%s:%d tests[%d] failed. the timestamp is not zero "
                "but tests[%d].permanent is TRUE\n",
                __FILE__, __LINE__, i, i);
        problem = true;
        break;
      }

      if(dns->timestamp == 0 && !tests[i].permanent) {
        fprintf(stderr, "%s:%d tests[%d] failed. the timestamp is zero "
                "but tests[%d].permanent is FALSE\n",
                __FILE__, __LINE__, i, i);
        problem = true;
        break;
      }

      addr = addr->ai_next;
    }

Changes to jni/curl/tests/unit/unit1608.c.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2020, 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 https://curl.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







|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2021, 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 https://curl.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
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
  }

  return CURLE_OK;
}

static void unit_stop(void)
{

}

UNITTEST_START
{
  int i;
  CURLcode code;
  struct Curl_addrinfo *addrhead = addrs;







|







37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
  }

  return CURLE_OK;
}

static void unit_stop(void)
{
  curl_global_cleanup();
}

UNITTEST_START
{
  int i;
  CURLcode code;
  struct Curl_addrinfo *addrhead = addrs;
Changes to jni/curl/tests/unit/unit1651.c.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 2018 - 2020, 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 https://curl.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







|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 2018 - 2021, 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 https://curl.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
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
  0xA7, 0xD7, 0xA9, 0xC4, 0xEC, 0x17, 0x17, 0x8D, 0x87, 0x70, 0x6B, 0x48, 0x88,
  0x61, 0x54, 0x4A, 0x2B, 0xB7, 0x6A, 0x12, 0x08, 0xFB,
};

UNITTEST_START
{
  CURLcode result;
  struct connectdata conn;
  const char *beg = (const char *)&cert[0];
  const char *end = (const char *)&cert[sizeof(cert)];
  struct Curl_easy *data = curl_easy_init();
  int i;
  int byte;
  if(!data)
    return 2;

  memset(&conn, 0, sizeof(struct connectdata));
  /* this is a lot of assuming, but we expect the parsing function to only
     really need the easy handle pointer */
  conn.data = data;
  result = Curl_extract_certinfo(&conn, 0, beg, end);

  fail_unless(result == CURLE_OK, "Curl_extract_certinfo returned error");

  /* a poor man's fuzzing of some initial data to make sure nothing bad
     happens */
  for(byte = 1 ; byte < 255; byte += 17) {
    for(i = 0; i < 45; i++) {
      char backup = cert[i];
      cert[i] = (unsigned char) (byte & 0xff);
      (void) Curl_extract_certinfo(&conn, 0, beg, end);
      cert[i] = backup;
    }
  }
  curl_easy_cleanup(data);
}
UNITTEST_STOP








<








<
<
<
<
|









|







342
343
344
345
346
347
348

349
350
351
352
353
354
355
356




357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
  0xA7, 0xD7, 0xA9, 0xC4, 0xEC, 0x17, 0x17, 0x8D, 0x87, 0x70, 0x6B, 0x48, 0x88,
  0x61, 0x54, 0x4A, 0x2B, 0xB7, 0x6A, 0x12, 0x08, 0xFB,
};

UNITTEST_START
{
  CURLcode result;

  const char *beg = (const char *)&cert[0];
  const char *end = (const char *)&cert[sizeof(cert)];
  struct Curl_easy *data = curl_easy_init();
  int i;
  int byte;
  if(!data)
    return 2;





  result = Curl_extract_certinfo(data, 0, beg, end);

  fail_unless(result == CURLE_OK, "Curl_extract_certinfo returned error");

  /* a poor man's fuzzing of some initial data to make sure nothing bad
     happens */
  for(byte = 1 ; byte < 255; byte += 17) {
    for(i = 0; i < 45; i++) {
      char backup = cert[i];
      cert[i] = (unsigned char) (byte & 0xff);
      (void) Curl_extract_certinfo(data, 0, beg, end);
      cert[i] = backup;
    }
  }
  curl_easy_cleanup(data);
}
UNITTEST_STOP

Changes to jni/curl/tests/unit/unit1652.c.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2020, 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 https://curl.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







|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2021, 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 https://curl.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
59
60
61
62
63
64
65
66

67

68
69
70
71
72
73
74
static CURLcode
unit_setup(void)
{
  int res = 0;

  global_init(CURL_GLOBAL_ALL);
  data = curl_easy_init();
  if(!data)

    return CURLE_OUT_OF_MEMORY;

  curl_easy_setopt(data, CURLOPT_DEBUGFUNCTION, debugf_cb);
  curl_easy_setopt(data, CURLOPT_VERBOSE, 1L);
  return CURLE_OK;
}

static void
unit_stop(void)







|
>

>







59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
static CURLcode
unit_setup(void)
{
  int res = 0;

  global_init(CURL_GLOBAL_ALL);
  data = curl_easy_init();
  if(!data) {
    curl_global_cleanup();
    return CURLE_OUT_OF_MEMORY;
  }
  curl_easy_setopt(data, CURLOPT_DEBUGFUNCTION, debugf_cb);
  curl_easy_setopt(data, CURLOPT_VERBOSE, 1L);
  return CURLE_OK;
}

static void
unit_stop(void)
Changes to jni/curl/tests/unit/unit1654.c.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 2019 - 2020, 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 https://curl.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







|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 2019 - 2021, 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 https://curl.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
129
130
131
132
133
134
135

136
137
138
139

  Curl_altsvc_save(curl, asi, outname);

  curl_easy_cleanup(curl);
  curl_global_cleanup();
  fail:
  Curl_altsvc_cleanup(&asi);

  return unitfail;
}
UNITTEST_STOP
#endif







>




129
130
131
132
133
134
135
136
137
138
139
140

  Curl_altsvc_save(curl, asi, outname);

  curl_easy_cleanup(curl);
  curl_global_cleanup();
  fail:
  Curl_altsvc_cleanup(&asi);
  curl_global_cleanup();
  return unitfail;
}
UNITTEST_STOP
#endif
Changes to jni/curl/tests/unit/unit1660.c.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 2020, 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 https://curl.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







|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 2020 - 2021, 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 https://curl.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
121
122
123
124
125
126
127


128
129


130

131
132
133
134
135
136
137
  struct stsentry *e;
  struct hsts *h = Curl_hsts_init();
  int i;
  const char *chost;
  CURL *easy;
  if(!h)
    return 1;


  easy = curl_easy_init();
  if(!easy)


    return 1;


  Curl_hsts_loadfile(easy, h, "log/input1660");

  for(i = 0; headers[i].host ; i++) {
    if(headers[i].hdr) {
      result = Curl_hsts_parse(h, headers[i].host, headers[i].hdr);








>
>

|
>
>

>







121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
  struct stsentry *e;
  struct hsts *h = Curl_hsts_init();
  int i;
  const char *chost;
  CURL *easy;
  if(!h)
    return 1;

  curl_global_init(CURL_GLOBAL_ALL);
  easy = curl_easy_init();
  if(!easy) {
    Curl_hsts_cleanup(&h);
    curl_global_cleanup();
    return 1;
  }

  Curl_hsts_loadfile(easy, h, "log/input1660");

  for(i = 0; headers[i].host ; i++) {
    if(headers[i].hdr) {
      result = Curl_hsts_parse(h, headers[i].host, headers[i].hdr);

161
162
163
164
165
166
167

168
169
170
171
    showsts(e, chost);
    deltatime++; /* another second passed */
  }

  (void)Curl_hsts_save(easy, h, "log/hsts1660");
  Curl_hsts_cleanup(&h);
  curl_easy_cleanup(easy);

  return unitfail;
}
UNITTEST_STOP
#endif







>




166
167
168
169
170
171
172
173
174
175
176
177
    showsts(e, chost);
    deltatime++; /* another second passed */
  }

  (void)Curl_hsts_save(easy, h, "log/hsts1660");
  Curl_hsts_cleanup(&h);
  curl_easy_cleanup(easy);
  curl_global_cleanup();
  return unitfail;
}
UNITTEST_STOP
#endif
Changes to jni/curl/winbuild/gen_resp_file.bat.