mirror of
https://github.com/msharov/snownews.git
synced 2024-06-25 06:57:07 +00:00
Revert 1170f79f8e
Restore openssl dependency (required by curl anyway) and use openssl to do the MD5 hashes. Remove more code obsoleted by curl; base64encode, decodechunked, and the HTTP auth code in digcalc.
This commit is contained in:
parent
e41256a853
commit
c8df7b657d
13
README.md
13
README.md
|
@ -2,7 +2,7 @@ Snownews
|
|||
========
|
||||
|
||||
Snownews is a command-line RSS feed reader, originally written by
|
||||
[Oliver Feiler](https://github.com/kouya) (@kouya).
|
||||
[Oliver Feiler](https://github.com/kouya).
|
||||
It is designed to be simple and lightweight, and integrates well with
|
||||
other command-line tools, for both generating and filtering the feeds
|
||||
it reads.
|
||||
|
@ -14,9 +14,8 @@ Features
|
|||
* Fast and very resource friendly.
|
||||
* Downloads feeds using libcurl to support a variety of URL types.
|
||||
* Uses local cache for minimal network traffic.
|
||||
* Supports cookies.
|
||||
* A help menu available throughout the program.
|
||||
* Few dependencies on external libraries; ncurses, libcurl, and libxml2.
|
||||
* Few dependencies on external libraries; ncurses, libcurl, openssl, and libxml2.
|
||||
* Import feature for OPML subscription lists.
|
||||
* Fully customizable key bindings of all program functions.
|
||||
* Type Ahead Find for quick and easy navigation.
|
||||
|
@ -32,19 +31,17 @@ You will need the following:
|
|||
- ncurses 5.0+
|
||||
- libcurl
|
||||
- libxml2
|
||||
- openssl 1.1+
|
||||
- gettext
|
||||
|
||||
Once you have the above dependencies installed:
|
||||
Once you have these dependencies installed:
|
||||
|
||||
```sh
|
||||
./configure --prefix=/usr
|
||||
make install
|
||||
```
|
||||
|
||||
By default, this will install Snownews into `/usr/local`. If you
|
||||
prefer it to go somewhere else, set the `./configure --prefix=DIR`
|
||||
parameter. `configure --help` will list other options that you may
|
||||
find interesting.
|
||||
`configure --help` will list other options that you may find interesting.
|
||||
|
||||
Localization
|
||||
------------
|
||||
|
|
|
@ -33,9 +33,6 @@
|
|||
#define SNOWNEWS_CONFIG_DIR "%s/.snownews/"
|
||||
#define SNOWNEWS_CACHE_DIR SNOWNEWS_CONFIG_DIR "cache/"
|
||||
|
||||
// Define to use experimental code
|
||||
#undef USE_UNSUPPORTED_AND_BROKEN_CODE
|
||||
|
||||
// Define to output of uname
|
||||
#undef OS
|
||||
|
||||
|
|
4
configure
vendored
4
configure
vendored
|
@ -34,9 +34,9 @@ seds=[s/^#undef \(USE_UNSUPPORTED_AND_BROKEN_CODE\)/#define \1/]
|
|||
progs="CC=gcc CC=clang CC=cc INSTALL=install MSGFMT=msgfmt"
|
||||
|
||||
# Libs found using pkg-config
|
||||
pkgs="libcurl libxml-2.0 ncurses"
|
||||
pkgs="libcurl libxml-2.0 libcrypto ncurses"
|
||||
# Default pkg flags to substitute when pkg-config is not found
|
||||
pkg_libs="-lcurl -lxml2 -lncursesw"
|
||||
pkg_libs="-lcurl -lxml2 -lcrypto -lncursesw"
|
||||
pkg_cflags="-I\/usr\/include\/libxml2"
|
||||
pkg_ldflags=""
|
||||
|
||||
|
|
103
conversions.c
103
conversions.c
|
@ -2,6 +2,7 @@
|
|||
//
|
||||
// Copyright (c) 2003-2009 Oliver Feiler <kiza@kcore.de>
|
||||
// Copyright (c) 2003-2009 Rene Puls <rpuls@gmx.net>
|
||||
// Copyright (c) 2021 Mike Sharov <msharov@users.sourceforge.net>
|
||||
//
|
||||
// Snownews is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License version 3
|
||||
|
@ -17,11 +18,12 @@
|
|||
|
||||
#include "main.h"
|
||||
#include "conversions.h"
|
||||
#include "md5.h"
|
||||
#include "ui-support.h"
|
||||
#include <iconv.h>
|
||||
#include <libxml/HTMLparser.h>
|
||||
#include <langinfo.h>
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/md5.h>
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
|
@ -342,86 +344,6 @@ char* WrapText (const char* text, unsigned width)
|
|||
return newtext;
|
||||
}
|
||||
|
||||
char* base64encode (const char* inbuf, unsigned inbuf_size)
|
||||
{
|
||||
static unsigned char const alphabet[65] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
||||
|
||||
unsigned inbuf_pos = 0, outbuf_pos = 0, outbuf_size = 0, bits = 0, char_count = 0;
|
||||
|
||||
char* outbuf = malloc (1);
|
||||
while (inbuf_pos < inbuf_size) {
|
||||
bits |= *inbuf;
|
||||
++char_count;
|
||||
if (char_count == 3) {
|
||||
outbuf = realloc (outbuf, outbuf_size + 4);
|
||||
outbuf_size += 4;
|
||||
outbuf[outbuf_pos + 0] = alphabet[bits >> 18];
|
||||
outbuf[outbuf_pos + 1] = alphabet[(bits >> 12) & 0x3f];
|
||||
outbuf[outbuf_pos + 2] = alphabet[(bits >> 6) & 0x3f];
|
||||
outbuf[outbuf_pos + 3] = alphabet[bits & 0x3f];
|
||||
outbuf_pos += 4;
|
||||
bits = 0;
|
||||
char_count = 0;
|
||||
}
|
||||
++inbuf;
|
||||
++inbuf_pos;
|
||||
bits <<= 8;
|
||||
}
|
||||
|
||||
if (char_count > 0) {
|
||||
bits <<= 16 - (8 * char_count);
|
||||
outbuf = realloc (outbuf, outbuf_size + 4);
|
||||
outbuf_size += 4;
|
||||
outbuf[outbuf_pos + 0] = alphabet[bits >> 18];
|
||||
outbuf[outbuf_pos + 1] = alphabet[(bits >> 12) & 0x3f];
|
||||
if (char_count == 1) {
|
||||
outbuf[outbuf_pos + 2] = '=';
|
||||
outbuf[outbuf_pos + 3] = '=';
|
||||
} else {
|
||||
outbuf[outbuf_pos + 2] = alphabet[(bits >> 6) & 0x3f];
|
||||
outbuf[outbuf_pos + 3] = '=';
|
||||
}
|
||||
outbuf_pos += 4;
|
||||
}
|
||||
|
||||
outbuf = realloc (outbuf, outbuf_size + 1);
|
||||
outbuf[outbuf_pos] = 0;
|
||||
|
||||
return outbuf;
|
||||
}
|
||||
|
||||
#ifdef USE_UNSUPPORTED_AND_BROKEN_CODE
|
||||
// Returns NULL on invalid input
|
||||
char* decodechunked (char* chunked, unsigned int* inputlen)
|
||||
{
|
||||
#warning ===The function decodedechunked() is not safe for binary data. Since you specifically requested it to be compiled in you probably know better what you are doing than me. Do not report bugs for this code.===
|
||||
char* orig = chunked, *dest = chunked;
|
||||
unsigned long chunklen;
|
||||
|
||||
// We can reuse the same buffer to dechunkify it:
|
||||
// the data size will never increase.
|
||||
while ((chunklen = strtoul (orig, &orig, 16))) {
|
||||
// process one more chunk:
|
||||
// skip chunk-extension part
|
||||
while (*orig && (*orig != '\r'))
|
||||
++orig;
|
||||
// skip '\r\n' after chunk length
|
||||
orig += 2;
|
||||
if ((chunklen > (chunked + *inputlen - orig)))
|
||||
// insane chunk length. Well...
|
||||
return NULL;
|
||||
memmove (dest, orig, chunklen);
|
||||
dest += chunklen;
|
||||
orig += chunklen;
|
||||
// and go to the next chunk
|
||||
}
|
||||
*dest = '\0';
|
||||
*inputlen = dest - chunked;
|
||||
|
||||
return chunked;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Remove leading whitspaces, newlines, tabs.
|
||||
// This function should be safe for working on UTF-8 strings.
|
||||
// tidyness: 0 = only suck chars from beginning of string
|
||||
|
@ -484,14 +406,21 @@ char* Hashify (const char* url)
|
|||
|
||||
char* genItemHash (const char* const* hashitems, unsigned items)
|
||||
{
|
||||
struct HashMD5 hash;
|
||||
hash_md5_init (&hash);
|
||||
EVP_MD_CTX* mdctx = EVP_MD_CTX_new();
|
||||
EVP_DigestInit (mdctx, EVP_md5());
|
||||
|
||||
for (unsigned i = 0; i < items; ++i)
|
||||
if (hashitems[i])
|
||||
hash_md5_data (&hash, hashitems[i], strlen (hashitems[i]));
|
||||
hash_md5_finish (&hash);
|
||||
char hashtext[HASH_SIZE_MD5 * 2 + 1];
|
||||
hash_md5_to_text (&hash, hashtext);
|
||||
EVP_DigestUpdate (mdctx, hashitems[i], strlen (hashitems[i]));
|
||||
|
||||
unsigned char md_value[EVP_MAX_MD_SIZE];
|
||||
unsigned md_len = 0;
|
||||
EVP_DigestFinal_ex (mdctx, md_value, &md_len);
|
||||
EVP_MD_CTX_free (mdctx);
|
||||
|
||||
char hashtext [MD5_DIGEST_LENGTH*2 + 1];
|
||||
for (unsigned i = 0; i < md_len; ++i)
|
||||
sprintf (&hashtext[2*i], "%02hhx", md_value[i]);
|
||||
return strdup (hashtext);
|
||||
}
|
||||
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
//
|
||||
// Copyright (c) 2003-2004 Oliver Feiler <kiza@kcore.de>
|
||||
// Copyright (c) 2003-2004 Rene Puls <rpuls@gmx.net>
|
||||
// Copyright (c) 2021 Mike Sharov <msharov@users.sourceforge.net>
|
||||
//
|
||||
// Snownews is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License version 3
|
||||
|
@ -20,14 +21,9 @@
|
|||
char* iconvert (const char* inbuf);
|
||||
char* UIDejunk (const char* feed_description);
|
||||
char* WrapText (const char* text, unsigned width);
|
||||
char* base64encode (const char* inbuf, unsigned int inbuf_size);
|
||||
void CleanupString (char* string, int tidyness);
|
||||
char* Hashify (const char* url);
|
||||
char* genItemHash (const char* const* hashitems, unsigned items);
|
||||
time_t ISODateToUnix (const char* ISODate);
|
||||
time_t pubDateToUnix (const char* pubDate);
|
||||
char* unixToPostDateString (time_t unixDate);
|
||||
|
||||
#ifdef USE_UNSUPPORTED_AND_BROKEN_CODE
|
||||
char* decodechunked (char* chunked, unsigned int* inputlen);
|
||||
#endif
|
||||
|
|
89
digcalc.c
89
digcalc.c
|
@ -1,89 +0,0 @@
|
|||
// This file is part of Snownews - A lightweight console RSS newsreader
|
||||
//
|
||||
// Copyright (c) 2003-2004 Oliver Feiler <kiza@kcore.de>
|
||||
//
|
||||
// Snownews is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License version 3
|
||||
// as published by the Free Software Foundation.
|
||||
//
|
||||
// Snownews is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty
|
||||
// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
// See the GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Snownews. If not, see http://www.gnu.org/licenses/.
|
||||
|
||||
// This is the sample implementation from RFC 2617.
|
||||
// The code has been modified to work with Colin Plumb's
|
||||
// MD5 implementation rather than using RSA's.
|
||||
|
||||
#include "digcalc.h"
|
||||
|
||||
// calculate H(A1) as per spec
|
||||
void DigestCalcHA1 (const char* pszAlg, const char* pszUserName, const char* pszRealm, const char* pszPassword, const char* pszNonce, const char* pszCNonce, HASHHEX SessionKey)
|
||||
{
|
||||
struct HashMD5 hash;
|
||||
hash_md5_init (&hash);
|
||||
hash_md5_data (&hash, pszUserName, strlen (pszUserName));
|
||||
hash_md5_data (&hash, ":", 1);
|
||||
hash_md5_data (&hash, pszRealm, strlen (pszRealm));
|
||||
hash_md5_data (&hash, ":", 1);
|
||||
hash_md5_data (&hash, pszPassword, strlen (pszPassword));
|
||||
hash_md5_finish (&hash);
|
||||
if (strcmp (pszAlg, "md5-sess") == 0) {
|
||||
hash_md5_init (&hash);
|
||||
hash_md5_data (&hash, hash.hash, sizeof (hash.hash));
|
||||
hash_md5_data (&hash, ":", 1);
|
||||
hash_md5_data (&hash, pszNonce, strlen (pszNonce));
|
||||
hash_md5_data (&hash, ":", 1);
|
||||
hash_md5_data (&hash, pszCNonce, strlen (pszCNonce));
|
||||
hash_md5_finish (&hash);
|
||||
}
|
||||
hash_md5_to_text (&hash, SessionKey);
|
||||
}
|
||||
|
||||
// calculate request-digest/response-digest as per HTTP Digest spec
|
||||
void DigestCalcResponse (const HASHHEX HA1, // H(A1)
|
||||
const char* pszNonce, // nonce from server
|
||||
const char* pszNonceCount, // 8 hex digits
|
||||
const char* pszCNonce, // client nonce
|
||||
const char* pszQop, // qop-value: "", "auth", "auth-int"
|
||||
const char* pszMethod, // method from the request
|
||||
const char* pszDigestUri, // requested URL
|
||||
const HASHHEX HEntity, // H(entity body) if qop="auth-int"
|
||||
HASHHEX Response // request-digest or response-digest
|
||||
)
|
||||
{
|
||||
// calculate H(A2)
|
||||
struct HashMD5 hash;
|
||||
hash_md5_init (&hash);
|
||||
hash_md5_data (&hash, pszMethod, strlen (pszMethod));
|
||||
hash_md5_data (&hash, ":", 1);
|
||||
hash_md5_data (&hash, pszDigestUri, strlen (pszDigestUri));
|
||||
if (strcmp (pszQop, "auth-int") == 0) {
|
||||
hash_md5_data (&hash, ":", 1);
|
||||
hash_md5_data (&hash, HEntity, HASHHEXLEN);
|
||||
}
|
||||
hash_md5_finish (&hash);
|
||||
HASHHEX HA2Hex;
|
||||
hash_md5_to_text (&hash, HA2Hex);
|
||||
|
||||
// calculate response
|
||||
hash_md5_init (&hash);
|
||||
hash_md5_data (&hash, HA1, HASHHEXLEN);
|
||||
hash_md5_data (&hash, ":", 1);
|
||||
hash_md5_data (&hash, pszNonce, strlen (pszNonce));
|
||||
hash_md5_data (&hash, ":", 1);
|
||||
if (*pszQop) {
|
||||
hash_md5_data (&hash, pszNonceCount, strlen (pszNonceCount));
|
||||
hash_md5_data (&hash, ":", 1);
|
||||
hash_md5_data (&hash, pszCNonce, strlen (pszCNonce));
|
||||
hash_md5_data (&hash, ":", 1);
|
||||
hash_md5_data (&hash, pszQop, strlen (pszQop));
|
||||
hash_md5_data (&hash, ":", 1);
|
||||
};
|
||||
hash_md5_data (&hash, HA2Hex, HASHHEXLEN);
|
||||
hash_md5_finish (&hash);
|
||||
hash_md5_to_text (&hash, Response);
|
||||
}
|
40
digcalc.h
40
digcalc.h
|
@ -1,40 +0,0 @@
|
|||
// This file is part of Snownews - A lightweight console RSS newsreader
|
||||
//
|
||||
// Copyright (c) 2003-2004 Oliver Feiler <kiza@kcore.de>
|
||||
//
|
||||
// Snownews is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License version 3
|
||||
// as published by the Free Software Foundation.
|
||||
//
|
||||
// Snownews is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty
|
||||
// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
// See the GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Snownews. If not, see http://www.gnu.org/licenses/.
|
||||
|
||||
// This is the sample implementation from RFC 2617.
|
||||
// The code has been modified to work with Colin Plumb's
|
||||
// MD5 implementation rather than using RSA's.
|
||||
|
||||
#pragma once
|
||||
#include "md5.h"
|
||||
|
||||
enum { HASHHEXLEN = HASH_SIZE_MD5 * 2 };
|
||||
typedef char HASHHEX[HASHHEXLEN + 1];
|
||||
|
||||
// calculate H(A1) as per HTTP Digest spec
|
||||
void DigestCalcHA1 (const char* pszAlg, const char* pszUserName, const char* pszRealm, const char* pszPassword, const char* pszNonce, const char* pszCNonce, HASHHEX SessionKey);
|
||||
|
||||
// calculate request-digest/response-digest as per HTTP Digest spec
|
||||
void DigestCalcResponse (const HASHHEX HA1, // H(A1)
|
||||
const char* pszNonce, // nonce from server
|
||||
const char* pszNonceCount, // 8 hex digits
|
||||
const char* pszCNonce, // client nonce
|
||||
const char* pszQop, // qop-value: "", "auth", "auth-int"
|
||||
const char* pszMethod, // method from the request
|
||||
const char* pszDigestUri, // requested URL
|
||||
const HASHHEX HEntity, // H(entity body) if qop="auth-int"
|
||||
HASHHEX Response // request-digest or response-digest
|
||||
);
|
|
@ -1,6 +1,7 @@
|
|||
// This file is part of Snownews - A lightweight console RSS newsreader
|
||||
//
|
||||
// Copyright (c) 2003-2004 Oliver Feiler <kiza@kcore.de>
|
||||
// Copyright (c) 2021 Mike Sharov <msharov@users.sourceforge.net>
|
||||
//
|
||||
// Snownews is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License version 3
|
||||
|
|
122
md5.c
122
md5.c
|
@ -1,122 +0,0 @@
|
|||
// This file is part of Snownews - A lightweight console RSS newsreader
|
||||
//
|
||||
// Copyright (c) 2018 Mike Sharov <msharov@users.sourceforge.net>
|
||||
//
|
||||
// Snownews is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License version 3
|
||||
// as published by the Free Software Foundation.
|
||||
//
|
||||
// Snownews is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty
|
||||
// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
// See the GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Snownews. If not, see http://www.gnu.org/licenses/.
|
||||
|
||||
#include "md5.h"
|
||||
|
||||
static inline uint32_t remove_bits (uint32_t v, uint8_t f, uint8_t n)
|
||||
{
|
||||
return ((v >> (f + n)) << f) | (v & ((1 << f) - 1));
|
||||
}
|
||||
|
||||
static inline uint32_t Rol (uint32_t v, uint32_t n)
|
||||
{
|
||||
return (v << n) | (v >> (32 - n));
|
||||
}
|
||||
|
||||
static void hash_md5_block (struct HashMD5* h)
|
||||
{
|
||||
static const uint8_t r[16] = { 7, 12, 17, 22, 5, 9, 14, 20, 4, 11, 16, 23, 6, 10, 15, 21 };
|
||||
//{{{ K table
|
||||
static const uint32_t K[64] = {
|
||||
0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee,
|
||||
0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501,
|
||||
0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be,
|
||||
0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821,
|
||||
0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa,
|
||||
0xd62f105d, 0x02441453, 0xd8a1e681, 0xe7d3fbc8,
|
||||
0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed,
|
||||
0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a,
|
||||
0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c,
|
||||
0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70,
|
||||
0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x04881d05,
|
||||
0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665,
|
||||
0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039,
|
||||
0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1,
|
||||
0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1,
|
||||
0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391
|
||||
};
|
||||
//}}}
|
||||
uint32_t a = h->hash[0], b = h->hash[1], c = h->hash[2], d = h->hash[3], f, g;
|
||||
for (uint32_t i = 0; i < 64; ++i) {
|
||||
if (i < 16) {
|
||||
f = d ^ (b & (c ^ d));
|
||||
g = i;
|
||||
} else if (i < 32) {
|
||||
f = c ^ (d & (b ^ c));
|
||||
g = (5 * i + 1) % 16;
|
||||
} else if (i < 48) {
|
||||
f = b ^ c ^ d;
|
||||
g = (3 * i + 5) % 16;
|
||||
} else {
|
||||
f = c ^ (b | ~d);
|
||||
g = (7 * i) % 16;
|
||||
}
|
||||
f = Rol (a + f + K[i] + h->words[g], r[remove_bits (i, 2, 2)]);
|
||||
g = d;
|
||||
d = c;
|
||||
c = b;
|
||||
b += f;
|
||||
a = g;
|
||||
}
|
||||
h->hash[0] += a;
|
||||
h->hash[1] += b;
|
||||
h->hash[2] += c;
|
||||
h->hash[3] += d;
|
||||
}
|
||||
|
||||
void hash_md5_init (struct HashMD5* h)
|
||||
{
|
||||
memset (h, 0, sizeof (*h));
|
||||
static const uint32_t hash_md5_initial_value[HASH_SIZE_MD5_WORDS]
|
||||
= { 0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476 };
|
||||
memcpy (h->hash, hash_md5_initial_value, sizeof (h->hash));
|
||||
}
|
||||
|
||||
void hash_md5_data (struct HashMD5* h, const void* d, size_t n)
|
||||
{
|
||||
while (n) {
|
||||
uint32_t blockOffset = h->offset % HASH_BLOCK_SIZE_MD5;
|
||||
uint32_t copied = HASH_BLOCK_SIZE_MD5 - blockOffset;
|
||||
if (copied > n)
|
||||
copied = n;
|
||||
memcpy (h->bytes + blockOffset, d, copied);
|
||||
d = (const char*) d + copied;
|
||||
n -= copied;
|
||||
h->offset += copied;
|
||||
blockOffset = (blockOffset + copied) % HASH_BLOCK_SIZE_MD5;
|
||||
if (!blockOffset)
|
||||
hash_md5_block (h);
|
||||
}
|
||||
}
|
||||
|
||||
void hash_md5_finish (struct HashMD5* h)
|
||||
{
|
||||
uint64_t size = h->offset;
|
||||
uint8_t pad = 0x80; // End message with one bit
|
||||
do {
|
||||
hash_md5_data (h, &pad, sizeof (pad));
|
||||
pad = 0; // Pad with zeroes until there is enough space for offset at the end
|
||||
} while (h->offset % HASH_BLOCK_SIZE_MD5 != HASH_BLOCK_SIZE_MD5 - sizeof (h->offset));
|
||||
h->quads[7] = size * 8; // Write size in bits at end of block
|
||||
hash_md5_block (h);
|
||||
}
|
||||
|
||||
void hash_md5_to_text (const struct HashMD5* h, char* text)
|
||||
{
|
||||
for (unsigned i = 0; i < HASH_SIZE_MD5_WORDS; ++i)
|
||||
for (unsigned j = 0; j < 4; ++j)
|
||||
sprintf (&text[i * 8 + j * 2], "%02hhx", (uint8_t) (h->hash[i] >> (j * 8)));
|
||||
}
|
39
md5.h
39
md5.h
|
@ -1,39 +0,0 @@
|
|||
// This file is part of Snownews - A lightweight console RSS newsreader
|
||||
//
|
||||
// Copyright (c) 2018 Mike Sharov <msharov@users.sourceforge.net>
|
||||
//
|
||||
// Snownews is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License version 3
|
||||
// as published by the Free Software Foundation.
|
||||
//
|
||||
// Snownews is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty
|
||||
// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
// See the GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Snownews. If not, see http://www.gnu.org/licenses/.
|
||||
|
||||
#pragma once
|
||||
#include "config.h"
|
||||
|
||||
enum {
|
||||
HASH_SIZE_MD5 = 16,
|
||||
HASH_SIZE_MD5_WORDS = HASH_SIZE_MD5 / sizeof (uint32_t),
|
||||
HASH_BLOCK_SIZE_MD5 = 64
|
||||
};
|
||||
|
||||
struct HashMD5 {
|
||||
uint32_t hash[HASH_SIZE_MD5_WORDS];
|
||||
uint64_t offset;
|
||||
union {
|
||||
uint8_t bytes[HASH_BLOCK_SIZE_MD5];
|
||||
uint32_t words[HASH_BLOCK_SIZE_MD5 / sizeof (uint32_t)];
|
||||
uint64_t quads[HASH_BLOCK_SIZE_MD5 / sizeof (uint64_t)];
|
||||
};
|
||||
};
|
||||
|
||||
void hash_md5_init (struct HashMD5* h);
|
||||
void hash_md5_data (struct HashMD5* h, const void* d, size_t n);
|
||||
void hash_md5_finish (struct HashMD5* h);
|
||||
void hash_md5_to_text (const struct HashMD5* h, char* text);
|
2
netio.c
2
netio.c
|
@ -116,7 +116,7 @@ void DownloadFeed (const char* url, struct feed* fp)
|
|||
|
||||
// Check if failed because already up-to-date
|
||||
long unmet = 0;
|
||||
if (CURLE_OK == curl_easy_getinfo (curl, CURLINFO_CONDITION_UNMET, &unmet)) {
|
||||
if (CURLE_OK == curl_easy_getinfo (curl, CURLINFO_CONDITION_UNMET, &unmet) && unmet) {
|
||||
fp->lasterror = strdup (_("Feed already up to date"));
|
||||
UIStatus (fp->lasterror, 0, 0);
|
||||
fp->problem = false;
|
||||
|
|
Loading…
Reference in New Issue
Block a user