source: mod_gnutls/src/gnutls_util.c @ c39ae1a

debian/masterdebian/stretch-backportsupstream
Last change on this file since c39ae1a was ef06c74, checked in by Thomas Klute <thomas2.klute@…>, 3 years ago

Compatibility code for GCC version < 5

The builtin_add_overflow() which is used for safe integer type
conversion was introduced with GCC 5, and thus unfortunately is not
available in Debian stable.

The "!defined(clang)" part in the version check is because Clang
3.8 has the builtin, but pretends to be GCC 4 as far as the GNUC
macro is concerned.

  • Property mode set to 100644
File size: 3.8 KB
Line 
1/**
2 *  Copyright 2016 Thomas Klute
3 *
4 *  Licensed under the Apache License, Version 2.0 (the "License");
5 *  you may not use this file except in compliance with the License.
6 *  You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 *  Unless required by applicable law or agreed to in writing, software
11 *  distributed under the License is distributed on an "AS IS" BASIS,
12 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 *  See the License for the specific language governing permissions and
14 *  limitations under the License.
15 */
16
17#include "gnutls_util.h"
18
19#include <apr_strings.h>
20#include <gnutls/gnutls.h>
21
22
23const char* http_post_header(apr_pool_t *p, apr_uri_t *uri,
24                             const char *content_type, const char *accept,
25                             apr_size_t size)
26{
27    return apr_psprintf(p, "POST %s HTTP/1.0\r\n"
28                        "Host: %s\r\n"
29                        "Content-Type: %s\r\n"
30                        "Accept: %s\r\n"
31                        "Content-Length: %ld\r\n\r\n",
32                        apr_uri_unparse(p, uri, APR_URI_UNP_OMITSITEPART),
33                        uri->hostname, content_type,
34                        accept != NULL ? accept : "*/*",
35                        size);
36}
37
38
39
40apr_status_t sock_send_buf(apr_socket_t *sock, const char *buf,
41                           const apr_size_t size)
42{
43    apr_status_t rv = APR_EINIT;
44    apr_size_t len = 0;
45    for (apr_size_t sent = 0; sent < size; sent += len)
46    {
47        len = size - sent;
48        rv = apr_socket_send(sock, buf + sent, &len);
49        /* API documentation for apr_socket_send(): "It is possible
50         * for both bytes to be sent and an error to be returned."
51         *
52         * So break if there was an error, unless bytes were also
53         * sent. In the latter case try to continue. */
54        if (rv != APR_SUCCESS && len == 0)
55            break;
56    }
57    return rv;
58}
59
60
61
62const char* read_line(apr_pool_t *p, apr_bucket_brigade *sockb,
63                      apr_bucket_brigade *lineb)
64{
65    apr_brigade_cleanup(lineb);
66    apr_status_t rv = apr_brigade_split_line(lineb, sockb,
67                                             APR_BLOCK_READ,
68                                             HTTP_HDR_LINE_MAX);
69    if (rv != APR_SUCCESS)
70        return NULL;
71
72    char *line;
73    apr_size_t len;
74    rv = apr_brigade_pflatten(lineb, &line, &len, p);
75    if (rv != APR_SUCCESS)
76        return NULL;
77
78    /* The last two characters on a correct header line are
79     * "\r\n". Switch \r to \0 to chomp off the line break. */
80    if (len >= 2 && line[len-1] == '\n' && line[len-2] == '\r')
81    {
82        line[len-2] = '\0';
83        return line;
84    }
85    else
86        return NULL;
87}
88
89
90
91apr_status_t datum_from_file(apr_pool_t *p, const char* filename,
92                             gnutls_datum_t *datum)
93{
94    apr_status_t rv = APR_EINIT;
95    apr_file_t *file;
96    apr_finfo_t finfo;
97    apr_size_t br = 0;
98    rv = apr_file_open(&file, filename,
99                       APR_READ | APR_BINARY, APR_OS_DEFAULT, p);
100    if (rv != APR_SUCCESS)
101        return rv;
102
103    rv = apr_file_info_get(&finfo, APR_FINFO_SIZE, file);
104    if (rv != APR_SUCCESS)
105        return rv;
106
107    datum->data = apr_palloc(p, finfo.size);
108    rv = apr_file_read_full(file, datum->data, finfo.size, &br);
109    if (rv != APR_SUCCESS)
110        return rv;
111
112    apr_file_close(file);
113
114    /* safe integer type conversion: unsigned int and apr_size_t might
115     * have different sizes */
116#if defined(__GNUC__) && __GNUC__ < 5 && !defined(__clang__)
117    if (__builtin_expect(br > UINT_MAX, 0))
118        return APR_EINVAL;
119    else
120        datum->size = (unsigned int) br;
121#else
122    if (__builtin_add_overflow(br, 0, &datum->size))
123        return APR_EINVAL;
124#endif
125
126    return rv;
127}
Note: See TracBrowser for help on using the repository browser.