CGem/src/gemlib.c

160 lines
2.8 KiB
C

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/wait.h>
#include <openssl/bio.h>
#include <openssl/err.h>
#include <openssl/ssl.h>
#include "gemlib.h"
Request *examineRequest(const char *request_content)
{
int i = 0, len = 0, len_req = strlen(request_content);
Request *request = malloc(sizeof(Request));
if (request == NULL)
return NULL;
memset(request, 0, sizeof(Request));
strcpy(request->request_content, request_content);
strcat(request->request_content, "\r\n");
/* We are trying to determine the protocol */
while (i <= len_req - 3)
if (request_content[i] != ':' || request_content[i + 1] != '/' || request_content[i + 2] != '/')
{
i++;
len++;
}
else
{
strncpy(request->scheme, request_content + i - len, len);
break;
}
/* If no protocol found error */
if (request->scheme[0] == 0)
{
free(request);
return NULL;
}
/* We skip the :// */
i += 3;
len = 0;
/* We try to determine hostname + port */
while (i < len_req && request_content[i] != '/')
{
i++;
len++;
}
strncpy(request->hostname, request_content + i - len, len);
/* if no hostname error */
if (request->hostname[0] == 0)
{
free(request);
return NULL;
}
/* now fill path in request struct */
strncpy(request->path, request_content + i, strlen(request_content) - i);
/* if path is empty, so path is root */
if (request->path[0] == 0)
strcpy(request->path, "/");
return request;
}
void requestTheServer(Request *request, FILE *answerFile)
{
const SSL_METHOD *method = TLS_client_method();
SSL *ssl = NULL;
SSL_CTX *ctx = NULL;
BIO *bio = NULL;
int n;
if (method == NULL)
{
perror("Method");
ERR_print_errors_fp(stderr);
exit(1);
}
ctx = SSL_CTX_new(method);
if (ctx == NULL)
{
perror("ctx");
ERR_print_errors_fp(stderr);
exit(2);
}
bio = BIO_new_ssl_connect(ctx);
if (bio == NULL)
{
perror("bio");
ERR_print_errors_fp(stderr);
SSL_CTX_free(ctx);
exit(3);
}
BIO_get_ssl(bio, &ssl);
SSL_set_mode(ssl, SSL_MODE_AUTO_RETRY);
BIO_set_conn_hostname(bio, request->hostname);
if (BIO_do_connect(bio) <= 0)
{
BIO_free_all(bio);
SSL_CTX_free(ctx);
perror("bio connect");
ERR_print_errors_fp(stderr);
exit(4);
}
BIO_puts(bio, request->request_content);
while (1)
{
memset(request->answer_content, 0, sizeof(request->answer_content));
n = BIO_read(bio, request->answer_content, 1024);
if (n <= 0) break;
fprintf(answerFile, "%s", request->answer_content);
}
BIO_free_all(bio);
SSL_CTX_free(ctx);
}
void initSSL (void)
{
SSL_load_error_strings();
SSL_library_init();
}
int getGem (const char *URL, FILE *answerFile)
{
Request *request = examineRequest(URL);
initSSL();
if (request == NULL)
{
printf("error during url parsing\n");
return 1;
}
requestTheServer(request, answerFile);
free(request);
return 0;
}