diff options
Diffstat (limited to '')
| -rw-r--r-- | html.c | 76 |
1 files changed, 38 insertions, 38 deletions
| @@ -2540,7 +2540,7 @@ int html_get_handler(const xs_dict *req, const char *q_path, | |||
| 2540 | char **body, int *b_size, char **ctype, xs_str **etag) | 2540 | char **body, int *b_size, char **ctype, xs_str **etag) |
| 2541 | { | 2541 | { |
| 2542 | const char *accept = xs_dict_get(req, "accept"); | 2542 | const char *accept = xs_dict_get(req, "accept"); |
| 2543 | int status = 404; | 2543 | int status = HTTP_STATUS_NOT_FOUND; |
| 2544 | snac snac; | 2544 | snac snac; |
| 2545 | xs *uid = NULL; | 2545 | xs *uid = NULL; |
| 2546 | const char *p_path; | 2546 | const char *p_path; |
| @@ -2553,7 +2553,7 @@ int html_get_handler(const xs_dict *req, const char *q_path, | |||
| 2553 | 2553 | ||
| 2554 | if (xs_is_null(v)) { | 2554 | if (xs_is_null(v)) { |
| 2555 | srv_log(xs_fmt("html_get_handler bad query '%s'", q_path)); | 2555 | srv_log(xs_fmt("html_get_handler bad query '%s'", q_path)); |
| 2556 | return 404; | 2556 | return HTTP_STATUS_NOT_FOUND; |
| 2557 | } | 2557 | } |
| 2558 | 2558 | ||
| 2559 | uid = xs_dup(v); | 2559 | uid = xs_dup(v); |
| @@ -2569,7 +2569,7 @@ int html_get_handler(const xs_dict *req, const char *q_path, | |||
| 2569 | if (!uid || !user_open(&snac, uid)) { | 2569 | if (!uid || !user_open(&snac, uid)) { |
| 2570 | /* invalid user */ | 2570 | /* invalid user */ |
| 2571 | srv_debug(1, xs_fmt("html_get_handler bad user %s", uid)); | 2571 | srv_debug(1, xs_fmt("html_get_handler bad user %s", uid)); |
| 2572 | return 404; | 2572 | return HTTP_STATUS_NOT_FOUND; |
| 2573 | } | 2573 | } |
| 2574 | 2574 | ||
| 2575 | /* return the RSS if requested by Accept header */ | 2575 | /* return the RSS if requested by Accept header */ |
| @@ -2598,7 +2598,7 @@ int html_get_handler(const xs_dict *req, const char *q_path, | |||
| 2598 | /** empty public timeline for private users **/ | 2598 | /** empty public timeline for private users **/ |
| 2599 | *body = html_timeline(&snac, NULL, 1, 0, 0, 0, NULL, "", 1); | 2599 | *body = html_timeline(&snac, NULL, 1, 0, 0, 0, NULL, "", 1); |
| 2600 | *b_size = strlen(*body); | 2600 | *b_size = strlen(*body); |
| 2601 | status = 200; | 2601 | status = HTTP_STATUS_OK; |
| 2602 | } | 2602 | } |
| 2603 | else | 2603 | else |
| 2604 | if (cache && history_mtime(&snac, h) > timeline_mtime(&snac)) { | 2604 | if (cache && history_mtime(&snac, h) > timeline_mtime(&snac)) { |
| @@ -2617,7 +2617,7 @@ int html_get_handler(const xs_dict *req, const char *q_path, | |||
| 2617 | *body = html_timeline(&snac, pins, 1, skip, show, xs_list_len(next), NULL, "", 1); | 2617 | *body = html_timeline(&snac, pins, 1, skip, show, xs_list_len(next), NULL, "", 1); |
| 2618 | 2618 | ||
| 2619 | *b_size = strlen(*body); | 2619 | *b_size = strlen(*body); |
| 2620 | status = 200; | 2620 | status = HTTP_STATUS_OK; |
| 2621 | 2621 | ||
| 2622 | if (save) | 2622 | if (save) |
| 2623 | history_add(&snac, h, *body, *b_size, etag); | 2623 | history_add(&snac, h, *body, *b_size, etag); |
| @@ -2627,7 +2627,7 @@ int html_get_handler(const xs_dict *req, const char *q_path, | |||
| 2627 | if (strcmp(p_path, "admin") == 0) { /** private timeline **/ | 2627 | if (strcmp(p_path, "admin") == 0) { /** private timeline **/ |
| 2628 | if (!login(&snac, req)) { | 2628 | if (!login(&snac, req)) { |
| 2629 | *body = xs_dup(uid); | 2629 | *body = xs_dup(uid); |
| 2630 | status = 401; | 2630 | status = HTTP_STATUS_UNAUTHORIZED; |
| 2631 | } | 2631 | } |
| 2632 | else { | 2632 | else { |
| 2633 | const char *q = xs_dict_get(q_vars, "q"); | 2633 | const char *q = xs_dict_get(q_vars, "q"); |
| @@ -2649,7 +2649,7 @@ int html_get_handler(const xs_dict *req, const char *q_path, | |||
| 2649 | 2649 | ||
| 2650 | *body = html_timeline(&snac, tl, 0, skip, show, more, title, page, 0); | 2650 | *body = html_timeline(&snac, tl, 0, skip, show, more, title, page, 0); |
| 2651 | *b_size = strlen(*body); | 2651 | *b_size = strlen(*body); |
| 2652 | status = 200; | 2652 | status = HTTP_STATUS_OK; |
| 2653 | } | 2653 | } |
| 2654 | else { | 2654 | else { |
| 2655 | /** search by content **/ | 2655 | /** search by content **/ |
| @@ -2670,7 +2670,7 @@ int html_get_handler(const xs_dict *req, const char *q_path, | |||
| 2670 | 2670 | ||
| 2671 | *body = html_timeline(&snac, tl, 0, skip, tl_len, to || tl_len == show, title, page, 0); | 2671 | *body = html_timeline(&snac, tl, 0, skip, tl_len, to || tl_len == show, title, page, 0); |
| 2672 | *b_size = strlen(*body); | 2672 | *b_size = strlen(*body); |
| 2673 | status = 200; | 2673 | status = HTTP_STATUS_OK; |
| 2674 | } | 2674 | } |
| 2675 | } | 2675 | } |
| 2676 | else { | 2676 | else { |
| @@ -2699,7 +2699,7 @@ int html_get_handler(const xs_dict *req, const char *q_path, | |||
| 2699 | xs_list_len(next), NULL, "/admin", 1); | 2699 | xs_list_len(next), NULL, "/admin", 1); |
| 2700 | 2700 | ||
| 2701 | *b_size = strlen(*body); | 2701 | *b_size = strlen(*body); |
| 2702 | status = 200; | 2702 | status = HTTP_STATUS_OK; |
| 2703 | 2703 | ||
| 2704 | if (save) | 2704 | if (save) |
| 2705 | history_add(&snac, "timeline.html_", *body, *b_size, etag); | 2705 | history_add(&snac, "timeline.html_", *body, *b_size, etag); |
| @@ -2711,7 +2711,7 @@ int html_get_handler(const xs_dict *req, const char *q_path, | |||
| 2711 | if (xs_startswith(p_path, "admin/p/")) { /** unique post by md5 **/ | 2711 | if (xs_startswith(p_path, "admin/p/")) { /** unique post by md5 **/ |
| 2712 | if (!login(&snac, req)) { | 2712 | if (!login(&snac, req)) { |
| 2713 | *body = xs_dup(uid); | 2713 | *body = xs_dup(uid); |
| 2714 | status = 401; | 2714 | status = HTTP_STATUS_UNAUTHORIZED; |
| 2715 | } | 2715 | } |
| 2716 | else { | 2716 | else { |
| 2717 | xs *l = xs_split(p_path, "/"); | 2717 | xs *l = xs_split(p_path, "/"); |
| @@ -2722,7 +2722,7 @@ int html_get_handler(const xs_dict *req, const char *q_path, | |||
| 2722 | 2722 | ||
| 2723 | *body = html_timeline(&snac, list, 0, 0, 0, 0, NULL, "/admin", 1); | 2723 | *body = html_timeline(&snac, list, 0, 0, 0, 0, NULL, "/admin", 1); |
| 2724 | *b_size = strlen(*body); | 2724 | *b_size = strlen(*body); |
| 2725 | status = 200; | 2725 | status = HTTP_STATUS_OK; |
| 2726 | } | 2726 | } |
| 2727 | } | 2727 | } |
| 2728 | } | 2728 | } |
| @@ -2730,31 +2730,31 @@ int html_get_handler(const xs_dict *req, const char *q_path, | |||
| 2730 | if (strcmp(p_path, "people") == 0) { /** the list of people **/ | 2730 | if (strcmp(p_path, "people") == 0) { /** the list of people **/ |
| 2731 | if (!login(&snac, req)) { | 2731 | if (!login(&snac, req)) { |
| 2732 | *body = xs_dup(uid); | 2732 | *body = xs_dup(uid); |
| 2733 | status = 401; | 2733 | status = HTTP_STATUS_UNAUTHORIZED; |
| 2734 | } | 2734 | } |
| 2735 | else { | 2735 | else { |
| 2736 | *body = html_people(&snac); | 2736 | *body = html_people(&snac); |
| 2737 | *b_size = strlen(*body); | 2737 | *b_size = strlen(*body); |
| 2738 | status = 200; | 2738 | status = HTTP_STATUS_OK; |
| 2739 | } | 2739 | } |
| 2740 | } | 2740 | } |
| 2741 | else | 2741 | else |
| 2742 | if (strcmp(p_path, "notifications") == 0) { /** the list of notifications **/ | 2742 | if (strcmp(p_path, "notifications") == 0) { /** the list of notifications **/ |
| 2743 | if (!login(&snac, req)) { | 2743 | if (!login(&snac, req)) { |
| 2744 | *body = xs_dup(uid); | 2744 | *body = xs_dup(uid); |
| 2745 | status = 401; | 2745 | status = HTTP_STATUS_UNAUTHORIZED; |
| 2746 | } | 2746 | } |
| 2747 | else { | 2747 | else { |
| 2748 | *body = html_notifications(&snac, skip, show); | 2748 | *body = html_notifications(&snac, skip, show); |
| 2749 | *b_size = strlen(*body); | 2749 | *b_size = strlen(*body); |
| 2750 | status = 200; | 2750 | status = HTTP_STATUS_OK; |
| 2751 | } | 2751 | } |
| 2752 | } | 2752 | } |
| 2753 | else | 2753 | else |
| 2754 | if (strcmp(p_path, "instance") == 0) { /** instance timeline **/ | 2754 | if (strcmp(p_path, "instance") == 0) { /** instance timeline **/ |
| 2755 | if (!login(&snac, req)) { | 2755 | if (!login(&snac, req)) { |
| 2756 | *body = xs_dup(uid); | 2756 | *body = xs_dup(uid); |
| 2757 | status = 401; | 2757 | status = HTTP_STATUS_UNAUTHORIZED; |
| 2758 | } | 2758 | } |
| 2759 | else { | 2759 | else { |
| 2760 | xs *list = timeline_instance_list(skip, show); | 2760 | xs *list = timeline_instance_list(skip, show); |
| @@ -2763,14 +2763,14 @@ int html_get_handler(const xs_dict *req, const char *q_path, | |||
| 2763 | *body = html_timeline(&snac, list, 0, skip, show, | 2763 | *body = html_timeline(&snac, list, 0, skip, show, |
| 2764 | xs_list_len(next), L("Showing instance timeline"), "/instance", 0); | 2764 | xs_list_len(next), L("Showing instance timeline"), "/instance", 0); |
| 2765 | *b_size = strlen(*body); | 2765 | *b_size = strlen(*body); |
| 2766 | status = 200; | 2766 | status = HTTP_STATUS_OK; |
| 2767 | } | 2767 | } |
| 2768 | } | 2768 | } |
| 2769 | else | 2769 | else |
| 2770 | if (xs_startswith(p_path, "list/")) { /** list timelines **/ | 2770 | if (xs_startswith(p_path, "list/")) { /** list timelines **/ |
| 2771 | if (!login(&snac, req)) { | 2771 | if (!login(&snac, req)) { |
| 2772 | *body = xs_dup(uid); | 2772 | *body = xs_dup(uid); |
| 2773 | status = 401; | 2773 | status = HTTP_STATUS_UNAUTHORIZED; |
| 2774 | } | 2774 | } |
| 2775 | else { | 2775 | else { |
| 2776 | xs *l = xs_split(p_path, "/"); | 2776 | xs *l = xs_split(p_path, "/"); |
| @@ -2787,14 +2787,14 @@ int html_get_handler(const xs_dict *req, const char *q_path, | |||
| 2787 | *body = html_timeline(&snac, list, 0, skip, show, | 2787 | *body = html_timeline(&snac, list, 0, skip, show, |
| 2788 | xs_list_len(next), title, base, 1); | 2788 | xs_list_len(next), title, base, 1); |
| 2789 | *b_size = strlen(*body); | 2789 | *b_size = strlen(*body); |
| 2790 | status = 200; | 2790 | status = HTTP_STATUS_OK; |
| 2791 | } | 2791 | } |
| 2792 | } | 2792 | } |
| 2793 | } | 2793 | } |
| 2794 | else | 2794 | else |
| 2795 | if (xs_startswith(p_path, "p/")) { /** a timeline with just one entry **/ | 2795 | if (xs_startswith(p_path, "p/")) { /** a timeline with just one entry **/ |
| 2796 | if (xs_type(xs_dict_get(snac.config, "private")) == XSTYPE_TRUE) | 2796 | if (xs_type(xs_dict_get(snac.config, "private")) == XSTYPE_TRUE) |
| 2797 | return 403; | 2797 | return HTTP_STATUS_FORBIDDEN; |
| 2798 | 2798 | ||
| 2799 | xs *id = xs_fmt("%s/%s", snac.actor, p_path); | 2799 | xs *id = xs_fmt("%s/%s", snac.actor, p_path); |
| 2800 | xs *msg = NULL; | 2800 | xs *msg = NULL; |
| @@ -2807,7 +2807,7 @@ int html_get_handler(const xs_dict *req, const char *q_path, | |||
| 2807 | 2807 | ||
| 2808 | *body = html_timeline(&snac, list, 1, 0, 0, 0, NULL, "", 1); | 2808 | *body = html_timeline(&snac, list, 1, 0, 0, 0, NULL, "", 1); |
| 2809 | *b_size = strlen(*body); | 2809 | *b_size = strlen(*body); |
| 2810 | status = 200; | 2810 | status = HTTP_STATUS_OK; |
| 2811 | } | 2811 | } |
| 2812 | } | 2812 | } |
| 2813 | else | 2813 | else |
| @@ -2829,10 +2829,10 @@ int html_get_handler(const xs_dict *req, const char *q_path, | |||
| 2829 | else | 2829 | else |
| 2830 | if (xs_startswith(p_path, "h/")) { /** an entry from the history **/ | 2830 | if (xs_startswith(p_path, "h/")) { /** an entry from the history **/ |
| 2831 | if (xs_type(xs_dict_get(snac.config, "private")) == XSTYPE_TRUE) | 2831 | if (xs_type(xs_dict_get(snac.config, "private")) == XSTYPE_TRUE) |
| 2832 | return 403; | 2832 | return HTTP_STATUS_FORBIDDEN; |
| 2833 | 2833 | ||
| 2834 | if (xs_type(xs_dict_get(srv_config, "disable_history")) == XSTYPE_TRUE) | 2834 | if (xs_type(xs_dict_get(srv_config, "disable_history")) == XSTYPE_TRUE) |
| 2835 | return 403; | 2835 | return HTTP_STATUS_FORBIDDEN; |
| 2836 | 2836 | ||
| 2837 | xs *l = xs_split(p_path, "/"); | 2837 | xs *l = xs_split(p_path, "/"); |
| 2838 | const char *id = xs_list_get(l, 1); | 2838 | const char *id = xs_list_get(l, 1); |
| @@ -2841,7 +2841,7 @@ int html_get_handler(const xs_dict *req, const char *q_path, | |||
| 2841 | if (xs_endswith(id, "timeline.html_")) { | 2841 | if (xs_endswith(id, "timeline.html_")) { |
| 2842 | /* Don't let them in */ | 2842 | /* Don't let them in */ |
| 2843 | *b_size = 0; | 2843 | *b_size = 0; |
| 2844 | status = 404; | 2844 | status = HTTP_STATUS_NOT_FOUND; |
| 2845 | } | 2845 | } |
| 2846 | else | 2846 | else |
| 2847 | status = history_get(&snac, id, body, b_size, | 2847 | status = history_get(&snac, id, body, b_size, |
| @@ -2851,7 +2851,7 @@ int html_get_handler(const xs_dict *req, const char *q_path, | |||
| 2851 | else | 2851 | else |
| 2852 | if (strcmp(p_path, ".rss") == 0) { /** public timeline in RSS format **/ | 2852 | if (strcmp(p_path, ".rss") == 0) { /** public timeline in RSS format **/ |
| 2853 | if (xs_type(xs_dict_get(snac.config, "private")) == XSTYPE_TRUE) | 2853 | if (xs_type(xs_dict_get(snac.config, "private")) == XSTYPE_TRUE) |
| 2854 | return 403; | 2854 | return HTTP_STATUS_FORBIDDEN; |
| 2855 | 2855 | ||
| 2856 | xs *elems = timeline_simple_list(&snac, "public", 0, 20); | 2856 | xs *elems = timeline_simple_list(&snac, "public", 0, 20); |
| 2857 | xs *bio = not_really_markdown(xs_dict_get(snac.config, "bio"), NULL, NULL); | 2857 | xs *bio = not_really_markdown(xs_dict_get(snac.config, "bio"), NULL, NULL); |
| @@ -2865,12 +2865,12 @@ int html_get_handler(const xs_dict *req, const char *q_path, | |||
| 2865 | *body = timeline_to_rss(&snac, elems, rss_title, rss_link, bio); | 2865 | *body = timeline_to_rss(&snac, elems, rss_title, rss_link, bio); |
| 2866 | *b_size = strlen(*body); | 2866 | *b_size = strlen(*body); |
| 2867 | *ctype = "application/rss+xml; charset=utf-8"; | 2867 | *ctype = "application/rss+xml; charset=utf-8"; |
| 2868 | status = 200; | 2868 | status = HTTP_STATUS_OK; |
| 2869 | 2869 | ||
| 2870 | snac_debug(&snac, 1, xs_fmt("serving RSS")); | 2870 | snac_debug(&snac, 1, xs_fmt("serving RSS")); |
| 2871 | } | 2871 | } |
| 2872 | else | 2872 | else |
| 2873 | status = 404; | 2873 | status = HTTP_STATUS_NOT_FOUND; |
| 2874 | 2874 | ||
| 2875 | user_free(&snac); | 2875 | user_free(&snac); |
| 2876 | 2876 | ||
| @@ -2901,7 +2901,7 @@ int html_post_handler(const xs_dict *req, const char *q_path, | |||
| 2901 | if (!uid || !user_open(&snac, uid)) { | 2901 | if (!uid || !user_open(&snac, uid)) { |
| 2902 | /* invalid user */ | 2902 | /* invalid user */ |
| 2903 | srv_debug(1, xs_fmt("html_post_handler bad user %s", uid)); | 2903 | srv_debug(1, xs_fmt("html_post_handler bad user %s", uid)); |
| 2904 | return 404; | 2904 | return HTTP_STATUS_NOT_FOUND; |
| 2905 | } | 2905 | } |
| 2906 | 2906 | ||
| 2907 | p_path = xs_list_get(l, 2); | 2907 | p_path = xs_list_get(l, 2); |
| @@ -2910,7 +2910,7 @@ int html_post_handler(const xs_dict *req, const char *q_path, | |||
| 2910 | if (!login(&snac, req)) { | 2910 | if (!login(&snac, req)) { |
| 2911 | user_free(&snac); | 2911 | user_free(&snac); |
| 2912 | *body = xs_dup(uid); | 2912 | *body = xs_dup(uid); |
| 2913 | return 401; | 2913 | return HTTP_STATUS_UNAUTHORIZED; |
| 2914 | } | 2914 | } |
| 2915 | 2915 | ||
| 2916 | p_vars = xs_dict_get(req, "p_vars"); | 2916 | p_vars = xs_dict_get(req, "p_vars"); |
| @@ -3049,7 +3049,7 @@ int html_post_handler(const xs_dict *req, const char *q_path, | |||
| 3049 | history_del(&snac, "timeline.html_"); | 3049 | history_del(&snac, "timeline.html_"); |
| 3050 | } | 3050 | } |
| 3051 | 3051 | ||
| 3052 | status = 303; | 3052 | status = HTTP_STATUS_SEE_OTHER; |
| 3053 | } | 3053 | } |
| 3054 | else | 3054 | else |
| 3055 | if (p_path && strcmp(p_path, "admin/action") == 0) { /** **/ | 3055 | if (p_path && strcmp(p_path, "admin/action") == 0) { /** **/ |
| @@ -3060,11 +3060,11 @@ int html_post_handler(const xs_dict *req, const char *q_path, | |||
| 3060 | const char *group = xs_dict_get(p_vars, "group"); | 3060 | const char *group = xs_dict_get(p_vars, "group"); |
| 3061 | 3061 | ||
| 3062 | if (action == NULL) | 3062 | if (action == NULL) |
| 3063 | return 404; | 3063 | return HTTP_STATUS_NOT_FOUND; |
| 3064 | 3064 | ||
| 3065 | snac_debug(&snac, 1, xs_fmt("web action '%s' received", action)); | 3065 | snac_debug(&snac, 1, xs_fmt("web action '%s' received", action)); |
| 3066 | 3066 | ||
| 3067 | status = 303; | 3067 | status = HTTP_STATUS_SEE_OTHER; |
| 3068 | 3068 | ||
| 3069 | if (strcmp(action, L("Like")) == 0) { /** **/ | 3069 | if (strcmp(action, L("Like")) == 0) { /** **/ |
| 3070 | xs *msg = msg_admiration(&snac, id, "Like"); | 3070 | xs *msg = msg_admiration(&snac, id, "Like"); |
| @@ -3216,10 +3216,10 @@ int html_post_handler(const xs_dict *req, const char *q_path, | |||
| 3216 | timeline_touch(&snac); | 3216 | timeline_touch(&snac); |
| 3217 | } | 3217 | } |
| 3218 | else | 3218 | else |
| 3219 | status = 404; | 3219 | status = HTTP_STATUS_NOT_FOUND; |
| 3220 | 3220 | ||
| 3221 | /* delete the cached timeline */ | 3221 | /* delete the cached timeline */ |
| 3222 | if (status == 303) | 3222 | if (status == HTTP_STATUS_SEE_OTHER) |
| 3223 | history_del(&snac, "timeline.html_"); | 3223 | history_del(&snac, "timeline.html_"); |
| 3224 | } | 3224 | } |
| 3225 | else | 3225 | else |
| @@ -3356,14 +3356,14 @@ int html_post_handler(const xs_dict *req, const char *q_path, | |||
| 3356 | 3356 | ||
| 3357 | enqueue_verify_links(&snac); | 3357 | enqueue_verify_links(&snac); |
| 3358 | 3358 | ||
| 3359 | status = 303; | 3359 | status = HTTP_STATUS_SEE_OTHER; |
| 3360 | } | 3360 | } |
| 3361 | else | 3361 | else |
| 3362 | if (p_path && strcmp(p_path, "admin/clear-notifications") == 0) { /** **/ | 3362 | if (p_path && strcmp(p_path, "admin/clear-notifications") == 0) { /** **/ |
| 3363 | notify_clear(&snac); | 3363 | notify_clear(&snac); |
| 3364 | timeline_touch(&snac); | 3364 | timeline_touch(&snac); |
| 3365 | 3365 | ||
| 3366 | status = 303; | 3366 | status = HTTP_STATUS_SEE_OTHER; |
| 3367 | } | 3367 | } |
| 3368 | else | 3368 | else |
| 3369 | if (p_path && strcmp(p_path, "admin/vote") == 0) { /** **/ | 3369 | if (p_path && strcmp(p_path, "admin/vote") == 0) { /** **/ |
| @@ -3416,10 +3416,10 @@ int html_post_handler(const xs_dict *req, const char *q_path, | |||
| 3416 | } | 3416 | } |
| 3417 | } | 3417 | } |
| 3418 | 3418 | ||
| 3419 | status = 303; | 3419 | status = HTTP_STATUS_SEE_OTHER; |
| 3420 | } | 3420 | } |
| 3421 | 3421 | ||
| 3422 | if (status == 303) { | 3422 | if (status == HTTP_STATUS_SEE_OTHER) { |
| 3423 | const char *redir = xs_dict_get(p_vars, "redir"); | 3423 | const char *redir = xs_dict_get(p_vars, "redir"); |
| 3424 | 3424 | ||
| 3425 | if (xs_is_null(redir)) | 3425 | if (xs_is_null(redir)) |