8 Commits

Author SHA1 Message Date
Dylan G
85d09107ed response to feedback 2021-03-16 16:24:54 +00:00
Dylan G
b16df2607c Add issue templates
We've needed this for a while, due to bug reports that don't really mean anything.
2021-03-11 18:38:00 +00:00
Dylan G
7745530764 Fixed 4720a499 (TP returns 303 currently, not 404) => handle 303 well(?); pushed some code around 2021-03-11 13:47:24 +00:00
Dylan G
0bab0f6700 Patched httpc error message to actually be readable on console; also provides Result code 2021-03-11 12:34:03 +00:00
Dylan G
38ab370cf1 Merge pull request #247 from KennLDN/patch-1
Fix broken link in CONTRIBUTORS.md
2021-02-08 13:40:16 +00:00
kenn
5cea6c8df4 Fix broken link in CONTRIBUTORS.md 2021-02-08 13:38:32 +00:00
Alex Taber
e4e0118c1a Prevent out of bounds scrolling in the browser 2021-01-01 23:51:51 -05:00
Dylan G
accdaaed2a Reduced code duplication 2020-12-31 21:28:10 +00:00
6 changed files with 128 additions and 52 deletions

39
.github/ISSUE_TEMPLATE/bug_report.md vendored Normal file
View File

