Fossil SCM
prefill the tktnew page email field with user emailaddr If the logged-in user has a valid email address in their contact-info, use it to prefill the email field in the /tktnew page when submitting a new ticket. As discussed in /chat, enhance the Fossil builtin find_emailaddr() SQL function--suggested by wyoung@--to parse strings for well-formed email addresses not necessarily wrapped in <...>. Requested by jose i cabrera on the [forum:62838ffe73|forum].
Commit
f974583f903a17f64f0f626072bd4a9820f5901731da4c08ee05e96fee811e29
Parent
3fe8a8cd18aa897…
2 files changed
+11
-10
+12
-1
+11
-10
| --- src/alerts.c | ||
| +++ src/alerts.c | ||
| @@ -714,12 +714,12 @@ | ||
| 714 | 714 | |
| 715 | 715 | /* |
| 716 | 716 | ** Make a copy of the input string up to but not including the |
| 717 | 717 | ** first cTerm character. |
| 718 | 718 | ** |
| 719 | -** Verify that the string really that is to be copied really is a | |
| 720 | -** valid email address. If it is not, then return NULL. | |
| 719 | +** Verify that the string to be copied really is a valid | |
| 720 | +** email address. If it is not, then return NULL. | |
| 721 | 721 | ** |
| 722 | 722 | ** This routine is more restrictive than necessary. It does not |
| 723 | 723 | ** allow comments, IP address, quoted strings, or certain uncommon |
| 724 | 724 | ** characters. The only non-alphanumerics allowed in the local |
| 725 | 725 | ** part are "_", "+", "-" and "+". |
| @@ -728,24 +728,25 @@ | ||
| 728 | 728 | int i = email_address_is_valid(z, cTerm); |
| 729 | 729 | return i==0 ? 0 : mprintf("%.*s", i, z); |
| 730 | 730 | } |
| 731 | 731 | |
| 732 | 732 | /* |
| 733 | -** Scan the input string for a valid email address enclosed in <...> | |
| 733 | +** Scan the input string for a valid email address that may be | |
| 734 | +** enclosed in <...>, or delimited by ',' or ':' or '=' or ' '. | |
| 734 | 735 | ** If the string contains one or more email addresses, extract the first |
| 735 | 736 | ** one into memory obtained from mprintf() and return a pointer to it. |
| 736 | 737 | ** If no valid email address can be found, return NULL. |
| 737 | 738 | */ |
| 738 | 739 | char *alert_find_emailaddr(const char *zIn){ |
| 739 | 740 | char *zOut = 0; |
| 740 | - while( zIn!=0 ){ | |
| 741 | - zIn = (const char*)strchr(zIn, '<'); | |
| 742 | - if( zIn==0 ) break; | |
| 743 | - zIn++; | |
| 744 | - zOut = email_copy_addr(zIn, '>'); | |
| 745 | - if( zOut!=0 ) break; | |
| 746 | - } | |
| 741 | + do{ | |
| 742 | + zOut = email_copy_addr(zIn, zIn[strcspn(zIn, ">,:= ")]); | |
| 743 | + if( zOut!=0 ) break; | |
| 744 | + zIn = (const char *)strpbrk(zIn, "<,:= "); | |
| 745 | + if( zIn==0 ) break; | |
| 746 | + zIn++; | |
| 747 | + }while( zIn!=0 ); | |
| 747 | 748 | return zOut; |
| 748 | 749 | } |
| 749 | 750 | |
| 750 | 751 | /* |
| 751 | 752 | ** SQL function: find_emailaddr(X) |
| 752 | 753 |
| --- src/alerts.c | |
| +++ src/alerts.c | |
| @@ -714,12 +714,12 @@ | |
| 714 | |
| 715 | /* |
| 716 | ** Make a copy of the input string up to but not including the |
| 717 | ** first cTerm character. |
| 718 | ** |
| 719 | ** Verify that the string really that is to be copied really is a |
| 720 | ** valid email address. If it is not, then return NULL. |
| 721 | ** |
| 722 | ** This routine is more restrictive than necessary. It does not |
| 723 | ** allow comments, IP address, quoted strings, or certain uncommon |
| 724 | ** characters. The only non-alphanumerics allowed in the local |
| 725 | ** part are "_", "+", "-" and "+". |
| @@ -728,24 +728,25 @@ | |
| 728 | int i = email_address_is_valid(z, cTerm); |
| 729 | return i==0 ? 0 : mprintf("%.*s", i, z); |
| 730 | } |
| 731 | |
| 732 | /* |
| 733 | ** Scan the input string for a valid email address enclosed in <...> |
| 734 | ** If the string contains one or more email addresses, extract the first |
| 735 | ** one into memory obtained from mprintf() and return a pointer to it. |
| 736 | ** If no valid email address can be found, return NULL. |
| 737 | */ |
| 738 | char *alert_find_emailaddr(const char *zIn){ |
| 739 | char *zOut = 0; |
| 740 | while( zIn!=0 ){ |
| 741 | zIn = (const char*)strchr(zIn, '<'); |
| 742 | if( zIn==0 ) break; |
| 743 | zIn++; |
| 744 | zOut = email_copy_addr(zIn, '>'); |
| 745 | if( zOut!=0 ) break; |
| 746 | } |
| 747 | return zOut; |
| 748 | } |
| 749 | |
| 750 | /* |
| 751 | ** SQL function: find_emailaddr(X) |
| 752 |
| --- src/alerts.c | |
| +++ src/alerts.c | |
| @@ -714,12 +714,12 @@ | |
| 714 | |
| 715 | /* |
| 716 | ** Make a copy of the input string up to but not including the |
| 717 | ** first cTerm character. |
| 718 | ** |
| 719 | ** Verify that the string to be copied really is a valid |
| 720 | ** email address. If it is not, then return NULL. |
| 721 | ** |
| 722 | ** This routine is more restrictive than necessary. It does not |
| 723 | ** allow comments, IP address, quoted strings, or certain uncommon |
| 724 | ** characters. The only non-alphanumerics allowed in the local |
| 725 | ** part are "_", "+", "-" and "+". |
| @@ -728,24 +728,25 @@ | |
| 728 | int i = email_address_is_valid(z, cTerm); |
| 729 | return i==0 ? 0 : mprintf("%.*s", i, z); |
| 730 | } |
| 731 | |
| 732 | /* |
| 733 | ** Scan the input string for a valid email address that may be |
| 734 | ** enclosed in <...>, or delimited by ',' or ':' or '=' or ' '. |
| 735 | ** If the string contains one or more email addresses, extract the first |
| 736 | ** one into memory obtained from mprintf() and return a pointer to it. |
| 737 | ** If no valid email address can be found, return NULL. |
| 738 | */ |
| 739 | char *alert_find_emailaddr(const char *zIn){ |
| 740 | char *zOut = 0; |
| 741 | do{ |
| 742 | zOut = email_copy_addr(zIn, zIn[strcspn(zIn, ">,:= ")]); |
| 743 | if( zOut!=0 ) break; |
| 744 | zIn = (const char *)strpbrk(zIn, "<,:= "); |
| 745 | if( zIn==0 ) break; |
| 746 | zIn++; |
| 747 | }while( zIn!=0 ); |
| 748 | return zOut; |
| 749 | } |
| 750 | |
| 751 | /* |
| 752 | ** SQL function: find_emailaddr(X) |
| 753 |
+12
-1
| --- src/tkt.c | ||
| +++ src/tkt.c | ||
| @@ -995,11 +995,12 @@ | ||
| 995 | 995 | ** when you press submit - it just prints the ticket artifact at the |
| 996 | 996 | ** top of the screen. |
| 997 | 997 | */ |
| 998 | 998 | void tktnew_page(void){ |
| 999 | 999 | const char *zScript; |
| 1000 | - char *zNewUuid = 0; | |
| 1000 | + char *zEmail = 0, *zNewUuid = 0; | |
| 1001 | + int uid; | |
| 1001 | 1002 | |
| 1002 | 1003 | login_check_credentials(); |
| 1003 | 1004 | if( !g.perm.NewTkt ){ login_needed(g.anon.NewTkt); return; } |
| 1004 | 1005 | if( P("cancel") ){ |
| 1005 | 1006 | cgi_redirect("home"); |
| @@ -1017,10 +1018,20 @@ | ||
| 1017 | 1018 | login_insert_csrf_secret(); |
| 1018 | 1019 | if( P("date_override") && g.perm.Setup ){ |
| 1019 | 1020 | @ <input type="hidden" name="date_override" value="%h(P("date_override"))"> |
| 1020 | 1021 | } |
| 1021 | 1022 | zScript = ticket_newpage_code(); |
| 1023 | + if( g.zLogin && g.zLogin[0] ){ | |
| 1024 | + uid = db_int(0, "SELECT uid FROM user WHERE login=%Q", g.zLogin); | |
| 1025 | + if( uid ){ | |
| 1026 | + zEmail = db_text(0, "SELECT find_emailaddr(info) FROM user WHERE uid=%d", | |
| 1027 | + uid); | |
| 1028 | + if( zEmail ){ | |
| 1029 | + Th_Store("private_contact", zEmail); | |
| 1030 | + } | |
| 1031 | + } | |
| 1032 | + } | |
| 1022 | 1033 | Th_Store("login", login_name()); |
| 1023 | 1034 | Th_Store("date", db_text(0, "SELECT datetime('now')")); |
| 1024 | 1035 | Th_CreateCommand(g.interp, "submit_ticket", submitTicketCmd, |
| 1025 | 1036 | (void*)&zNewUuid, 0); |
| 1026 | 1037 | if( g.thTrace ) Th_Trace("BEGIN_TKTNEW_SCRIPT<br />\n", -1); |
| 1027 | 1038 |
| --- src/tkt.c | |
| +++ src/tkt.c | |
| @@ -995,11 +995,12 @@ | |
| 995 | ** when you press submit - it just prints the ticket artifact at the |
| 996 | ** top of the screen. |
| 997 | */ |
| 998 | void tktnew_page(void){ |
| 999 | const char *zScript; |
| 1000 | char *zNewUuid = 0; |
| 1001 | |
| 1002 | login_check_credentials(); |
| 1003 | if( !g.perm.NewTkt ){ login_needed(g.anon.NewTkt); return; } |
| 1004 | if( P("cancel") ){ |
| 1005 | cgi_redirect("home"); |
| @@ -1017,10 +1018,20 @@ | |
| 1017 | login_insert_csrf_secret(); |
| 1018 | if( P("date_override") && g.perm.Setup ){ |
| 1019 | @ <input type="hidden" name="date_override" value="%h(P("date_override"))"> |
| 1020 | } |
| 1021 | zScript = ticket_newpage_code(); |
| 1022 | Th_Store("login", login_name()); |
| 1023 | Th_Store("date", db_text(0, "SELECT datetime('now')")); |
| 1024 | Th_CreateCommand(g.interp, "submit_ticket", submitTicketCmd, |
| 1025 | (void*)&zNewUuid, 0); |
| 1026 | if( g.thTrace ) Th_Trace("BEGIN_TKTNEW_SCRIPT<br />\n", -1); |
| 1027 |
| --- src/tkt.c | |
| +++ src/tkt.c | |
| @@ -995,11 +995,12 @@ | |
| 995 | ** when you press submit - it just prints the ticket artifact at the |
| 996 | ** top of the screen. |
| 997 | */ |
| 998 | void tktnew_page(void){ |
| 999 | const char *zScript; |
| 1000 | char *zEmail = 0, *zNewUuid = 0; |
| 1001 | int uid; |
| 1002 | |
| 1003 | login_check_credentials(); |
| 1004 | if( !g.perm.NewTkt ){ login_needed(g.anon.NewTkt); return; } |
| 1005 | if( P("cancel") ){ |
| 1006 | cgi_redirect("home"); |
| @@ -1017,10 +1018,20 @@ | |
| 1018 | login_insert_csrf_secret(); |
| 1019 | if( P("date_override") && g.perm.Setup ){ |
| 1020 | @ <input type="hidden" name="date_override" value="%h(P("date_override"))"> |
| 1021 | } |
| 1022 | zScript = ticket_newpage_code(); |
| 1023 | if( g.zLogin && g.zLogin[0] ){ |
| 1024 | uid = db_int(0, "SELECT uid FROM user WHERE login=%Q", g.zLogin); |
| 1025 | if( uid ){ |
| 1026 | zEmail = db_text(0, "SELECT find_emailaddr(info) FROM user WHERE uid=%d", |
| 1027 | uid); |
| 1028 | if( zEmail ){ |
| 1029 | Th_Store("private_contact", zEmail); |
| 1030 | } |
| 1031 | } |
| 1032 | } |
| 1033 | Th_Store("login", login_name()); |
| 1034 | Th_Store("date", db_text(0, "SELECT datetime('now')")); |
| 1035 | Th_CreateCommand(g.interp, "submit_ticket", submitTicketCmd, |
| 1036 | (void*)&zNewUuid, 0); |
| 1037 | if( g.thTrace ) Th_Trace("BEGIN_TKTNEW_SCRIPT<br />\n", -1); |
| 1038 |