| | @@ -763,11 +763,11 @@ |
| 763 | 763 | if( g.perm.Setup ){ |
| 764 | 764 | @ (%d(rid)) |
| 765 | 765 | } |
| 766 | 766 | modPending = moderation_pending(rid); |
| 767 | 767 | if( modPending ){ |
| 768 | | - @ <span class="modpending">*** Moderation Pending ***</span> |
| 768 | + @ <span class="modpending">*** Awaiting Moderator Approval ***</span> |
| 769 | 769 | } |
| 770 | 770 | @ </td></tr> |
| 771 | 771 | @ <tr><th>Page Name:</th><td>%h(pWiki->zWikiTitle)</td></tr> |
| 772 | 772 | @ <tr><th>Date:</th><td> |
| 773 | 773 | hyperlink_to_date(zDate, "</td></tr>"); |
| | @@ -1439,11 +1439,15 @@ |
| 1439 | 1439 | g.zTop, zUuid); |
| 1440 | 1440 | } |
| 1441 | 1441 | } |
| 1442 | 1442 | style_header("Hex Artifact Content"); |
| 1443 | 1443 | zUuid = db_text("?","SELECT uuid FROM blob WHERE rid=%d", rid); |
| 1444 | | - @ <h2>Artifact %s(zUuid):</h2> |
| 1444 | + if( g.perm.Setup ){ |
| 1445 | + @ <h2>Artifact %s(zUuid) (%d(rid)):</h2> |
| 1446 | + }else{ |
| 1447 | + @ <h2>Artifact %s(zUuid):</h2> |
| 1448 | + } |
| 1445 | 1449 | blob_zero(&downloadName); |
| 1446 | 1450 | object_description(rid, 0, &downloadName); |
| 1447 | 1451 | style_submenu_element("Download", "Download", |
| 1448 | 1452 | "%s/raw/%T?name=%s", g.zTop, blob_str(&downloadName), zUuid); |
| 1449 | 1453 | @ <hr /> |
| | @@ -1586,11 +1590,15 @@ |
| 1586 | 1590 | g.zTop, zUuid); |
| 1587 | 1591 | } |
| 1588 | 1592 | } |
| 1589 | 1593 | style_header("Artifact Content"); |
| 1590 | 1594 | zUuid = db_text("?", "SELECT uuid FROM blob WHERE rid=%d", rid); |
| 1591 | | - @ <h2>Artifact %s(zUuid)</h2> |
| 1595 | + if( g.perm.Setup ){ |
| 1596 | + @ <h2>Artifact %s(zUuid) (%d(rid)):</h2> |
| 1597 | + }else{ |
| 1598 | + @ <h2>Artifact %s(zUuid):</h2> |
| 1599 | + } |
| 1592 | 1600 | blob_zero(&downloadName); |
| 1593 | 1601 | objType = object_description(rid, 0, &downloadName); |
| 1594 | 1602 | style_submenu_element("Download", "Download", |
| 1595 | 1603 | "%s/raw/%T?name=%s", g.zTop, blob_str(&downloadName), zUuid); |
| 1596 | 1604 | asText = P("txt")!=0; |
| | @@ -1682,15 +1690,13 @@ |
| 1682 | 1690 | style_submenu_element("Shun","Shun", "%s/shun?shun=%s#addshun", |
| 1683 | 1691 | g.zTop, zUuid); |
| 1684 | 1692 | } |
| 1685 | 1693 | } |
| 1686 | 1694 | pTktChng = manifest_get(rid, CFTYPE_TICKET); |
| 1695 | + if( pTktChng==0 ) fossil_redirect_home(); |
| 1687 | 1696 | zDate = db_text(0, "SELECT datetime(%.12f)", pTktChng->rDate); |
| 1688 | 1697 | memcpy(zTktName, pTktChng->zTicketUuid, UUID_SIZE+1); |
| 1689 | | - if( pTktChng==0 ){ |
| 1690 | | - fossil_redirect_home(); |
| 1691 | | - } |
| 1692 | 1698 | if( g.perm.ModTkt && (zModAction = P("modaction"))!=0 ){ |
| 1693 | 1699 | if( strcmp(zModAction,"delete")==0 ){ |
| 1694 | 1700 | moderation_disapprove(rid); |
| 1695 | 1701 | cgi_redirectf("%R/tktview/%s", zTktName); |
| 1696 | 1702 | /*NOTREACHED*/ |
| | @@ -1712,11 +1718,11 @@ |
| 1712 | 1718 | if( g.perm.Setup ){ |
| 1713 | 1719 | @ (%d(rid)) |
| 1714 | 1720 | } |
| 1715 | 1721 | modPending = moderation_pending(rid); |
| 1716 | 1722 | if( modPending ){ |
| 1717 | | - @ <span class="modpending">*** Moderation Pending ***</span> |
| 1723 | + @ <span class="modpending">*** Awaiting Moderator Approval ***</span> |
| 1718 | 1724 | } |
| 1719 | 1725 | @ <tr><th>Ticket:</th> |
| 1720 | 1726 | @ <td>%z(href("%R/tktview/%s",zTktName))%s(zTktName)</a></td></tr> |
| 1721 | 1727 | @ <tr><th>Date:</th><td> |
| 1722 | 1728 | hyperlink_to_date(zDate, "</td></tr>"); |
| | @@ -1742,10 +1748,163 @@ |
| 1742 | 1748 | @ <p> |
| 1743 | 1749 | ticket_output_change_artifact(pTktChng); |
| 1744 | 1750 | manifest_destroy(pTktChng); |
| 1745 | 1751 | style_footer(); |
| 1746 | 1752 | } |
| 1753 | + |
| 1754 | +/* |
| 1755 | +** WEBPAGE: ainfo |
| 1756 | +** URL: /ainfo?name=ARTIFACTID |
| 1757 | +** |
| 1758 | +** Show the details of an attachment artifact. |
| 1759 | +*/ |
| 1760 | +void ainfo_page(void){ |
| 1761 | + int rid; /* RID for the control artifact */ |
| 1762 | + int ridSrc; /* RID for the attached file */ |
| 1763 | + char *zDate; /* Date attached */ |
| 1764 | + const char *zUuid; /* UUID of the control artifact */ |
| 1765 | + Manifest *pAttach; /* Parse of the control artifact */ |
| 1766 | + const char *zTarget; /* Wiki or ticket attached to */ |
| 1767 | + const char *zSrc; /* UUID of the attached file */ |
| 1768 | + const char *zName; /* Name of the attached file */ |
| 1769 | + const char *zDesc; /* Description of the attached file */ |
| 1770 | + const char *zWikiName = 0; /* Wiki page name when attached to Wiki */ |
| 1771 | + const char *zTktUuid = 0; /* Ticket ID when attached to a ticket */ |
| 1772 | + int modPending; /* True if awaiting moderation */ |
| 1773 | + const char *zModAction; /* Moderation action or NULL */ |
| 1774 | + int isModerator; /* TRUE if user is the moderator */ |
| 1775 | + const char *zMime; /* MIME Type */ |
| 1776 | + Blob attach; /* Content of the attachment */ |
| 1777 | + |
| 1778 | + login_check_credentials(); |
| 1779 | + if( !g.perm.Attach ){ login_needed(); return; } |
| 1780 | + rid = name_to_rid_www("name"); |
| 1781 | + if( rid==0 ){ fossil_redirect_home(); } |
| 1782 | + zUuid = db_text("", "SELECT uuid FROM blob WHERE rid=%d", rid); |
| 1783 | +#if 0 |
| 1784 | + /* Shunning here needs to get both the attachment control artifact and |
| 1785 | + ** the object that is attached. */ |
| 1786 | + if( g.perm.Admin ){ |
| 1787 | + if( db_exists("SELECT 1 FROM shun WHERE uuid='%s'", zUuid) ){ |
| 1788 | + style_submenu_element("Unshun","Unshun", "%s/shun?uuid=%s&sub=1", |
| 1789 | + g.zTop, zUuid); |
| 1790 | + }else{ |
| 1791 | + style_submenu_element("Shun","Shun", "%s/shun?shun=%s#addshun", |
| 1792 | + g.zTop, zUuid); |
| 1793 | + } |
| 1794 | + } |
| 1795 | +#endif |
| 1796 | + pAttach = manifest_get(rid, CFTYPE_ATTACHMENT); |
| 1797 | + if( pAttach==0 ) fossil_redirect_home(); |
| 1798 | + zTarget = pAttach->zAttachTarget; |
| 1799 | + zSrc = pAttach->zAttachSrc; |
| 1800 | + ridSrc = db_int(0,"SELECT rid FROM blob WHERE uuid='%s'", zSrc); |
| 1801 | + zName = pAttach->zAttachName; |
| 1802 | + zDesc = pAttach->zComment; |
| 1803 | + if( validate16(zTarget, strlen(zTarget)) |
| 1804 | + && db_exists("SELECT 1 FROM ticket WHERE tkt_uuid='%s'", zTarget) |
| 1805 | + ){ |
| 1806 | + zTktUuid = zTarget; |
| 1807 | + }else if( db_exists("SELECT 1 FROM tag WHERE tagname='wiki-%q'",zTarget) ){ |
| 1808 | + zWikiName = zTarget; |
| 1809 | + } |
| 1810 | + zDate = db_text(0, "SELECT datetime(%.12f)", pAttach->rDate); |
| 1811 | + isModerator = (zTktUuid && g.perm.ModTkt) || (zWikiName && g.perm.ModWiki); |
| 1812 | + if( isModerator && (zModAction = P("modaction"))!=0 ){ |
| 1813 | + if( strcmp(zModAction,"delete")==0 ){ |
| 1814 | + moderation_disapprove(rid); |
| 1815 | + if( zTktUuid ){ |
| 1816 | + cgi_redirectf("%R/tktview/%s", zTktUuid); |
| 1817 | + }else{ |
| 1818 | + cgi_redirectf("%R/wiki?name=%t", zWikiName); |
| 1819 | + } |
| 1820 | + return; |
| 1821 | + } |
| 1822 | + if( strcmp(zModAction,"approve")==0 ){ |
| 1823 | + moderation_approve(rid); |
| 1824 | + } |
| 1825 | + } |
| 1826 | + style_header("Attachment Details"); |
| 1827 | + style_submenu_element("Raw", "Raw", "%R/artifact/%S", zUuid); |
| 1828 | + |
| 1829 | + @ <div class="section">Overview</div> |
| 1830 | + @ <p><table class="label-value"> |
| 1831 | + @ <tr><th>Artifact ID:</th> |
| 1832 | + @ <td>%z(href("%R/artifact/%s",zUuid))%s(zUuid)</a> |
| 1833 | + if( g.perm.Setup ){ |
| 1834 | + @ (%d(rid)) |
| 1835 | + } |
| 1836 | + modPending = moderation_pending(rid); |
| 1837 | + if( modPending ){ |
| 1838 | + @ <span class="modpending">*** Awaiting Moderator Approval ***</span> |
| 1839 | + } |
| 1840 | + if( zTktUuid ){ |
| 1841 | + @ <tr><th>Ticket:</th> |
| 1842 | + @ <td>%z(href("%R/tktview/%s",zTktUuid))%s(zTktUuid)</a></td></tr> |
| 1843 | + } |
| 1844 | + if( zWikiName ){ |
| 1845 | + @ <tr><th>Wiki Page:</th> |
| 1846 | + @ <td>%z(href("%R/wiki?name=%t",zWikiName))%h(zWikiName)</a></td></tr> |
| 1847 | + } |
| 1848 | + @ <tr><th>Date:</th><td> |
| 1849 | + hyperlink_to_date(zDate, "</td></tr>"); |
| 1850 | + free(zDate); |
| 1851 | + @ <tr><th>User:</th><td> |
| 1852 | + hyperlink_to_user(pAttach->zUser, zDate, "</td></tr>"); |
| 1853 | + @ <tr><th>Artifact Attached:</th> |
| 1854 | + @ <td>%z(href("%R/artifact/%s",zSrc))%s(zSrc)</a> |
| 1855 | + if( g.perm.Setup ){ |
| 1856 | + @ (%d(ridSrc)) |
| 1857 | + } |
| 1858 | + @ <tr><th>Filename:</th><td>%h(zName)</td></tr> |
| 1859 | + zMime = mimetype_from_name(zName); |
| 1860 | + if( g.perm.Setup ){ |
| 1861 | + @ <tr><th>MIME-Type:</th><td>%h(zMime)</td></tr> |
| 1862 | + } |
| 1863 | + @ <tr><th valign="top">Description:</th><td valign="top">%h(zDesc)</td></tr> |
| 1864 | + @ </table> |
| 1865 | + |
| 1866 | + if( isModerator && modPending ){ |
| 1867 | + @ <div class="section">Moderation</div> |
| 1868 | + @ <blockquote> |
| 1869 | + @ <form method="POST" action="%R/ainfo/%s(zUuid)"> |
| 1870 | + @ <label><input type="radio" name="modaction" value="delete"> |
| 1871 | + @ Delete this change</label><br /> |
| 1872 | + @ <label><input type="radio" name="modaction" value="approve"> |
| 1873 | + @ Approve this change</label><br /> |
| 1874 | + @ <input type="submit" value="Submit"> |
| 1875 | + @ </form> |
| 1876 | + @ </blockquote> |
| 1877 | + } |
| 1878 | + |
| 1879 | + @ <div class="section">Content Appended</div> |
| 1880 | + @ <blockquote> |
| 1881 | + blob_zero(&attach); |
| 1882 | + if( zMime==0 || strncmp(zMime,"text/", 5)==0 ){ |
| 1883 | + const char *z; |
| 1884 | + const char *zLn = P("ln"); |
| 1885 | + content_get(ridSrc, &attach); |
| 1886 | + blob_strip_bom(&attach, 0); |
| 1887 | + z = blob_str(&attach); |
| 1888 | + if( zLn ){ |
| 1889 | + output_text_with_line_numbers(z, zLn); |
| 1890 | + }else{ |
| 1891 | + @ <pre> |
| 1892 | + @ %h(z) |
| 1893 | + @ </pre> |
| 1894 | + } |
| 1895 | + }else if( strncmp(zMime, "image/", 6)==0 ){ |
| 1896 | + @ <img src="%R/raw?name=%s(zSrc)&m=%s(zMime)"></img> |
| 1897 | + }else{ |
| 1898 | + int sz = db_int(0, "SELECT sz FROM blob WHERE rid=%d", ridSrc); |
| 1899 | + @ <i>(file is %d(sz) bytes of binary data)</i> |
| 1900 | + } |
| 1901 | + @ </blockquote> |
| 1902 | + manifest_destroy(pAttach); |
| 1903 | + blob_reset(&attach); |
| 1904 | + style_footer(); |
| 1905 | +} |
| 1747 | 1906 | |
| 1748 | 1907 | |
| 1749 | 1908 | /* |
| 1750 | 1909 | ** WEBPAGE: info |
| 1751 | 1910 | ** URL: info/ARTIFACTID |
| | @@ -1807,10 +1966,13 @@ |
| 1807 | 1966 | if( db_exists("SELECT 1 FROM plink WHERE cid=%d", rid) ){ |
| 1808 | 1967 | ci_page(); |
| 1809 | 1968 | }else |
| 1810 | 1969 | if( db_exists("SELECT 1 FROM plink WHERE pid=%d", rid) ){ |
| 1811 | 1970 | ci_page(); |
| 1971 | + }else |
| 1972 | + if( db_exists("SELECT 1 FROM attachment WHERE attachid=%d", rid) ){ |
| 1973 | + ainfo_page(); |
| 1812 | 1974 | }else |
| 1813 | 1975 | { |
| 1814 | 1976 | artifact_page(); |
| 1815 | 1977 | } |
| 1816 | 1978 | } |
| 1817 | 1979 | |