@@ -0,0 +1,39 @@
---
name: Bug report
about: Found a bug? Report it here
title: ''
labels: ''
assignees: ''
---
**Description**
A clear and concise description of what the bug is.
**Steps to reproduce**
***If you cannot reproduce the bug, please describe what you were doing in as much detail as possible***
*If you were scanning using the QR scanner, ensure you include a link to the theme you were attempting to download.*
**Expected behavior**
A clear and concise description of what you expected to happen.
**Screenshots**
Add screenshots of any error screens you encountered. Bug reports without screenshots will take longer to solve, so we recommend you get some!
**Crash dumps**
If your bug causes a crash in Luma3DS, please upload any crash dumps generated. You can find these in `SD:/luma/dumps/armX` (`X = 9 or 11`) with the name Luma3DS's exception handlers give you.
**System information**
*System model* e.g. new3DS XL
*System firmware version* e.g. 11.14.0 (this can be found in the System Settings applet by default)
*Anemone3DS version* e.g. v2.2.0 (found in the bottom-left of Anemone3DS)
*Luma3DS version* e.g. v10.2.1 (found in the menu when you hold Select on boot)
**If you are not on the [latest version of Anemone3DS](https://github.com/astronautlevel2/Anemone3DS/releases/latest), your bug report will likely be closed. Ensure the bug occurs in the latest build!**

View File

@@ -0,0 +1,20 @@
---
name: Feature request
about: Suggest an idea for this project
title: ''
labels: ''
assignees: ''
---
**Is your feature request related to a problem? Please describe.**
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
**Describe the solution you'd like**
A clear and concise description of what you want to happen.
**Describe alternatives you've considered**
A clear and concise description of any alternative solutions or features you've considered.
**Additional context**
Add any other context or screenshots about the feature request here.

View File

@@ -4,7 +4,7 @@
* Dawid Eckert ([@daedreth](https://github.com/daedreth)) * Dawid Eckert ([@daedreth](https://github.com/daedreth))
* Dylan G. ([@helloman892](https://github.com/helloman892)) * Dylan G. ([@helloman892](https://github.com/helloman892))
* Nils P. ([@ZetaDesigns](https://github.com/ZetaDesigns)) * Nils P. ([@ZetaDesigns](https://github.com/ZetaDesigns))
* Matt Kenny ([@8kenn](https://github.com/8kenn)) * Matt Kenny ([@KennLDN](https://github.com/KennLDN))
# Minor Contributors # Minor Contributors
* Nic ([@Wizzrobes](https://github.com/Wizzrobes)) * Nic ([@Wizzrobes](https://github.com/Wizzrobes))

View File

@@ -340,7 +340,7 @@ bool init_qr(void)
free(zip_buf); free(zip_buf);
return false; return false;
} }
else if (R_DESCRIPTION(res) == RD_CANCEL_REQUESTED) else if (R_DESCRIPTION(res) == RD_NO_DATA || R_DESCRIPTION(res) == RD_CANCEL_REQUESTED)
{ {
free(filename); free(filename);
return true; return true;

View File

@@ -301,7 +301,7 @@ void throw_error(char* error, ErrorLevel level)
draw_base_interface(); draw_base_interface();
draw_text_center(GFX_TOP, 100, 0.5f, 0.6f, 0.6f, colors[text_color], error); draw_text_center(GFX_TOP, 100, 0.5f, 0.6f, 0.6f, colors[text_color], error);
draw_c2d_text_center(GFX_TOP, 150, 0.5f, 0.6f, 0.6f, colors[COLOR_WHITE], &text[bottom_text]); draw_c2d_text_center(GFX_TOP, 170, 0.5f, 0.6f, 0.6f, colors[COLOR_WHITE], &text[bottom_text]);
end_frame(); end_frame();
if(kDown & KEY_A) break; if(kDown & KEY_A) break;

View File

@@ -250,7 +250,7 @@ static void load_remote_list(Entry_List_s * list, json_int_t page, EntryMode mod
json_decref(root); json_decref(root);
} }
else else
throw_error("Couldn't download ThemePlaza data.\nMake sure WiFi is on.", ERROR_LEVEL_WARNING); throw_error("Couldn't download Theme Plaza data.\nMake sure WiFi is on.", ERROR_LEVEL_WARNING);
free(page_json); free(page_json);
} }
@@ -469,6 +469,7 @@ static void change_selected(Entry_List_s * list, int change_value)
newval += list->entries_per_screen_h; newval += list->entries_per_screen_h;
if (newval / list->entries_per_screen_h != list->selected_entry / list->entries_per_screen_h) if (newval / list->entries_per_screen_h != list->selected_entry / list->entries_per_screen_h)
newval += list->entries_per_screen_h * (-change_value); newval += list->entries_per_screen_h * (-change_value);
newval %= list->entries_count;
} }
else else
{ {
@@ -756,10 +757,11 @@ typedef struct header
typedef enum ParseResult typedef enum ParseResult
{ {
SUCCESS, // 200/203 (203 indicates a successful request with a transformation applied by a proxy) SUCCESS, // 200/203 (203 indicates a successful request with a transformation applied by a proxy)
REDIRECT, // 301/302/303/307/308 REDIRECT, // 301/302/307/308
HTTPC_ERROR, HTTPC_ERROR,
ABORTED, ABORTED,
SERVER_IS_MISBEHAVING, SERVER_IS_MISBEHAVING,
SEE_OTHER = 303, // Theme Plaza returns these
HTTP_UNAUTHORIZED = 401, HTTP_UNAUTHORIZED = 401,
HTTP_FORBIDDEN = 403, HTTP_FORBIDDEN = 403,
HTTP_NOT_FOUND = 404, HTTP_NOT_FOUND = 404,
@@ -952,7 +954,8 @@ redirect: // goto here if we need to redirect
return ret; return ret;
} }
char err_buf[0x69]; #define ERROR_BUFFER_SIZE 0x80
char err_buf[ERROR_BUFFER_SIZE];
ParseResult parse = parse_header(&_header, &context, acceptable_mime_types); ParseResult parse = parse_header(&_header, &context, acceptable_mime_types);
switch (parse) switch (parse)
{ {
@@ -963,6 +966,24 @@ redirect: // goto here if we need to redirect
if(R_FAILED(ret)) if(R_FAILED(ret))
return ret; return ret;
return MAKERESULT(RL_SUCCESS, RS_CANCELED, RM_APPLICATION, RD_CANCEL_REQUESTED); return MAKERESULT(RL_SUCCESS, RS_CANCELED, RM_APPLICATION, RD_CANCEL_REQUESTED);
case HTTPC_ERROR:
DEBUG("httpc error %lx\n", _header.result_code);
snprintf(err_buf, ERROR_BUFFER_SIZE, "Error in HTTPC sysmodule - 0x%08lx.\nIf you are seeing this, please contact an\nAnemone developer on the Theme Plaza Discord.", _header.result_code);
throw_error(err_buf, ERROR_LEVEL_ERROR);
quit = true;
httpcCloseContext(&context);
return _header.result_code;
case SEE_OTHER:
if (strstr(url, THEMEPLAZA_BASE_URL))
{
snprintf(err_buf, ERROR_BUFFER_SIZE, "HTTP 303 See Other (Theme Plaza)\nHas this theme been approved?");
goto error;
}
else
{
snprintf(err_buf, ERROR_BUFFER_SIZE, "HTTP 303 See Other\nDownload the resource directly\nor contact the site administrator.");
goto error;
}
case REDIRECT: case REDIRECT:
httpcGetResponseHeader(&context, "Location", redirect_url, 0x824); httpcGetResponseHeader(&context, "Location", redirect_url, 0x824);
httpcCloseContext(&context); httpcCloseContext(&context);
@@ -980,82 +1001,78 @@ redirect: // goto here if we need to redirect
} }
DEBUG("HTTP Redirect: %s %s\n", new_url, *redirect_url == '/' ? "relative" : "absolute"); DEBUG("HTTP Redirect: %s %s\n", new_url, *redirect_url == '/' ? "relative" : "absolute");
goto redirect; goto redirect;
case HTTP_UNACCEPTABLE:
DEBUG("HTTP 406 Unacceptable; Accept: %s\n", acceptable_mime_types);
throw_error(ZIP_NOT_AVAILABLE, ERROR_LEVEL_WARNING);
return httpcCloseContext(&context);
case SERVER_IS_MISBEHAVING: case SERVER_IS_MISBEHAVING:
DEBUG("Server is misbehaving (provided resource with incorrect MIME)\n"); DEBUG("Server is misbehaving (provided resource with incorrect MIME)\n");
throw_error(ZIP_NOT_AVAILABLE, ERROR_LEVEL_WARNING); snprintf(err_buf, ERROR_BUFFER_SIZE, ZIP_NOT_AVAILABLE);
return httpcCloseContext(&context); goto error;
case HTTPC_ERROR:
DEBUG("httpc error\n");
throw_error("Error in HTTPC sysmodule.\nIf you are seeing this, please contact an Anemone developer\non the ThemePlaza Discord.", ERROR_LEVEL_ERROR);
quit = true;
httpcCloseContext(&context);
return _header.result_code;
case HTTP_NOT_FOUND: case HTTP_NOT_FOUND:
case HTTP_GONE: ; case HTTP_GONE: ;
const char * http_error = parse == HTTP_NOT_FOUND ? "404 Not Found" : "410 Gone"; const char * http_error = parse == HTTP_NOT_FOUND ? "404 Not Found" : "410 Gone";
DEBUG("HTTP %s; URL: %s\n", http_error, url); DEBUG("HTTP %s; URL: %s\n", http_error, url);
if (strstr(url, THEMEPLAZA_BASE_URL) && parse == HTTP_NOT_FOUND) if (strstr(url, THEMEPLAZA_BASE_URL) && parse == HTTP_NOT_FOUND)
throw_error("HTTP 404 Not Found\nHas this theme been approved?", ERROR_LEVEL_WARNING); snprintf(err_buf, ERROR_BUFFER_SIZE, "HTTP 404 Not Found\nHas this theme been approved?");
else else
{ snprintf(err_buf, ERROR_BUFFER_SIZE, "HTTP %s\nCheck that the URL is correct.", http_error);
snprintf(err_buf, 0x69, "HTTP %s\nCheck that the URL is correct.", http_error); goto error;
throw_error(err_buf, ERROR_LEVEL_WARNING); case HTTP_UNACCEPTABLE:
} DEBUG("HTTP 406 Unacceptable; Accept: %s\n", acceptable_mime_types);
return httpcCloseContext(&context); snprintf(err_buf, ERROR_BUFFER_SIZE, ZIP_NOT_AVAILABLE);
goto error;
case HTTP_UNAUTHORIZED: case HTTP_UNAUTHORIZED:
case HTTP_FORBIDDEN: case HTTP_FORBIDDEN:
case HTTP_PROXY_UNAUTHORIZED: case HTTP_PROXY_UNAUTHORIZED:
DEBUG("HTTP %u: device not authenticated\n", parse); DEBUG("HTTP %u: device not authenticated\n", parse);
snprintf(err_buf, 0x69, "HTTP %s\nContact the site administrator.", parse == HTTP_UNAUTHORIZED snprintf(err_buf, ERROR_BUFFER_SIZE, "HTTP %s\nContact the site administrator.", parse == HTTP_UNAUTHORIZED
? "401 Unauthorized" ? "401 Unauthorized"
: parse == HTTP_FORBIDDEN : parse == HTTP_FORBIDDEN
? "403 Forbidden" ? "403 Forbidden"
: "407 Proxy Authentication Required"); : "407 Proxy Authentication Required");
throw_error(err_buf, ERROR_LEVEL_WARNING); goto error;
return httpcCloseContext(&context);
case HTTP_URI_TOO_LONG: case HTTP_URI_TOO_LONG:
DEBUG("HTTP 414; URL is too long, maybe too many redirects?\n"); DEBUG("HTTP 414; URL is too long, maybe too many redirects?\n");
throw_error("HTTP 414 URI Too Long\nThe QR code points to a really long URL.\nDownload the file directly.", ERROR_LEVEL_WARNING); snprintf(err_buf, ERROR_BUFFER_SIZE, "HTTP 414 URI Too Long\nThe QR code points to a really long URL.\nDownload the file directly.");
return httpcCloseContext(&context); goto error;
case HTTP_IM_A_TEAPOT: case HTTP_IM_A_TEAPOT:
DEBUG("HTTP 418 I'm a teapot\n"); DEBUG("HTTP 418 I'm a teapot\n");
throw_error("HTTP 418 I'm a teapot\nContact the site administrator.", ERROR_LEVEL_WARNING); snprintf(err_buf, ERROR_BUFFER_SIZE, "HTTP 418 I'm a teapot\nContact the site administrator.");
return httpcCloseContext(&context); goto error;
case HTTP_UPGRADE_REQUIRED: case HTTP_UPGRADE_REQUIRED:
DEBUG("HTTP 426; HTTP/2 required\n"); DEBUG("HTTP 426; HTTP/2 required\n");
throw_error("HTTP 426 Upgrade Required\nThe 3DS does not support this website.\nContact the site administrator.", ERROR_LEVEL_WARNING); snprintf(err_buf, ERROR_BUFFER_SIZE, "HTTP 426 Upgrade Required\nThe 3DS cannot connect to this server.\nContact the site administrator.");
return httpcCloseContext(&context); goto error;
case HTTP_LEGAL_REASONS: case HTTP_LEGAL_REASONS:
DEBUG("HTTP 451; URL: %s\n", url); DEBUG("HTTP 451; URL: %s\n", url);
throw_error("HTTP 451 Unavailable for Legal Reasons\nSome entity is preventing access\nto the host server for legal reasons.", ERROR_LEVEL_WARNING); snprintf(err_buf, ERROR_BUFFER_SIZE, "HTTP 451 Unavailable for Legal Reasons\nSome entity is preventing access\nto the host server for legal reasons.");
return httpcCloseContext(&context); goto error;
case HTTP_INTERNAL_SERVER_ERROR: case HTTP_INTERNAL_SERVER_ERROR:
DEBUG("HTTP 500\n"); DEBUG("HTTP 500; URL: %s\n", url);
throw_error("HTTP 500 Internal Server Error\nContact the site administrator.", ERROR_LEVEL_WARNING); snprintf(err_buf, ERROR_BUFFER_SIZE, "HTTP 500 Internal Server Error\nContact the site administrator.");
return httpcCloseContext(&context); goto error;
case HTTP_BAD_GATEWAY: case HTTP_BAD_GATEWAY:
DEBUG("HTTP 502\n"); DEBUG("HTTP 502; URL: %s\n", url);
throw_error("HTTP 502 Bad Gateway\nContact the site administrator.", ERROR_LEVEL_WARNING); snprintf(err_buf, ERROR_BUFFER_SIZE, "HTTP 502 Bad Gateway\nContact the site administrator.");
return httpcCloseContext(&context); goto error;
case HTTP_SERVICE_UNAVAILABLE: case HTTP_SERVICE_UNAVAILABLE:
DEBUG("HTTP 503\n"); DEBUG("HTTP 503; URL: %s\n", url);
throw_error("HTTP 503 Service Unavailable\nContact the site administrator.", ERROR_LEVEL_WARNING); snprintf(err_buf, ERROR_BUFFER_SIZE, "HTTP 503 Service Unavailable\nContact the site administrator.");
return httpcCloseContext(&context); goto error;
case HTTP_GATEWAY_TIMEOUT: case HTTP_GATEWAY_TIMEOUT:
DEBUG("HTTP 504\n"); DEBUG("HTTP 504; URL: %s\n", url);
throw_error("HTTP 504 Gateway Timeout\nContact the site administrator.", ERROR_LEVEL_WARNING); snprintf(err_buf, ERROR_BUFFER_SIZE, "HTTP 504 Gateway Timeout\nContact the site administrator.");
return httpcCloseContext(&context); goto error;
default: default:
DEBUG("HTTP %u\n", parse); DEBUG("HTTP %u; URL: %s\n", parse, url);
snprintf(err_buf, 0x69, "HTTP %u\nIf you believe this is unexpected, please\ncontact the site administrator.", parse); snprintf(err_buf, ERROR_BUFFER_SIZE, "HTTP %u\nIf you believe this is unexpected, please\ncontact the site administrator.", parse);
throw_error(err_buf, ERROR_LEVEL_WARNING); goto error;
return httpcCloseContext(&context);
} }
goto no_error;
error:
throw_error(err_buf, ERROR_LEVEL_WARNING);
Result res = httpcCloseContext(&context);
if (R_FAILED(res)) return res;
return MAKERESULT(RL_TEMPORARY, RS_CANCELED, RM_APPLICATION, RD_NO_DATA);
no_error:;
u32 chunk_size; u32 chunk_size;
if (_header.file_size) if (_header.file_size)
// the only reason we chunk this at all is for the download bar; // the only reason we chunk this at all is for the download bar;
@@ -1115,4 +1132,4 @@ redirect: // goto here if we need to redirect
DEBUG("size: %lu\n", *size); DEBUG("size: %lu\n", *size);
if (filename) { DEBUG("filename: %s\n", *filename); } if (filename) { DEBUG("filename: %s\n", *filename); }
return MAKERESULT(RL_SUCCESS, RS_SUCCESS, RM_APPLICATION, RD_SUCCESS); return MAKERESULT(RL_SUCCESS, RS_SUCCESS, RM_APPLICATION, RD_SUCCESS);
} }