1
0
mirror of https://github.com/rkd77/elinks.git synced 2024-12-04 14:46:47 -05:00

[xhr] Implemented getAllResponseHeaders

This commit is contained in:
Witold Filipczyk 2022-09-25 19:40:35 +02:00
parent c52f0cecdd
commit 5657e59006

View File

@ -51,7 +51,10 @@
#include "viewer/text/link.h" #include "viewer/text/link.h"
#include "viewer/text/vs.h" #include "viewer/text/vs.h"
#include <iostream>
#include <map> #include <map>
#include <sstream>
#include <vector>
const unsigned short UNSENT = 0; const unsigned short UNSENT = 0;
const unsigned short OPENED = 1; const unsigned short OPENED = 1;
@ -92,14 +95,25 @@ static bool xhr_set_property_responseType(JSContext *cx, unsigned int argc, JS::
static bool xhr_set_property_timeout(JSContext *cx, unsigned int argc, JS::Value *vp); static bool xhr_set_property_timeout(JSContext *cx, unsigned int argc, JS::Value *vp);
static bool xhr_set_property_withCredentials(JSContext *cx, unsigned int argc, JS::Value *vp); static bool xhr_set_property_withCredentials(JSContext *cx, unsigned int argc, JS::Value *vp);
static char *normalize(char *value);
enum { enum {
GET = 1, GET = 1,
HEAD = 2, HEAD = 2,
POST = 3 POST = 3
}; };
struct classcomp {
bool operator() (const std::string& lhs, const std::string& rhs) const
{
return strcasecmp(lhs.c_str(), rhs.c_str()) < 0;
}
};
struct xhr { struct xhr {
std::map<std::string, std::string> requestHeaders; std::map<std::string, std::string> requestHeaders;
std::map<std::string, std::string, classcomp> responseHeaders;
struct download download; struct download download;
struct ecmascript_interpreter *interpreter; struct ecmascript_interpreter *interpreter;
JS::RootedObject thisval; JS::RootedObject thisval;
@ -149,6 +163,7 @@ xhr_finalize(JSFreeOp *op, JSObject *xhr_obj)
mem_free_if(xhr->responseURL); mem_free_if(xhr->responseURL);
mem_free_if(xhr->statusText); mem_free_if(xhr->statusText);
mem_free_if(xhr->upload); mem_free_if(xhr->upload);
xhr->responseHeaders.clear();
xhr->requestHeaders.clear(); xhr->requestHeaders.clear();
mem_free(xhr); mem_free(xhr);
@ -268,10 +283,28 @@ xhr_getAllResponseHeaders(JSContext *ctx, unsigned int argc, JS::Value *rval)
fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__);
#endif #endif
JS::CallArgs args = JS::CallArgsFromVp(argc, rval); JS::CallArgs args = JS::CallArgsFromVp(argc, rval);
// JS::RootedObject hobj(ctx, &args.thisv().toObject()); JS::RootedObject hobj(ctx, &args.thisv().toObject());
/// TODO JS::Realm *comp = js::GetContextRealm(ctx);
args.rval().setUndefined(); if (!comp) {
#ifdef ECMASCRIPT_DEBUG
fprintf(stderr, "%s:%s %d\n", __FILE__, __FUNCTION__, __LINE__);
#endif
return false;
}
struct ecmascript_interpreter *interpreter = (struct ecmascript_interpreter *)JS::GetRealmPrivate(comp);
struct xhr *xhr = (struct xhr *)(JS::GetPrivate(hobj));
struct view_state *vs = interpreter->vs;
if (!xhr) {
return false;
}
std::string output = "";
for (auto h: xhr->responseHeaders) {
output += h.first + ": " + h.second + "\r\n";
}
args.rval().setString(JS_NewStringCopyZ(ctx, output.c_str()));
return true; return true;
} }
@ -411,6 +444,7 @@ xhr_open(JSContext *ctx, unsigned int argc, JS::Value *rval)
xhr->isSend = false; xhr->isSend = false;
xhr->isUpload = false; xhr->isUpload = false;
xhr->requestHeaders.clear(); xhr->requestHeaders.clear();
xhr->responseHeaders.clear();
mem_free_set(&xhr->response, NULL); mem_free_set(&xhr->response, NULL);
mem_free_set(&xhr->responseText, NULL); mem_free_set(&xhr->responseText, NULL);
@ -476,6 +510,32 @@ onreadystatechange_run(void *data)
} }
} }
static const std::vector<std::string>
explode(const std::string& s, const char& c)
{
std::string buff{""};
std::vector<std::string> v;
bool found = false;
for (auto n:s) {
if (found || (n != c)) {
buff += n;
}
else if (!found && n == c && buff != "") {
v.push_back(buff);
buff = "";
found = true;
}
}
if (buff != "") {
v.push_back(buff);
}
return v;
}
static void static void
xhr_loading_callback(struct download *download, struct xhr *xhr) xhr_loading_callback(struct download *download, struct xhr *xhr)
{ {
@ -493,11 +553,62 @@ xhr_loading_callback(struct download *download, struct xhr *xhr)
if (!fragment) { if (!fragment) {
return; return;
} }
if (cached->head) {
std::istringstream headers(cached->head);
std::string http;
int status;
std::string statusText;
std::string line;
std::getline(headers, line);
std::istringstream linestream(line);
linestream >> http >> status >> statusText;
while (1) {
std::getline(headers, line);
if (line.empty()) {
break;
}
std::vector<std::string> v = explode(line, ':');
if (v.size() == 2) {
char *value = stracpy(v[1].c_str());
if (!value) {
continue;
}
char *header = stracpy(v[0].c_str());
if (!header) {
mem_free(value);
continue;
}
char *normalized_value = normalize(value);
bool found = false;
for (auto h: xhr->responseHeaders) {
const std::string hh = h.first;
if (!strcasecmp(hh.c_str(), header)) {
xhr->responseHeaders[hh] = xhr->responseHeaders[hh] + ", " + normalized_value;
found = true;
break;
}
}
if (!found) {
xhr->responseHeaders[header] = normalized_value;
}
mem_free(header);
mem_free(value);
}
}
xhr->status = status;
mem_free_set(&xhr->statusText, stracpy(statusText.c_str()));
}
mem_free_set(&xhr->responseText, memacpy(fragment->data, fragment->length)); mem_free_set(&xhr->responseText, memacpy(fragment->data, fragment->length));
mem_free_set(&xhr->responseType, stracpy("")); mem_free_set(&xhr->responseType, stracpy(""));
xhr->readyState = DONE; xhr->readyState = DONE;
xhr->status = 200;
mem_free_set(&xhr->statusText, stracpy("OK"));
register_bottom_half(onload_run, xhr); register_bottom_half(onload_run, xhr);
} }
} }