aboutsummaryrefslogtreecommitdiffstats
path: root/src/input
diff options
context:
space:
mode:
Diffstat (limited to 'src/input')
-rw-r--r--src/input/AsyncInputStream.hxx4
-rw-r--r--src/input/InputStream.hxx4
-rw-r--r--src/input/TextInputStream.cxx20
-rw-r--r--src/input/plugins/CurlInputPlugin.cxx34
4 files changed, 54 insertions, 8 deletions
diff --git a/src/input/AsyncInputStream.hxx b/src/input/AsyncInputStream.hxx
index 7935f1a17..d1f0c3b9d 100644
--- a/src/input/AsyncInputStream.hxx
+++ b/src/input/AsyncInputStream.hxx
@@ -83,6 +83,10 @@ protected:
*/
void SetTag(Tag *_tag);
+ void ClearTag() {
+ SetTag(nullptr);
+ }
+
void Pause();
bool IsPaused() const {
diff --git a/src/input/InputStream.hxx b/src/input/InputStream.hxx
index 15c350103..81b903ba2 100644
--- a/src/input/InputStream.hxx
+++ b/src/input/InputStream.hxx
@@ -200,6 +200,10 @@ public:
return mime.empty() ? nullptr : mime.c_str();
}
+ void ClearMimeType() {
+ mime.clear();
+ }
+
gcc_nonnull_all
void SetMimeType(const char *_mime) {
assert(!ready);
diff --git a/src/input/TextInputStream.cxx b/src/input/TextInputStream.cxx
index b79f64bdc..5a8dcc065 100644
--- a/src/input/TextInputStream.cxx
+++ b/src/input/TextInputStream.cxx
@@ -38,8 +38,8 @@ TextInputStream::ReadLine()
while (true) {
auto dest = buffer.Write();
if (dest.size < 2) {
- /* end of file (or line too long): terminate
- the current line */
+ /* line too long: terminate the current
+ line */
assert(!dest.IsEmpty());
dest[0] = 0;
@@ -66,7 +66,19 @@ TextInputStream::ReadLine()
if (line != nullptr)
return line;
- if (nbytes == 0)
- return nullptr;
+ if (nbytes == 0) {
+ /* end of file: see if there's an unterminated
+ line */
+
+ dest = buffer.Write();
+ assert(!dest.IsEmpty());
+ dest[0] = 0;
+
+ auto r = buffer.Read();
+ buffer.Clear();
+ return r.IsEmpty()
+ ? nullptr
+ : r.data;
+ }
}
}
diff --git a/src/input/plugins/CurlInputPlugin.cxx b/src/input/plugins/CurlInputPlugin.cxx
index 617805e2c..1e1a46108 100644
--- a/src/input/plugins/CurlInputPlugin.cxx
+++ b/src/input/plugins/CurlInputPlugin.cxx
@@ -109,6 +109,13 @@ struct CurlInputStream final : public AsyncInputStream {
*/
void FreeEasyIndirect();
+ /**
+ * Called when a new response begins. This is used to discard
+ * headers from previous responses (for example authentication
+ * and redirects).
+ */
+ void ResponseBoundary();
+
void HeaderReceived(const char *name, std::string &&value);
size_t DataReceived(const void *ptr, size_t size);
@@ -598,6 +605,20 @@ CurlInputStream::~CurlInputStream()
}
inline void
+CurlInputStream::ResponseBoundary()
+{
+ /* undo all effects of HeaderReceived() because the previous
+ response was not applicable for this stream */
+
+ seekable = false;
+ size = UNKNOWN_SIZE;
+ ClearMimeType();
+ ClearTag();
+
+ // TODO: reset the IcyInputStream?
+}
+
+inline void
CurlInputStream::HeaderReceived(const char *name, std::string &&value)
{
if (IsSeekPending())
@@ -645,6 +666,11 @@ input_curl_headerfunction(void *ptr, size_t size, size_t nmemb, void *stream)
size *= nmemb;
const char *header = (const char *)ptr;
+ if (size > 5 && memcmp(header, "HTTP/", 5) == 0) {
+ c.ResponseBoundary();
+ return size;
+ }
+
const char *end = header + size;
char name[64];
@@ -720,10 +746,10 @@ CurlInputStream::InitEasy(Error &error)
input_curl_writefunction);
curl_easy_setopt(easy, CURLOPT_WRITEDATA, this);
curl_easy_setopt(easy, CURLOPT_HTTP200ALIASES, http_200_aliases);
- curl_easy_setopt(easy, CURLOPT_FOLLOWLOCATION, 1);
- curl_easy_setopt(easy, CURLOPT_NETRC, 1);
- curl_easy_setopt(easy, CURLOPT_MAXREDIRS, 5);
- curl_easy_setopt(easy, CURLOPT_FAILONERROR, true);
+ curl_easy_setopt(easy, CURLOPT_FOLLOWLOCATION, 1l);
+ curl_easy_setopt(easy, CURLOPT_NETRC, 1l);
+ curl_easy_setopt(easy, CURLOPT_MAXREDIRS, 5l);
+ curl_easy_setopt(easy, CURLOPT_FAILONERROR, 1l);
curl_easy_setopt(easy, CURLOPT_ERRORBUFFER, error_buffer);
curl_easy_setopt(easy, CURLOPT_NOPROGRESS, 1l);
curl_easy_setopt(easy, CURLOPT_NOSIGNAL, 1l);