Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Difference From c3e7ed308900482e To 6f70a236ce66fa2a
2022-08-29
| ||
14:27 | Add a missing closing LI tag for the /tkthistory page. ... (check-in: 2d0b2bda user: george tags: deltify-tkt-blobs) | |
14:03 |
Minor optimization within getAllTicketFields() function.
...
(check-in: c3e7ed30 user: george tags: deltify-tkt-blobs)
| |
2022-08-23
| ||
11:14 | Correct a NULL being passed to strcmp() which caused any submit of JS script code in the skin editor to segfault. Reported in forum post 9d9f0580fd. ... (check-in: a8847839 user: stephan tags: trunk) | |
2022-08-22
| ||
18:27 |
Make it possible to store similar ticket change artifacts as deltas.
This might be useful when a certain column of the TICKET table
holds a lengthy text that may undergo frequent modifications.
This is an opt-in feature. It is activated only when TICKET table
contains a phony | |
2022-08-18
| ||
13:21 | Add the "Timeline" submenu link on the setup_edit page, for ordinary users. Change the "Access Log" link on that same page so that it is only present for ordinary users - not special users like "reader" or "developer". ... (check-in: 6f70a236 user: drh tags: trunk) | |
2022-08-17
| ||
05:30 | Removed a digression in the gitusers doc about Fossil's new clone-and-open mechanisms. That got moved to the ckout-workflows doc quite some time back, and we already point to it from that same section. There's no reason for the redundancy. Also cleaned up some grammar and typos while in there. ... (check-in: f43eaf01 user: wyoung tags: trunk) | |
Changes to src/tkt.c.
︙ | ︙ | |||
28 29 30 31 32 33 34 | ** use. The internal-use fields begin with "tkt_". */ static int nField = 0; static struct tktFieldInfo { char *zName; /* Name of the database field */ char *zValue; /* Value to store */ char *zAppend; /* Value to append */ | < < < < < | 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 | ** use. The internal-use fields begin with "tkt_". */ static int nField = 0; static struct tktFieldInfo { char *zName; /* Name of the database field */ char *zValue; /* Value to store */ char *zAppend; /* Value to append */ unsigned mUsed; /* 01: TICKET 02: TICKETCHNG */ } *aField; #define USEDBY_TICKET 01 #define USEDBY_TICKETCHNG 02 #define USEDBY_BOTH 03 static u8 haveTicket = 0; /* True if the TICKET table exists */ static u8 haveTicketCTime = 0; /* True if TICKET.TKT_CTIME exists */ static u8 haveTicketChng = 0; /* True if the TICKETCHNG table exists */ static u8 haveTicketChngRid = 0; /* True if TICKETCHNG.TKT_RID exists */ static u8 haveTicketChngUser = 0;/* True if TICKETCHNG.TKT_USER exists */ static u8 useTicketGenMt = 0; /* use generated TICKET.MIMETYPE */ static u8 useTicketChngGenMt = 0;/* use generated TICKETCHNG.MIMETYPE */ /* ** Compare two entries in aField[] for sorting purposes */ static int nameCmpr(const void *a, const void *b){ return fossil_strcmp(((const struct tktFieldInfo*)a)->zName, |
︙ | ︙ | |||
76 77 78 79 80 81 82 | ** in sorted order in aField[]. ** ** The haveTicket and haveTicketChng variables are set to 1 if the TICKET and ** TICKETCHANGE tables exist, respectively. */ static void getAllTicketFields(void){ Stmt q; | | < < < < < < < < < < < < < < < < < < < < < < < < < < | 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 | ** in sorted order in aField[]. ** ** The haveTicket and haveTicketChng variables are set to 1 if the TICKET and ** TICKETCHANGE tables exist, respectively. */ static void getAllTicketFields(void){ Stmt q; int i, noRegularMimetype; static int once = 0; if( once ) return; once = 1; db_prepare(&q, "PRAGMA table_info(ticket)"); while( db_step(&q)==SQLITE_ROW ){ const char *zFieldName = db_column_text(&q, 1); haveTicket = 1; if( memcmp(zFieldName,"tkt_",4)==0 ){ if( strcmp(zFieldName, "tkt_ctime")==0 ) haveTicketCTime = 1; continue; } if( strchr(zFieldName,' ')!=0 ) continue; if( nField%10==0 ){ aField = fossil_realloc(aField, sizeof(aField[0])*(nField+10) ); } aField[nField].zName = mprintf("%s", zFieldName); aField[nField].mUsed = USEDBY_TICKET; nField++; } db_finalize(&q); db_prepare(&q, "PRAGMA table_info(ticketchng)"); while( db_step(&q)==SQLITE_ROW ){ const char *zFieldName = db_column_text(&q, 1); haveTicketChng = 1; if( memcmp(zFieldName,"tkt_",4)==0 ){ if( strcmp(zFieldName+4,"rid")==0 ){ haveTicketChngRid = 1; /* tkt_rid */ }else if( strcmp(zFieldName+4,"user")==0 ){ haveTicketChngUser = 1; /* tkt_user */ } continue; } if( strchr(zFieldName,' ')!=0 ) continue; if( (i = fieldId(zFieldName))>=0 ){ aField[i].mUsed |= USEDBY_TICKETCHNG; continue; } if( nField%10==0 ){ aField = fossil_realloc(aField, sizeof(aField[0])*(nField+10) ); } aField[nField].zName = mprintf("%s", zFieldName); aField[nField].mUsed = USEDBY_TICKETCHNG; nField++; } db_finalize(&q); qsort(aField, nField, sizeof(aField[0]), nameCmpr); noRegularMimetype = 1; |
︙ | ︙ | |||
261 262 263 264 265 266 267 | blob_zero(&sql1); blob_zero(&sql2); blob_zero(&sql3); blob_append_sql(&sql1, "UPDATE OR REPLACE ticket SET tkt_mtime=:mtime"); if( haveTicketCTime ){ blob_append_sql(&sql1, ", tkt_ctime=coalesce(tkt_ctime,:mtime)"); } | | > < < < < | 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 | blob_zero(&sql1); blob_zero(&sql2); blob_zero(&sql3); blob_append_sql(&sql1, "UPDATE OR REPLACE ticket SET tkt_mtime=:mtime"); if( haveTicketCTime ){ blob_append_sql(&sql1, ", tkt_ctime=coalesce(tkt_ctime,:mtime)"); } aUsed = fossil_malloc( nField ); memset(aUsed, 0, nField); for(i=0; i<p->nField; i++){ const char * const zName = p->aField[i].zName; const char * const zBaseName = zName[0]=='+' ? zName+1 : zName; j = fieldId(zBaseName); if( j<0 ) continue; aUsed[j] = 1; if( aField[j].mUsed & USEDBY_TICKET ){ if( zName[0]=='+' ){ blob_append_sql(&sql1,", \"%w\"=coalesce(\"%w\",'') || %Q", zBaseName, zBaseName, p->aField[i].zValue); }else{ blob_append_sql(&sql1,", \"%w\"=%Q", zBaseName, p->aField[i].zValue); } } if( aField[j].mUsed & USEDBY_TICKETCHNG ){ blob_append_sql(&sql2, ",\"%w\"", zBaseName); blob_append_sql(&sql3, ",%Q", p->aField[i].zValue); } if( strcmp(zBaseName,"mimetype")==0 ){ |
︙ | ︙ | |||
774 775 776 777 778 779 780 | /* ** Write a ticket into the repository. */ static int ticket_put( Blob *pTicket, /* The text of the ticket change record */ const char *zTktId, /* The ticket to which this change is applied */ | < < < < < < < < < < < < < < < < | 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 | /* ** Write a ticket into the repository. */ static int ticket_put( Blob *pTicket, /* The text of the ticket change record */ const char *zTktId, /* The ticket to which this change is applied */ int needMod /* True if moderation is needed */ ){ int result; int rid; manifest_crosslink_begin(); rid = content_put_ex(pTicket, 0, 0, 0, needMod); if( rid==0 ){ fossil_fatal("trouble committing ticket: %s", g.zErrMsg); } if( needMod ){ moderation_table_create(); db_multi_exec( "INSERT INTO modreq(objid, tktid) VALUES(%d,%Q)", rid, zTktId ); }else{ |
︙ | ︙ | |||
835 836 837 838 839 840 841 | static int submitTicketCmd( Th_Interp *interp, void *pUuid, int argc, const char **argv, int *argl ){ | | | < < < < | > | < < < | | 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 | static int submitTicketCmd( Th_Interp *interp, void *pUuid, int argc, const char **argv, int *argl ){ char *zDate; const char *zUuid; int i; int nJ = 0; Blob tktchng, cksum; int needMod; login_verify_csrf_secret(); if( !captcha_is_correct(0) ){ @ <p class="generalError">Error: Incorrect security code.</p> return TH_OK; } zUuid = (const char *)pUuid; blob_zero(&tktchng); zDate = date_in_standard_format("now"); blob_appendf(&tktchng, "D %s\n", zDate); free(zDate); for(i=0; i<nField; i++){ if( aField[i].zAppend ){ blob_appendf(&tktchng, "J +%s %z\n", aField[i].zName, fossilize(aField[i].zAppend, -1)); ++nJ; } } for(i=0; i<nField; i++){ const char *zValue; int nValue; if( aField[i].zAppend ) continue; zValue = Th_Fetch(aField[i].zName, &nValue); if( zValue ){ while( nValue>0 && fossil_isspace(zValue[nValue-1]) ){ nValue--; } if( ((aField[i].mUsed & USEDBY_TICKETCHNG)!=0 && nValue>0) || memcmp(zValue, aField[i].zValue, nValue)!=0 || strlen(aField[i].zValue)!=nValue ){ if( memcmp(aField[i].zName, "private_", 8)==0 ){ zValue = db_conceal(zValue, nValue); blob_appendf(&tktchng, "J %s %s\n", aField[i].zName, zValue); }else{ blob_appendf(&tktchng, "J %s %#F\n", aField[i].zName, nValue, zValue); } nJ++; } } } if( *(char**)pUuid ){ zUuid = db_text(0, "SELECT tkt_uuid FROM ticket WHERE tkt_uuid GLOB '%q*'", P("name") ); }else{ zUuid = db_text(0, "SELECT lower(hex(randomblob(20)))"); } *(const char**)pUuid = zUuid; blob_appendf(&tktchng, "K %s\n", zUuid); blob_appendf(&tktchng, "U %F\n", login_name()); md5sum_blob(&tktchng, &cksum); blob_appendf(&tktchng, "Z %b\n", &cksum); if( nJ==0 ){ blob_reset(&tktchng); return TH_OK; } needMod = ticket_need_moderation(0); if( g.zPath[0]=='d' ){ const char *zNeedMod = needMod ? "required" : "skipped"; /* If called from /debug_tktnew or /debug_tktedit... */ @ <div style="color:blue"> @ <p>Ticket artifact that would have been submitted:</p> @ <blockquote><pre>%h(blob_str(&tktchng))</pre></blockquote> @ <blockquote><pre>Moderation would be %h(zNeedMod).</pre></blockquote> @ </div> @ <hr /> return TH_OK; }else{ if( g.thTrace ){ Th_Trace("submit_ticket {\n<blockquote><pre>\n%h\n</pre></blockquote>\n" "}<br />\n", blob_str(&tktchng)); } ticket_put(&tktchng, zUuid, needMod); } return ticket_change(zUuid); } /* ** WEBPAGE: tktnew ** WEBPAGE: debug_tktnew ** |
︙ | ︙ | |||
1514 1515 1516 1517 1518 1519 1520 | rptshow( zRep, zSep, zFilterUuid, tktEncoding ); } }else{ /* add a new ticket or update an existing ticket */ enum { set,add,history,err } eCmd = err; int i = 0; Blob tktchng, cksum; | < | 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 | rptshow( zRep, zSep, zFilterUuid, tktEncoding ); } }else{ /* add a new ticket or update an existing ticket */ enum { set,add,history,err } eCmd = err; int i = 0; Blob tktchng, cksum; /* get command type (set/add) and get uuid, if needed for set */ if( strncmp(g.argv[2],"set",n)==0 || strncmp(g.argv[2],"change",n)==0 || strncmp(g.argv[2],"history",n)==0 ){ if( strncmp(g.argv[2],"history",n)==0 ){ eCmd = history; }else{ |
︙ | ︙ | |||
1657 1658 1659 1660 1661 1662 1663 | if( append ){ aField[j].zAppend = zFValue; }else{ aField[j].zValue = zFValue; } } } | < < < < | < < | 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 | if( append ){ aField[j].zAppend = zFValue; }else{ aField[j].zValue = zFValue; } } } /* now add the needed artifacts to the repository */ blob_zero(&tktchng); /* add the time to the ticket manifest */ blob_appendf(&tktchng, "D %s\n", zDate); /* append defined elements */ for(i=0; i<nField; i++){ char *zValue = 0; char *zPfx; if( aField[i].zAppend && aField[i].zAppend[0] ){ zPfx = " +"; zValue = aField[i].zAppend; }else if( aField[i].zValue && aField[i].zValue[0] ){ zPfx = " "; zValue = aField[i].zValue; }else{ continue; } if( memcmp(aField[i].zName, "private_", 8)==0 ){ zValue = db_conceal(zValue, strlen(zValue)); blob_appendf(&tktchng, "J%s%s %s\n", zPfx, aField[i].zName, zValue); }else{ blob_appendf(&tktchng, "J%s%s %#F\n", zPfx, aField[i].zName, strlen(zValue), zValue); } } blob_appendf(&tktchng, "K %s\n", zTktUuid); blob_appendf(&tktchng, "U %F\n", zUser); md5sum_blob(&tktchng, &cksum); blob_appendf(&tktchng, "Z %b\n", &cksum); if( ticket_put(&tktchng, zTktUuid, ticket_need_moderation(1))==0 ){ fossil_fatal("%s", g.zErrMsg); }else{ fossil_print("ticket %s succeeded for %s\n", (eCmd==set?"set":"add"),zTktUuid); } } } } #if INTERFACE /* Standard submenu items for wiki pages */ |
︙ | ︙ |