~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to plugin/pbms/src/cslib/CSS3Protocol.cc

  • Committer: Brian Aker
  • Date: 2010-10-20 20:26:18 UTC
  • mfrom: (1859.2.13 refactor)
  • Revision ID: brian@tangent.org-20101020202618-9222n39lm329urv5
Merge for Brian 

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* Copyright (C) 2009 PrimeBase Technologies GmbH, Germany
 
1
/* Copyright (c) 2009 PrimeBase Technologies GmbH, Germany
2
2
 *
3
3
 * PrimeBase Media Stream for MySQL
4
4
 *
35
35
#ifdef S3_UNIT_TEST
36
36
//#define SHOW_SIGNING
37
37
// Uncomment this line to trace network action during request. Very Usefull!!
38
 
#define DEBUG_CURL
 
38
//#define DEBUG_CURL
39
39
#define DUMP_ERRORS
40
40
#endif
41
41
 
42
 
//#define DUMP_ERRORS
 
42
//#define DEBUG_CURL
 
43
#define DUMP_ERRORS
43
44
//#define SHOW_SIGNING
44
45
 
45
46
#define HEX_CHECKSUM_VALUE_SIZE (2 *CHECKSUM_VALUE_SIZE)
127
128
        
128
129
        CSMd5                   ms_md5;
129
130
        char                    ms_s3Checksum[HEX_CHECKSUM_VALUE_SIZE +1];
130
 
        bool                    ms_calculate_md5;
131
131
        
132
132
        bool                    ms_notFound; // True if the object could not be found
133
133
        bool                    ms_retry; // True if the request failed with a retry error.
142
142
        bool                    ms_throw_error; // Gets set if an exception occurs in a callback.
143
143
        bool                    ms_old_libcurl;
144
144
        char                    *ms_safe_url;
145
 
        time_t                  ms_last_modified;
146
145
        
147
146
        S3ProtocolCon():
148
147
                ms_curl(NULL),
149
148
                ms_header_list(NULL),
150
149
                ms_inputStream(NULL),
151
150
                ms_outputStream(NULL),
152
 
                ms_calculate_md5(false),
153
151
                ms_notFound(false),
154
152
                ms_retry(false),
155
153
                ms_slowDown(false),
158
156
                ms_replyStatus(0),
159
157
                ms_throw_error(false),
160
158
                ms_old_libcurl(false),
161
 
                ms_safe_url(NULL),
162
 
                ms_last_modified(0)
 
159
                ms_safe_url(NULL)
163
160
        {
164
161
        
165
162
                ms_curl = curl_easy_init();
233
230
                        //case 307: // Temporary Redirect
234
231
                                break;
235
232
                        case 404:       // Not Found
236
 
                        case 403:       // Forbidden (S3 object not found)
237
233
                                ms_notFound = true;
238
234
                                break;
239
235
                        case 500:       
371
367
        {
372
368
                enter_();
373
369
                
374
 
                if (output) {
375
 
                        push_(output);
376
 
                        THROW_CURL_IF(curl_easy_setopt(ms_curl, CURLOPT_HTTPGET, 1L));
377
 
                } else {
378
 
                        THROW_CURL_IF(curl_easy_setopt(ms_curl, CURLOPT_NOBODY, 1L));
379
 
                }
380
 
                
381
 
                // 
382
 
                THROW_CURL_IF(curl_easy_setopt(ms_curl, CURLOPT_FILETIME, 1L));
 
370
                push_(output);  
383
371
                THROW_CURL_IF(curl_easy_setopt(ms_curl, CURLOPT_HTTPHEADER, ms_header_list));
384
 
    // Ask curl to parse the Last-Modified header.  This is easier than
385
 
    // parsing it ourselves.
 
372
                THROW_CURL_IF(curl_easy_setopt(ms_curl, CURLOPT_HTTPGET, 1L));
386
373
 
387
374
                ms_outputStream = output;       
388
375
                if (curl_easy_perform(ms_curl) && !ms_throw_error) {
390
377
                        CSException::throwException(CS_CONTEXT, CS_ERR_GENERIC_ERROR, ms_curl_error);
391
378
                }
392
379
                ms_outputStream = NULL; 
393
 
                if (output){
394
 
                        release_(output);
395
 
                }
 
380
                release_(output);       
396
381
                
397
382
                if (ms_throw_error) 
398
383
                        throw_();
399
384
                
400
385
                check_reply_status();
401
 
                curl_easy_getinfo(ms_curl, CURLINFO_FILETIME, &ms_last_modified);
402
386
                exit_();                
403
387
        }
404
388
        
405
 
        inline void ms_execute_put_request(CSInputStream *input, off64_t size)
 
389
        inline void ms_execute_put_request(CSInputStream *input, off64_t size, Md5Digest *digest)
406
390
        {
407
391
                enter_();
408
392
                
430
414
                
431
415
                check_reply_status();
432
416
                
433
 
                if (ms_calculate_md5) {
434
 
                        // If the data was not sent with an md5 checksum then verify
435
 
                        // the server's md5 value with the one calculated during the send.
436
 
                        char checksum[HEX_CHECKSUM_VALUE_SIZE +1];
437
 
                        Md5Digest digest;
438
 
                        
439
 
                        ms_md5.md5_get_digest(&digest);
440
 
                        cs_bin_to_hex(HEX_CHECKSUM_VALUE_SIZE, checksum, CHECKSUM_VALUE_SIZE, digest.val);
441
 
                        checksum[HEX_CHECKSUM_VALUE_SIZE] = 0;
442
 
                        
443
 
                        cs_strToUpper(ms_s3Checksum);
444
 
                        if (strcmp(checksum, ms_s3Checksum)) {
445
 
                                // The request should be restarted in this case.
446
 
                                ms_retry = true;
447
 
                                CSException::logException(CS_CONTEXT, CS_ERR_CHECKSUM_ERROR, "Calculated checksum did not match S3 checksum");
448
 
                        }
 
417
                // Check that the checksums agree
 
418
                char checksum[HEX_CHECKSUM_VALUE_SIZE +1];
 
419
                
 
420
                ms_md5.md5_digest(digest);
 
421
                cs_bin_to_hex(HEX_CHECKSUM_VALUE_SIZE, checksum, CHECKSUM_VALUE_SIZE, digest->val);
 
422
                checksum[HEX_CHECKSUM_VALUE_SIZE] = 0;
 
423
                
 
424
                cs_strToUpper(ms_s3Checksum);
 
425
                if (strcmp(checksum, ms_s3Checksum)) {
 
426
                        // The request should be restarted in this case.
 
427
                        ms_retry = true;
 
428
                        CSException::logException(CS_CONTEXT, CS_ERR_CHECKSUM_ERROR, "Calculated checksum did not match S3 checksum");
449
429
                }
450
 
 
 
430
                
451
431
                exit_();                
452
432
        }
453
433
        
463
443
        s3_server(NULL),
464
444
        s3_public_key(NULL),
465
445
        s3_private_key(NULL),
466
 
        s3_maxRetries(5),
467
 
        s3_sleepTime(0)
 
446
        s3_maxRetrys(5)
468
447
{
469
448
        new_(s3_server, CSStringBuffer());
470
449
        s3_server->append("s3.amazonaws.com/");
545
524
// CURL callback functions:
546
525
////////////////////////////
547
526
//----------------------
548
 
//-----------------
549
 
static bool try_ReadStream(CSThread *self, S3ProtocolCon *con, unsigned char *ptr, size_t buffer_size, size_t *data_sent)
550
 
{
551
 
        volatile bool rtc = true;
552
 
        try_(a) {
553
 
                *data_sent = con->ms_inputStream->read((char*)ptr, buffer_size);
554
 
                if (*data_sent <= con->ms_data_size) {
555
 
                        con->ms_data_size -= *data_sent;
556
 
                        if (*data_sent)
557
 
                                con->ms_md5.md5_append(ptr, *data_sent); // Calculating the checksum for the data sent.
558
 
                } else if (*data_sent > con->ms_data_size) 
559
 
                        CSException::RecordException(CS_CONTEXT, CS_ERR_GENERIC_ERROR, "Blob larger than expected.");
560
 
                else if (con->ms_data_size && !*data_sent)
561
 
                        CSException::RecordException(CS_CONTEXT, CS_ERR_GENERIC_ERROR, "Blob smaller than expected.");
562
 
                rtc = false;
563
 
        }
564
 
        
565
 
        catch_(a)
566
 
        cont_(a);
567
 
        return rtc;
568
 
}
569
 
 
570
 
//----------------------
571
527
static size_t send_callback(void *ptr, size_t objs, size_t obj_size, void *v_con)
572
528
{
573
529
        S3ProtocolCon *con = (S3ProtocolCon*) v_con;
577
533
                return 0;
578
534
                
579
535
        enter_();
580
 
        if (try_ReadStream(self, con, (unsigned char*)ptr, buffer_size, &data_sent)) {
581
 
                con->ms_throw_error = true;
582
 
                data_sent = (size_t)-1;
 
536
        try_(a) {
 
537
                data_sent = con->ms_inputStream->read((char*)ptr, buffer_size);
 
538
                if (data_sent <= con->ms_data_size) {
 
539
                        con->ms_data_size -= data_sent;
 
540
                        if (data_sent)
 
541
                                con->ms_md5.md5_append((u_char*)ptr, data_sent); // Calculating the checksum for the data sent.
 
542
                } else if (data_sent > con->ms_data_size) 
 
543
                        CSException::RecordException(CS_CONTEXT, CS_ERR_GENERIC_ERROR, "Blob larger than expected.");
 
544
                else if (con->ms_data_size && !data_sent)
 
545
                        CSException::RecordException(CS_CONTEXT, CS_ERR_GENERIC_ERROR, "Blob smaller than expected.");
583
546
        }
584
 
        
585
 
        return_(data_sent);
 
547
        catch_(a);
 
548
        con->ms_throw_error = true;
 
549
        data_sent = SIZE_MAX;
 
550
        
 
551
        cont_(a);
 
552
        
 
553
        return data_sent;
586
554
}
 
555
//----------------------
 
556
static size_t receive_data(void *vptr, size_t objs, size_t obj_size, void *v_con)
 
557
{
 
558
        S3ProtocolCon *con = (S3ProtocolCon*) v_con;
 
559
        size_t data_len = objs * obj_size;
587
560
 
588
 
//-----------------
589
 
static bool try_WriteStream(CSThread *self, S3ProtocolCon *con, char *ptr, size_t data_len)
590
 
{
591
 
        volatile bool rtc = true;
 
561
        enter_();
592
562
        try_(a) {
593
563
                if (con->ms_replyStatus >= 400) { // Collect the error reply.
594
564
                        if (!con->ms_errorReply)
595
565
                                con->ms_errorReply = new CSStringBuffer(50);            
596
 
                        con->ms_errorReply->append(ptr, data_len);
 
566
                        con->ms_errorReply->append((char*)vptr, data_len);
597
567
                } else if (     con->ms_outputStream)
598
 
                        con->ms_outputStream->write(ptr, data_len);
599
 
                rtc = false;
 
568
                        con->ms_outputStream->write((char*)vptr, data_len);
600
569
        }
 
570
        catch_(a);
 
571
        con->ms_throw_error = true;
 
572
        data_len = SIZE_MAX; 
601
573
        
602
 
        catch_(a)
603
574
        cont_(a);
604
 
        return rtc;
605
 
}
606
 
 
607
 
//----------------------
608
 
static size_t receive_data(void *vptr, size_t objs, size_t obj_size, void *v_con)
609
 
{
610
 
        S3ProtocolCon *con = (S3ProtocolCon*) v_con;
611
 
        size_t data_len = objs * obj_size;
612
 
 
613
 
        enter_();
614
 
        if (try_WriteStream(self, con, (char*)vptr, data_len)) {
615
 
                con->ms_throw_error = true;
616
 
                data_len = (size_t)-1;
617
 
        }
618
 
 
619
575
        return_(data_len);      
620
576
}
621
577
 
622
578
#define IS_REDIRECT(s) ((s >= 300) && (s < 400))
623
579
//----------------------
624
 
static bool try_addHeader(CSThread *self, S3ProtocolCon *con, char *name, uint32_t name_len, char *value, uint32_t value_len)
625
 
{
626
 
        try_(a) {
627
 
                con->ms_reply_headers.addHeader(name, name_len, value, value_len);
628
 
                return false;
629
 
        }
630
 
        
631
 
        catch_(a);
632
 
        cont_(a);
633
 
        return true;
634
 
}
635
 
 
636
 
//----------------------
637
580
static size_t receive_header(void *header, size_t objs, size_t obj_size, void *v_con)
638
581
{
639
582
        S3ProtocolCon *con = (S3ProtocolCon*) v_con;
641
584
        char *end, *ptr = (char*) header, *name, *value = NULL;
642
585
        uint32_t name_len =0, value_len = 0;
643
586
        
 
587
        CLOBBER_PROTECT(con);
 
588
        CLOBBER_PROTECT(size);
 
589
        CLOBBER_PROTECT(ptr);
 
590
        CLOBBER_PROTECT(value);
 
591
        CLOBBER_PROTECT(value_len);
 
592
        CLOBBER_PROTECT(name_len);
 
593
 
644
594
//printf(       "receive_header: %s\n", ptr);
645
595
        end = ptr + size;
646
596
        if (*(end -2) == '\r' && *(end -1) == '\n')
688
638
        while (value[value_len-1] == ' ') value_len--;
689
639
        
690
640
        if (!strncasecmp(name, "ETag", 4)) {
691
 
                if (*value == '"') {
692
 
                        value++; value_len -=2; // Strip quotation marks from checksum string.
693
 
                }
 
641
                value++; value_len -=2; // Strip quotation marks from checksum string.
694
642
                if (value_len == HEX_CHECKSUM_VALUE_SIZE) {
695
643
                        memcpy(con->ms_s3Checksum, value, value_len);
696
644
                        con->ms_s3Checksum[value_len] = 0;
698
646
        }
699
647
        
700
648
        enter_();
701
 
        if (try_addHeader(self, con, name, name_len, value, value_len)) {
702
 
                con->ms_throw_error = true;
703
 
                size = (size_t)-1;
 
649
        try_(a) {
 
650
                con->ms_reply_headers.addHeader(name, name_len, value, value_len);
704
651
        }
 
652
        
 
653
        catch_(a);
 
654
        con->ms_throw_error = true;
 
655
        size = (size_t)-1;
 
656
                
 
657
        cont_(a);
705
658
        return_(size);
706
659
}
707
660
 
763
716
        con_data->ms_execute_delete_request();
764
717
        
765
718
        if (con_data->ms_retry) {
766
 
                if (retry_count == s3_maxRetries) {
 
719
                if (retry_count == s3_maxRetrys) {
767
720
                        CSException::throwException(CS_CONTEXT, CS_ERR_GENERIC_ERROR, "S3 operation aborted after max retries.");
768
721
                }
769
 
        //printf("RETRY: s3_delete()\n");
 
722
        printf("RETRY: s3_delete()\n");
770
723
                retry_count++;
771
 
                self->sleep(s3_sleepTime);
772
724
                goto retry;
773
725
        }
774
726
        
863
815
        }
864
816
        
865
817
        if (con_data->ms_retry) {
866
 
                if (retry_count == s3_maxRetries) {
 
818
                if (retry_count == s3_maxRetrys) {
867
819
                        CSException::throwException(CS_CONTEXT, CS_ERR_GENERIC_ERROR, "S3 operation aborted after max retries.");
868
820
                }
869
 
        //printf("RETRY: s3_copy()\n");
 
821
        printf("RETRY: s3_copy()\n");
870
822
                retry_count++;
871
 
                self->sleep(s3_sleepTime);
872
823
                goto retry;
873
824
        }
874
825
        
880
831
 
881
832
 
882
833
//-------------------------------
883
 
CSVector *CSS3Protocol::s3_receive(CSOutputStream *output, const char *bucket, const char *key, bool *found, S3RangePtr range, time_t *last_modified)
 
834
CSVector *CSS3Protocol::s3_receive(CSOutputStream *output, const char *bucket, const char *key, bool *found)
884
835
{
885
836
        CSStringBuffer *s3_buffer;
886
837
    char date[64];
888
839
        uint32_t retry_count = 0;
889
840
        S3ProtocolCon *con_data;
890
841
        CSVector *replyHeaders;
891
 
        CSString *range_header = NULL;
892
 
        const char *http_op;
893
842
 
894
843
        enter_();
895
844
 
896
 
        if (output) {
897
 
                push_(output);
898
 
                http_op = "GET";
899
 
        } else
900
 
                http_op = "HEAD";
 
845
        push_(output);
901
846
 
902
847
        new_(s3_buffer, CSStringBuffer());
903
848
        push_(s3_buffer);
927
872
        s3_buffer->append(date);
928
873
        con_data->ms_setHeader(s3_buffer->getCString());
929
874
 
930
 
        if (range) {
931
 
                char buffer[80];
932
 
                snprintf(buffer, 80,"Range: bytes=%"PRIu64"-%"PRIu64, range->startByte, range->endByte);
933
 
 
934
 
                range_header = CSString::newString(buffer);
935
 
        }
936
875
        // Create the authentication signature and add the 'Authorization' header
937
 
        if (range_header)
938
 
                con_data->ms_setHeader(range_header->getCString());
939
 
        signed_str = s3_getSignature(http_op, NULL, NULL, date, bucket, key, NULL);
 
876
        signed_str = s3_getSignature("GET", NULL, NULL, date, bucket, key);
940
877
        push_(signed_str);
941
878
        s3_buffer->setLength(0);
942
879
        s3_buffer->append("Authorization: AWS ");       
946
883
        release_(signed_str); signed_str = NULL;
947
884
        con_data->ms_setHeader(s3_buffer->getCString());
948
885
        
949
 
        if (output) output->retain();
950
 
        con_data->ms_execute_get_request(output);
 
886
        con_data->ms_execute_get_request(RETAIN(output));
951
887
        
952
888
        if (con_data->ms_retry) {
953
 
                if (retry_count == s3_maxRetries) {
 
889
                if (retry_count == s3_maxRetrys) {
954
890
                        CSException::throwException(CS_CONTEXT, CS_ERR_GENERIC_ERROR, "S3 operation aborted after max retries.");
955
891
                }
956
 
        //printf("RETRY: s3_receive()\n");
 
892
        printf("RETRY: s3_receive()\n");
957
893
                retry_count++;
958
894
                output->reset();
959
 
                self->sleep(s3_sleepTime);
960
895
                goto retry;
961
896
        }
962
897
        
963
 
        if (last_modified)
964
 
                *last_modified = con_data->ms_last_modified;
965
898
        *found = !con_data->ms_notFound;
966
899
        replyHeaders = con_data->ms_reply_headers.takeHeaders();
967
900
        release_(con_data);
968
901
        release_(s3_buffer);
969
 
        if (output)
970
 
                release_(output);
 
902
        release_(output);
971
903
        
972
904
        return_(replyHeaders);
973
905
}
1068
1000
        s3_buffer->append(bucket);
1069
1001
        s3_buffer->append("."); 
1070
1002
        s3_buffer->append(s3_server->getCString());
1071
 
//s3_buffer->append("/");       
1072
 
//s3_buffer->append(bucket);
1073
1003
        if (key_prefix) {
1074
1004
                s3_buffer->append("?prefix=");
1075
1005
                s3_buffer->append(key_prefix);
1105
1035
        con_data->ms_execute_get_request(RETAIN(output));
1106
1036
        
1107
1037
        if (con_data->ms_retry) {
1108
 
                if (retry_count == s3_maxRetries) {
 
1038
                if (retry_count == s3_maxRetrys) {
1109
1039
                        CSException::throwException(CS_CONTEXT, CS_ERR_GENERIC_ERROR, "S3 operation aborted after max retries.");
1110
1040
                }
1111
 
        //printf("RETRY: s3_list()\n");
 
1041
        printf("RETRY: s3_list()\n");
1112
1042
                retry_count++;
1113
1043
                output->reset();
1114
 
                self->sleep(s3_sleepTime);
1115
1044
                goto retry;
1116
1045
        }
1117
1046
        
1148
1077
        CSStringBuffer *s3_buffer;
1149
1078
    char date[64];
1150
1079
        CSString *signed_str;
 
1080
        Md5Digest dummy_digest;
1151
1081
        uint32_t retry_count = 0;
1152
1082
        S3ProtocolCon *con_data;
1153
1083
        CSVector *replyHeaders;
1154
 
        char checksum[32], *md5 = NULL;
1155
1084
 
1156
1085
        enter_();
1157
1086
        push_(input);
1161
1090
 
1162
1091
        new_(con_data, S3ProtocolCon());
1163
1092
        push_(con_data);
 
1093
 
 
1094
        if (!digest)
 
1095
                digest = &dummy_digest;
1164
1096
                
1165
1097
        if (!content_type)
1166
1098
                content_type = "binary/octet-stream";
1198
1130
        s3_buffer->append(content_type);
1199
1131
        con_data->ms_setHeader(s3_buffer->getCString());
1200
1132
                
1201
 
        if (digest) {
1202
 
                // Add the Md5 checksum header
1203
 
                md5 = checksum;
1204
 
                memset(checksum, 0, 32);
1205
 
                base64Encode(digest->val, 16, checksum, 32);
1206
 
                
1207
 
                s3_buffer->setLength(0);
1208
 
                s3_buffer->append("Content-MD5: ");     
1209
 
                s3_buffer->append(checksum);
1210
 
                con_data->ms_setHeader(s3_buffer->getCString());                
1211
 
                con_data->ms_calculate_md5 = false;
1212
 
        } else 
1213
 
                con_data->ms_calculate_md5 = true;
1214
 
        
1215
 
 
1216
1133
        // Create the authentication signature and add the 'Authorization' header
1217
1134
        if (!s3Authorization)
1218
 
                signed_str = s3_getSignature("PUT", md5, content_type, date, bucket, key);
 
1135
                signed_str = s3_getSignature("PUT", NULL, content_type, date, bucket, key);
1219
1136
        else
1220
1137
                signed_str = CSString::newString(s3Authorization);
1221
1138
        push_(signed_str);
1227
1144
        release_(signed_str); signed_str = NULL;
1228
1145
        con_data->ms_setHeader(s3_buffer->getCString());
1229
1146
        
1230
 
        con_data->ms_execute_put_request(RETAIN(input), size);
 
1147
        con_data->ms_execute_put_request(RETAIN(input), size, digest);
1231
1148
        
1232
1149
        if (con_data->ms_retry) {
1233
 
                if (retry_count == s3_maxRetries) {
 
1150
                if (retry_count == s3_maxRetrys) {
1234
1151
                        CSException::throwException(CS_CONTEXT, CS_ERR_GENERIC_ERROR, "S3 operation aborted after max retries.");
1235
1152
                }
1236
 
        //printf("RETRY: s3_send()\n");
 
1153
        printf("RETRY: s3_send()\n");
1237
1154
                retry_count++;
1238
1155
                input->reset();
1239
 
                self->sleep(s3_sleepTime);
1240
1156
                goto retry;
1241
1157
        }
1242
1158
        
1243
1159
        replyHeaders = con_data->ms_reply_headers.takeHeaders();
1244
 
 
1245
1160
        release_(con_data);
1246
1161
        release_(s3_buffer);
1247
1162
        release_(input);
1296
1211
        printf("Delete object:\n\t%s d <bucket> <object_key>\n", cmd);
1297
1212
        printf("Delete all object with a given prefix:\n\t%s D <bucket> <object_prefix>\n", cmd);
1298
1213
        printf("Get object, data will be written to 'prottest.out':\n\t%s g <bucket> <object_key> <timeout>\n", cmd);
1299
 
        printf("Get object header only:\n\t%s h <bucket> <object_key> <timeout>\n", cmd);
1300
1214
        printf("Put (Upload) an object:\n\t%s p <bucket> <object_key> <file>\n", cmd);
1301
1215
        printf("List objects in the bucket:\n\t%s l <bucket> [<object_prefix> [max_list_size]]\n", cmd);
1302
1216
        printf("Copy object:\n\t%s c <src_bucket> <src_object_key> <dst_bucket> <dst_object_key> \n", cmd);
1326
1240
        CSThread *main_thread;
1327
1241
        const char *pub_key;
1328
1242
        const char *priv_key;
1329
 
        const char *server;
1330
1243
        CSS3Protocol *prot = NULL;
1331
1244
        
1332
1245
        if (argc < 3) {
1352
1265
                new_(prot, CSS3Protocol());
1353
1266
                push_(prot);
1354
1267
                
1355
 
                server = getenv("S3_SERVER");
1356
 
                if ((server == NULL) || (*server == 0))
1357
 
                        server = "s3.amazonaws.com/";
1358
 
                prot->s3_setServer(server);
 
1268
                prot->s3_setServer("s3.amazonaws.com/");
1359
1269
                prot->s3_setPublicKey(pub_key);
1360
1270
                prot->s3_setPrivateKey(priv_key);
1361
1271
                
1398
1308
                                
1399
1309
                                break;
1400
1310
                        case 'g':  // Get the object
1401
 
                                if ((argc == 4) || (argc == 6)) {
 
1311
                                if (argc == 4) {
1402
1312
                                        CSFile *output; 
1403
1313
                                        CSVector *headers;
1404
1314
                                        bool found;                             
1405
 
                                        S3RangeRec *range_ptr = NULL, range =   {0,0};          
1406
 
                                        
1407
 
                                        if (argc == 6) {
1408
 
                                                range.startByte = atoi(argv[4]);
1409
 
                                                range.endByte = atoi(argv[5]);
1410
 
                                                range_ptr = &range;
1411
 
                                        }
1412
1315
                                        
1413
1316
                                        output = CSFile::newFile("prottest.out");
1414
1317
                                        push_(output);
1415
1318
                                        output->open(CSFile::CREATE | CSFile::TRUNCATE);
1416
 
                                        headers = prot->s3_receive(output->getOutputStream(), argv[2], argv[3], &found, range_ptr);
 
1319
                                        headers = prot->s3_receive(output->getOutputStream(), argv[2], argv[3], &found);
1417
1320
                                        if (!found)
1418
1321
                                                printf("%s/%s could not be found.\n", argv[2], argv[3]);
1419
1322
                                                
1425
1328
                                
1426
1329
                                break;
1427
1330
                                
1428
 
                        case 'h':  // Get the object header
1429
 
                                if (argc == 4) {
1430
 
                                        CSVector *headers;
1431
 
                                        bool found;     
1432
 
                                        S3RangeRec range =      {0,0};          
1433
 
                                        
1434
 
                                        headers = prot->s3_receive(NULL, argv[2], argv[3], &found);
1435
 
                                        if (!found)
1436
 
                                                printf("%s/%s could not be found.\n", argv[2], argv[3]);
1437
 
                                                
1438
 
                                        dump_headers(headers);
1439
 
                                                
1440
 
                                } else
1441
 
                                        printf("Bad command: h <bucket> <object_key>\n");
1442
 
                                
1443
 
                                break;
1444
 
                                
1445
1331
                        case 'p':  // Put (Upload) the object
1446
1332
                                if (argc == 5) {
1447
1333
                                        CSFile *input;
1448
 
                                        Md5Digest digest;
1449
1334
                                        CSVector *headers;
1450
1335
                                        
1451
1336
                                        input = CSFile::newFile(argv[4]);
1452
1337
                                        push_(input);
1453
1338
                                        input->open(CSFile::READONLY);
1454
 
                                        input->md5Digest(&digest);
1455
 
                                        headers = prot->s3_send(input->getInputStream(), argv[2], argv[3], input->myFilePath->getSize(), NULL, &digest);
 
1339
                                        headers = prot->s3_send(input->getInputStream(), argv[2], argv[3], input->myFilePath->getSize());
1456
1340
                                        dump_headers(headers);
1457
1341
                                        release_(input);
1458
1342
                                } else