Fossil SCM
Further enhancements to the new /file webpage.
Commit
3cca4c254f885b0d2cd2af0127562d85971cfdf7
Parent
d95f712f2caba1e…
1 file changed
+54
-48
+54
-48
| --- src/info.c | ||
| +++ src/info.c | ||
| @@ -1565,11 +1565,11 @@ | ||
| 1565 | 1565 | char *zUuid; |
| 1566 | 1566 | const char *zMime; |
| 1567 | 1567 | Blob content; |
| 1568 | 1568 | |
| 1569 | 1569 | if( P("ci") && P("filename") ){ |
| 1570 | - rid = artifact_from_ci_and_filename_www(); | |
| 1570 | + rid = artifact_from_ci_and_filename(0); | |
| 1571 | 1571 | } |
| 1572 | 1572 | if( rid==0 ){ |
| 1573 | 1573 | rid = name_to_rid_www("name"); |
| 1574 | 1574 | } |
| 1575 | 1575 | login_check_credentials(); |
| @@ -1699,46 +1699,19 @@ | ||
| 1699 | 1699 | hexdump(&content); |
| 1700 | 1700 | @ </pre></blockquote> |
| 1701 | 1701 | style_footer(); |
| 1702 | 1702 | } |
| 1703 | 1703 | |
| 1704 | -/* | |
| 1705 | -** Attempt to lookup the specified check-in and file name into an rid. | |
| 1706 | -*/ | |
| 1707 | -int artifact_from_ci_and_filename( | |
| 1708 | - const char *zCI, | |
| 1709 | - const char *zFilename | |
| 1710 | -){ | |
| 1711 | - int cirid; | |
| 1712 | - Manifest *pManifest; | |
| 1713 | - ManifestFile *pFile; | |
| 1714 | - | |
| 1715 | - if( zCI==0 ) return 0; | |
| 1716 | - if( zFilename==0 ) return 0; | |
| 1717 | - cirid = name_to_rid(zCI); | |
| 1718 | - pManifest = manifest_get(cirid, CFTYPE_MANIFEST, 0); | |
| 1719 | - if( pManifest==0 ) return 0; | |
| 1720 | - manifest_file_rewind(pManifest); | |
| 1721 | - while( (pFile = manifest_file_next(pManifest,0))!=0 ){ | |
| 1722 | - if( fossil_strcmp(zFilename, pFile->zName)==0 ){ | |
| 1723 | - int rid = db_int(0, "SELECT rid FROM blob WHERE uuid=%Q", pFile->zUuid); | |
| 1724 | - manifest_destroy(pManifest); | |
| 1725 | - return rid; | |
| 1726 | - } | |
| 1727 | - } | |
| 1728 | - return 0; | |
| 1729 | -} | |
| 1730 | - | |
| 1731 | 1704 | /* |
| 1732 | 1705 | ** Look for "ci" and "filename" query parameters. If found, try to |
| 1733 | 1706 | ** use them to extract the record ID of an artifact for the file. |
| 1734 | 1707 | ** |
| 1735 | 1708 | ** Also look for "fn" as an alias for "filename". If either "filename" |
| 1736 | 1709 | ** or "fn" is present but "ci" is missing, use "tip" as a default value |
| 1737 | 1710 | ** for "ci". |
| 1738 | 1711 | */ |
| 1739 | -int artifact_from_ci_and_filename_www(void){ | |
| 1712 | +int artifact_from_ci_and_filename(HQuery *pUrl){ | |
| 1740 | 1713 | const char *zFilename; |
| 1741 | 1714 | const char *zCI; |
| 1742 | 1715 | int cirid; |
| 1743 | 1716 | Manifest *pManifest; |
| 1744 | 1717 | ManifestFile *pFile; |
| @@ -1746,23 +1719,28 @@ | ||
| 1746 | 1719 | zFilename = P("filename"); |
| 1747 | 1720 | if( zFilename==0 ){ |
| 1748 | 1721 | zFilename = P("fn"); |
| 1749 | 1722 | if( zFilename==0 ) return 0; |
| 1750 | 1723 | } |
| 1751 | - zCI = PD("ci", "tip"); | |
| 1752 | - cirid = name_to_typed_rid(zCI, "ci"); | |
| 1724 | + zCI = P("ci"); | |
| 1725 | + cirid = name_to_typed_rid(zCI ? zCI : "tip", "ci"); | |
| 1753 | 1726 | if( cirid<=0 ) return 0; |
| 1754 | 1727 | pManifest = manifest_get(cirid, CFTYPE_MANIFEST, 0); |
| 1755 | 1728 | if( pManifest==0 ) return 0; |
| 1756 | 1729 | manifest_file_rewind(pManifest); |
| 1757 | 1730 | while( (pFile = manifest_file_next(pManifest,0))!=0 ){ |
| 1758 | 1731 | if( fossil_strcmp(zFilename, pFile->zName)==0 ){ |
| 1759 | 1732 | int rid = db_int(0, "SELECT rid FROM blob WHERE uuid=%Q", pFile->zUuid); |
| 1760 | 1733 | manifest_destroy(pManifest); |
| 1734 | + if( pUrl ){ | |
| 1735 | + url_add_parameter(pUrl, "fn", zFilename); | |
| 1736 | + if( zCI ) url_add_parameter(pUrl, "ci", zCI); | |
| 1737 | + } | |
| 1761 | 1738 | return rid; |
| 1762 | 1739 | } |
| 1763 | 1740 | } |
| 1741 | + manifest_destroy(pManifest); | |
| 1764 | 1742 | return 0; |
| 1765 | 1743 | } |
| 1766 | 1744 | |
| 1767 | 1745 | /* |
| 1768 | 1746 | ** The "z" argument is a string that contains the text of a source code |
| @@ -1862,11 +1840,11 @@ | ||
| 1862 | 1840 | ** Additional query parameters: |
| 1863 | 1841 | ** |
| 1864 | 1842 | ** ln - show line numbers |
| 1865 | 1843 | ** ln=N - highlight line number N |
| 1866 | 1844 | ** ln=M-N - highlight lines M through N inclusive |
| 1867 | -** ln=M-N+Y-Z - highlight lines M through N and Y through Z (inclusive) | |
| 1845 | +** ln=M-N,Y-Z - highlight lines M through N and Y through Z (inclusive) | |
| 1868 | 1846 | ** verbose - show more detail in the description |
| 1869 | 1847 | ** download - redirect to the download (artifact page only) |
| 1870 | 1848 | ** name=SHA1HASH - Provide the SHA1HASH as a query parameter |
| 1871 | 1849 | ** filename=NAME - Show information for content file NAME |
| 1872 | 1850 | ** fn=NAME - "fn" is shorthand for "filename" |
| @@ -1889,33 +1867,55 @@ | ||
| 1889 | 1867 | const char *zUuid; |
| 1890 | 1868 | u32 objdescFlags = 0; |
| 1891 | 1869 | int descOnly = fossil_strcmp(g.zPath,"whatis")==0; |
| 1892 | 1870 | int isFile = fossil_strcmp(g.zPath,"file")==0; |
| 1893 | 1871 | const char *zLn = P("ln"); |
| 1872 | + const char *zName = P("name"); | |
| 1873 | + HQuery url; | |
| 1894 | 1874 | |
| 1895 | - rid = artifact_from_ci_and_filename_www(); | |
| 1875 | + url_initialize(&url, g.zPath); | |
| 1876 | + rid = artifact_from_ci_and_filename(&url); | |
| 1896 | 1877 | if( rid==0 ){ |
| 1897 | - if( fossil_strcmp(g.zPath,"file")==0 ){ | |
| 1878 | + url_add_parameter(&url, "name", zName); | |
| 1879 | + if( isFile ){ | |
| 1880 | + if( zName==0 ) zName = ""; | |
| 1898 | 1881 | rid = db_int(0, |
| 1899 | 1882 | "SELECT fid FROM filename, mlink, event" |
| 1900 | 1883 | " WHERE name=%Q" |
| 1901 | 1884 | " AND mlink.fnid=filename.fnid" |
| 1902 | 1885 | " AND event.objid=mlink.mid" |
| 1903 | 1886 | " ORDER BY event.mtime DESC LIMIT 1", |
| 1904 | - PD("name","") | |
| 1887 | + zName | |
| 1905 | 1888 | ); |
| 1889 | + if( rid==0 ){ | |
| 1890 | + style_header("No such file"); | |
| 1891 | + @ File '%h(zName)' does not exist in this repository. | |
| 1892 | + style_footer(); | |
| 1893 | + return; | |
| 1894 | + } | |
| 1906 | 1895 | }else{ |
| 1907 | 1896 | rid = name_to_rid_www("name"); |
| 1908 | 1897 | } |
| 1909 | 1898 | } |
| 1910 | 1899 | |
| 1911 | 1900 | login_check_credentials(); |
| 1912 | 1901 | if( !g.perm.Read ){ login_needed(g.anon.Read); return; } |
| 1913 | - if( rid==0 ) fossil_redirect_home(); | |
| 1914 | - if( descOnly || P("verbose")!=0 ) objdescFlags |= OBJDESC_DETAIL; | |
| 1902 | + if( rid==0 ){ | |
| 1903 | + style_header("No such artifact"); | |
| 1904 | + @ Artifact '%h(zName)' does not exist in this repository. | |
| 1905 | + style_footer(); | |
| 1906 | + return; | |
| 1907 | + } | |
| 1908 | + if( descOnly || P("verbose")!=0 ){ | |
| 1909 | + url_add_parameter(&url, "verbose", "1"); | |
| 1910 | + objdescFlags |= OBJDESC_DETAIL; | |
| 1911 | + } | |
| 1915 | 1912 | zUuid = db_text("?", "SELECT uuid FROM blob WHERE rid=%d", rid); |
| 1916 | - if( g.perm.Setup ){ | |
| 1913 | + if( isFile ){ | |
| 1914 | + @ <h2>Latest version of file '%h(zName)':</h2> | |
| 1915 | + style_submenu_element("Artifact", "%R/artifact/%S", zUuid); | |
| 1916 | + }else if( g.perm.Setup ){ | |
| 1917 | 1917 | @ <h2>Artifact %s(zUuid) (%d(rid)):</h2> |
| 1918 | 1918 | }else{ |
| 1919 | 1919 | @ <h2>Artifact %s(zUuid):</h2> |
| 1920 | 1920 | } |
| 1921 | 1921 | blob_zero(&downloadName); |
| @@ -1932,11 +1932,12 @@ | ||
| 1932 | 1932 | g.zTop, zUuid); |
| 1933 | 1933 | }else{ |
| 1934 | 1934 | style_submenu_element("Shun", "%s/shun?shun=%s#addshun", g.zTop, zUuid); |
| 1935 | 1935 | } |
| 1936 | 1936 | } |
| 1937 | - style_header("%s", descOnly ? "Artifact Description" : "Artifact Content"); | |
| 1937 | + style_header("%s", isFile ? "File Content" : | |
| 1938 | + descOnly ? "Artifact Description" : "Artifact Content"); | |
| 1938 | 1939 | if( g.perm.Admin ){ |
| 1939 | 1940 | Stmt q; |
| 1940 | 1941 | db_prepare(&q, |
| 1941 | 1942 | "SELECT coalesce(user.login,rcvfrom.uid)," |
| 1942 | 1943 | " datetime(rcvfrom.mtime,toLocal()), rcvfrom.ipaddr" |
| @@ -1959,42 +1960,47 @@ | ||
| 1959 | 1960 | asText = P("txt")!=0; |
| 1960 | 1961 | zMime = mimetype_from_name(blob_str(&downloadName)); |
| 1961 | 1962 | if( zMime ){ |
| 1962 | 1963 | if( fossil_strcmp(zMime, "text/html")==0 ){ |
| 1963 | 1964 | if( asText ){ |
| 1964 | - style_submenu_element("Html", "%s/artifact/%s", g.zTop, zUuid); | |
| 1965 | + style_submenu_element("Html", "%s", url_render(&url, "txt", 0, 0, 0)); | |
| 1965 | 1966 | }else{ |
| 1966 | 1967 | renderAsHtml = 1; |
| 1967 | - style_submenu_element("Text", "%s/artifact/%s?txt=1", g.zTop, zUuid); | |
| 1968 | + style_submenu_element("Text", "%s", url_render(&url, "txt", "1", 0, 0)); | |
| 1968 | 1969 | } |
| 1969 | 1970 | }else if( fossil_strcmp(zMime, "text/x-fossil-wiki")==0 |
| 1970 | 1971 | || fossil_strcmp(zMime, "text/x-markdown")==0 ){ |
| 1971 | 1972 | if( asText ){ |
| 1972 | - style_submenu_element("Wiki", "%s/artifact/%s", g.zTop, zUuid); | |
| 1973 | + style_submenu_element("Wiki", "%s", url_render(&url, "txt", 0, 0, 0)); | |
| 1973 | 1974 | }else{ |
| 1974 | 1975 | renderAsWiki = 1; |
| 1975 | - style_submenu_element("Text", "%s/artifact/%s?txt=1", g.zTop, zUuid); | |
| 1976 | + style_submenu_element("Text", "%s", url_render(&url, "txt", "1", 0, 0)); | |
| 1976 | 1977 | } |
| 1977 | 1978 | } |
| 1978 | 1979 | } |
| 1979 | 1980 | if( (objType & (OBJTYPE_WIKI|OBJTYPE_TICKET))!=0 ){ |
| 1980 | 1981 | style_submenu_element("Parsed", "%R/info/%s", zUuid); |
| 1981 | 1982 | } |
| 1982 | 1983 | if( descOnly ){ |
| 1983 | 1984 | style_submenu_element("Content", "%R/artifact/%s", zUuid); |
| 1984 | 1985 | }else{ |
| 1985 | - style_submenu_element("Line Numbers", "%R/artifact/%s%s", zUuid, | |
| 1986 | - ((zLn&&*zLn) ? "" : "?txt=1&ln=0")); | |
| 1986 | + if( zLn==0 ){ | |
| 1987 | + style_submenu_element("Line Numbers", "%s", | |
| 1988 | + url_render(&url, "ln", "", 0, 0)); | |
| 1989 | + }else{ | |
| 1990 | + style_submenu_element("Line Numbers", "%s", | |
| 1991 | + url_render(&url, "ln", 0, 0, 0)); | |
| 1992 | + } | |
| 1987 | 1993 | @ <hr /> |
| 1988 | 1994 | content_get(rid, &content); |
| 1989 | 1995 | if( renderAsWiki ){ |
| 1990 | 1996 | wiki_render_by_mimetype(&content, zMime); |
| 1991 | 1997 | }else if( renderAsHtml ){ |
| 1992 | 1998 | @ <iframe src="%R/raw/%T(blob_str(&downloadName))?name=%s(zUuid)" |
| 1993 | - @ width="100%%" frameborder="0" marginwidth="0" marginheight="0" | |
| 1994 | - @ sandbox="allow-same-origin" | |
| 1995 | - @ onload="this.height=this.contentDocument.documentElement.scrollHeight;"> | |
| 1999 | + @ width="100%%" frameborder="0" marginwidth="0" marginheight="0" | |
| 2000 | + @ sandbox="allow-same-origin" | |
| 2001 | + @ onload="this.height=this.contentDocument.documentElement.scrollHeight;"> | |
| 1996 | 2002 | @ </iframe> |
| 1997 | 2003 | }else{ |
| 1998 | 2004 | style_submenu_element("Hex", "%s/hexdump?name=%s", g.zTop, zUuid); |
| 1999 | 2005 | blob_to_utf8_no_bom(&content, 0); |
| 2000 | 2006 | zMime = mimetype_from_content(&content); |
| 2001 | 2007 |
| --- src/info.c | |
| +++ src/info.c | |
| @@ -1565,11 +1565,11 @@ | |
| 1565 | char *zUuid; |
| 1566 | const char *zMime; |
| 1567 | Blob content; |
| 1568 | |
| 1569 | if( P("ci") && P("filename") ){ |
| 1570 | rid = artifact_from_ci_and_filename_www(); |
| 1571 | } |
| 1572 | if( rid==0 ){ |
| 1573 | rid = name_to_rid_www("name"); |
| 1574 | } |
| 1575 | login_check_credentials(); |
| @@ -1699,46 +1699,19 @@ | |
| 1699 | hexdump(&content); |
| 1700 | @ </pre></blockquote> |
| 1701 | style_footer(); |
| 1702 | } |
| 1703 | |
| 1704 | /* |
| 1705 | ** Attempt to lookup the specified check-in and file name into an rid. |
| 1706 | */ |
| 1707 | int artifact_from_ci_and_filename( |
| 1708 | const char *zCI, |
| 1709 | const char *zFilename |
| 1710 | ){ |
| 1711 | int cirid; |
| 1712 | Manifest *pManifest; |
| 1713 | ManifestFile *pFile; |
| 1714 | |
| 1715 | if( zCI==0 ) return 0; |
| 1716 | if( zFilename==0 ) return 0; |
| 1717 | cirid = name_to_rid(zCI); |
| 1718 | pManifest = manifest_get(cirid, CFTYPE_MANIFEST, 0); |
| 1719 | if( pManifest==0 ) return 0; |
| 1720 | manifest_file_rewind(pManifest); |
| 1721 | while( (pFile = manifest_file_next(pManifest,0))!=0 ){ |
| 1722 | if( fossil_strcmp(zFilename, pFile->zName)==0 ){ |
| 1723 | int rid = db_int(0, "SELECT rid FROM blob WHERE uuid=%Q", pFile->zUuid); |
| 1724 | manifest_destroy(pManifest); |
| 1725 | return rid; |
| 1726 | } |
| 1727 | } |
| 1728 | return 0; |
| 1729 | } |
| 1730 | |
| 1731 | /* |
| 1732 | ** Look for "ci" and "filename" query parameters. If found, try to |
| 1733 | ** use them to extract the record ID of an artifact for the file. |
| 1734 | ** |
| 1735 | ** Also look for "fn" as an alias for "filename". If either "filename" |
| 1736 | ** or "fn" is present but "ci" is missing, use "tip" as a default value |
| 1737 | ** for "ci". |
| 1738 | */ |
| 1739 | int artifact_from_ci_and_filename_www(void){ |
| 1740 | const char *zFilename; |
| 1741 | const char *zCI; |
| 1742 | int cirid; |
| 1743 | Manifest *pManifest; |
| 1744 | ManifestFile *pFile; |
| @@ -1746,23 +1719,28 @@ | |
| 1746 | zFilename = P("filename"); |
| 1747 | if( zFilename==0 ){ |
| 1748 | zFilename = P("fn"); |
| 1749 | if( zFilename==0 ) return 0; |
| 1750 | } |
| 1751 | zCI = PD("ci", "tip"); |
| 1752 | cirid = name_to_typed_rid(zCI, "ci"); |
| 1753 | if( cirid<=0 ) return 0; |
| 1754 | pManifest = manifest_get(cirid, CFTYPE_MANIFEST, 0); |
| 1755 | if( pManifest==0 ) return 0; |
| 1756 | manifest_file_rewind(pManifest); |
| 1757 | while( (pFile = manifest_file_next(pManifest,0))!=0 ){ |
| 1758 | if( fossil_strcmp(zFilename, pFile->zName)==0 ){ |
| 1759 | int rid = db_int(0, "SELECT rid FROM blob WHERE uuid=%Q", pFile->zUuid); |
| 1760 | manifest_destroy(pManifest); |
| 1761 | return rid; |
| 1762 | } |
| 1763 | } |
| 1764 | return 0; |
| 1765 | } |
| 1766 | |
| 1767 | /* |
| 1768 | ** The "z" argument is a string that contains the text of a source code |
| @@ -1862,11 +1840,11 @@ | |
| 1862 | ** Additional query parameters: |
| 1863 | ** |
| 1864 | ** ln - show line numbers |
| 1865 | ** ln=N - highlight line number N |
| 1866 | ** ln=M-N - highlight lines M through N inclusive |
| 1867 | ** ln=M-N+Y-Z - highlight lines M through N and Y through Z (inclusive) |
| 1868 | ** verbose - show more detail in the description |
| 1869 | ** download - redirect to the download (artifact page only) |
| 1870 | ** name=SHA1HASH - Provide the SHA1HASH as a query parameter |
| 1871 | ** filename=NAME - Show information for content file NAME |
| 1872 | ** fn=NAME - "fn" is shorthand for "filename" |
| @@ -1889,33 +1867,55 @@ | |
| 1889 | const char *zUuid; |
| 1890 | u32 objdescFlags = 0; |
| 1891 | int descOnly = fossil_strcmp(g.zPath,"whatis")==0; |
| 1892 | int isFile = fossil_strcmp(g.zPath,"file")==0; |
| 1893 | const char *zLn = P("ln"); |
| 1894 | |
| 1895 | rid = artifact_from_ci_and_filename_www(); |
| 1896 | if( rid==0 ){ |
| 1897 | if( fossil_strcmp(g.zPath,"file")==0 ){ |
| 1898 | rid = db_int(0, |
| 1899 | "SELECT fid FROM filename, mlink, event" |
| 1900 | " WHERE name=%Q" |
| 1901 | " AND mlink.fnid=filename.fnid" |
| 1902 | " AND event.objid=mlink.mid" |
| 1903 | " ORDER BY event.mtime DESC LIMIT 1", |
| 1904 | PD("name","") |
| 1905 | ); |
| 1906 | }else{ |
| 1907 | rid = name_to_rid_www("name"); |
| 1908 | } |
| 1909 | } |
| 1910 | |
| 1911 | login_check_credentials(); |
| 1912 | if( !g.perm.Read ){ login_needed(g.anon.Read); return; } |
| 1913 | if( rid==0 ) fossil_redirect_home(); |
| 1914 | if( descOnly || P("verbose")!=0 ) objdescFlags |= OBJDESC_DETAIL; |
| 1915 | zUuid = db_text("?", "SELECT uuid FROM blob WHERE rid=%d", rid); |
| 1916 | if( g.perm.Setup ){ |
| 1917 | @ <h2>Artifact %s(zUuid) (%d(rid)):</h2> |
| 1918 | }else{ |
| 1919 | @ <h2>Artifact %s(zUuid):</h2> |
| 1920 | } |
| 1921 | blob_zero(&downloadName); |
| @@ -1932,11 +1932,12 @@ | |
| 1932 | g.zTop, zUuid); |
| 1933 | }else{ |
| 1934 | style_submenu_element("Shun", "%s/shun?shun=%s#addshun", g.zTop, zUuid); |
| 1935 | } |
| 1936 | } |
| 1937 | style_header("%s", descOnly ? "Artifact Description" : "Artifact Content"); |
| 1938 | if( g.perm.Admin ){ |
| 1939 | Stmt q; |
| 1940 | db_prepare(&q, |
| 1941 | "SELECT coalesce(user.login,rcvfrom.uid)," |
| 1942 | " datetime(rcvfrom.mtime,toLocal()), rcvfrom.ipaddr" |
| @@ -1959,42 +1960,47 @@ | |
| 1959 | asText = P("txt")!=0; |
| 1960 | zMime = mimetype_from_name(blob_str(&downloadName)); |
| 1961 | if( zMime ){ |
| 1962 | if( fossil_strcmp(zMime, "text/html")==0 ){ |
| 1963 | if( asText ){ |
| 1964 | style_submenu_element("Html", "%s/artifact/%s", g.zTop, zUuid); |
| 1965 | }else{ |
| 1966 | renderAsHtml = 1; |
| 1967 | style_submenu_element("Text", "%s/artifact/%s?txt=1", g.zTop, zUuid); |
| 1968 | } |
| 1969 | }else if( fossil_strcmp(zMime, "text/x-fossil-wiki")==0 |
| 1970 | || fossil_strcmp(zMime, "text/x-markdown")==0 ){ |
| 1971 | if( asText ){ |
| 1972 | style_submenu_element("Wiki", "%s/artifact/%s", g.zTop, zUuid); |
| 1973 | }else{ |
| 1974 | renderAsWiki = 1; |
| 1975 | style_submenu_element("Text", "%s/artifact/%s?txt=1", g.zTop, zUuid); |
| 1976 | } |
| 1977 | } |
| 1978 | } |
| 1979 | if( (objType & (OBJTYPE_WIKI|OBJTYPE_TICKET))!=0 ){ |
| 1980 | style_submenu_element("Parsed", "%R/info/%s", zUuid); |
| 1981 | } |
| 1982 | if( descOnly ){ |
| 1983 | style_submenu_element("Content", "%R/artifact/%s", zUuid); |
| 1984 | }else{ |
| 1985 | style_submenu_element("Line Numbers", "%R/artifact/%s%s", zUuid, |
| 1986 | ((zLn&&*zLn) ? "" : "?txt=1&ln=0")); |
| 1987 | @ <hr /> |
| 1988 | content_get(rid, &content); |
| 1989 | if( renderAsWiki ){ |
| 1990 | wiki_render_by_mimetype(&content, zMime); |
| 1991 | }else if( renderAsHtml ){ |
| 1992 | @ <iframe src="%R/raw/%T(blob_str(&downloadName))?name=%s(zUuid)" |
| 1993 | @ width="100%%" frameborder="0" marginwidth="0" marginheight="0" |
| 1994 | @ sandbox="allow-same-origin" |
| 1995 | @ onload="this.height=this.contentDocument.documentElement.scrollHeight;"> |
| 1996 | @ </iframe> |
| 1997 | }else{ |
| 1998 | style_submenu_element("Hex", "%s/hexdump?name=%s", g.zTop, zUuid); |
| 1999 | blob_to_utf8_no_bom(&content, 0); |
| 2000 | zMime = mimetype_from_content(&content); |
| 2001 |
| --- src/info.c | |
| +++ src/info.c | |
| @@ -1565,11 +1565,11 @@ | |
| 1565 | char *zUuid; |
| 1566 | const char *zMime; |
| 1567 | Blob content; |
| 1568 | |
| 1569 | if( P("ci") && P("filename") ){ |
| 1570 | rid = artifact_from_ci_and_filename(0); |
| 1571 | } |
| 1572 | if( rid==0 ){ |
| 1573 | rid = name_to_rid_www("name"); |
| 1574 | } |
| 1575 | login_check_credentials(); |
| @@ -1699,46 +1699,19 @@ | |
| 1699 | hexdump(&content); |
| 1700 | @ </pre></blockquote> |
| 1701 | style_footer(); |
| 1702 | } |
| 1703 | |
| 1704 | /* |
| 1705 | ** Look for "ci" and "filename" query parameters. If found, try to |
| 1706 | ** use them to extract the record ID of an artifact for the file. |
| 1707 | ** |
| 1708 | ** Also look for "fn" as an alias for "filename". If either "filename" |
| 1709 | ** or "fn" is present but "ci" is missing, use "tip" as a default value |
| 1710 | ** for "ci". |
| 1711 | */ |
| 1712 | int artifact_from_ci_and_filename(HQuery *pUrl){ |
| 1713 | const char *zFilename; |
| 1714 | const char *zCI; |
| 1715 | int cirid; |
| 1716 | Manifest *pManifest; |
| 1717 | ManifestFile *pFile; |
| @@ -1746,23 +1719,28 @@ | |
| 1719 | zFilename = P("filename"); |
| 1720 | if( zFilename==0 ){ |
| 1721 | zFilename = P("fn"); |
| 1722 | if( zFilename==0 ) return 0; |
| 1723 | } |
| 1724 | zCI = P("ci"); |
| 1725 | cirid = name_to_typed_rid(zCI ? zCI : "tip", "ci"); |
| 1726 | if( cirid<=0 ) return 0; |
| 1727 | pManifest = manifest_get(cirid, CFTYPE_MANIFEST, 0); |
| 1728 | if( pManifest==0 ) return 0; |
| 1729 | manifest_file_rewind(pManifest); |
| 1730 | while( (pFile = manifest_file_next(pManifest,0))!=0 ){ |
| 1731 | if( fossil_strcmp(zFilename, pFile->zName)==0 ){ |
| 1732 | int rid = db_int(0, "SELECT rid FROM blob WHERE uuid=%Q", pFile->zUuid); |
| 1733 | manifest_destroy(pManifest); |
| 1734 | if( pUrl ){ |
| 1735 | url_add_parameter(pUrl, "fn", zFilename); |
| 1736 | if( zCI ) url_add_parameter(pUrl, "ci", zCI); |
| 1737 | } |
| 1738 | return rid; |
| 1739 | } |
| 1740 | } |
| 1741 | manifest_destroy(pManifest); |
| 1742 | return 0; |
| 1743 | } |
| 1744 | |
| 1745 | /* |
| 1746 | ** The "z" argument is a string that contains the text of a source code |
| @@ -1862,11 +1840,11 @@ | |
| 1840 | ** Additional query parameters: |
| 1841 | ** |
| 1842 | ** ln - show line numbers |
| 1843 | ** ln=N - highlight line number N |
| 1844 | ** ln=M-N - highlight lines M through N inclusive |
| 1845 | ** ln=M-N,Y-Z - highlight lines M through N and Y through Z (inclusive) |
| 1846 | ** verbose - show more detail in the description |
| 1847 | ** download - redirect to the download (artifact page only) |
| 1848 | ** name=SHA1HASH - Provide the SHA1HASH as a query parameter |
| 1849 | ** filename=NAME - Show information for content file NAME |
| 1850 | ** fn=NAME - "fn" is shorthand for "filename" |
| @@ -1889,33 +1867,55 @@ | |
| 1867 | const char *zUuid; |
| 1868 | u32 objdescFlags = 0; |
| 1869 | int descOnly = fossil_strcmp(g.zPath,"whatis")==0; |
| 1870 | int isFile = fossil_strcmp(g.zPath,"file")==0; |
| 1871 | const char *zLn = P("ln"); |
| 1872 | const char *zName = P("name"); |
| 1873 | HQuery url; |
| 1874 | |
| 1875 | url_initialize(&url, g.zPath); |
| 1876 | rid = artifact_from_ci_and_filename(&url); |
| 1877 | if( rid==0 ){ |
| 1878 | url_add_parameter(&url, "name", zName); |
| 1879 | if( isFile ){ |
| 1880 | if( zName==0 ) zName = ""; |
| 1881 | rid = db_int(0, |
| 1882 | "SELECT fid FROM filename, mlink, event" |
| 1883 | " WHERE name=%Q" |
| 1884 | " AND mlink.fnid=filename.fnid" |
| 1885 | " AND event.objid=mlink.mid" |
| 1886 | " ORDER BY event.mtime DESC LIMIT 1", |
| 1887 | zName |
| 1888 | ); |
| 1889 | if( rid==0 ){ |
| 1890 | style_header("No such file"); |
| 1891 | @ File '%h(zName)' does not exist in this repository. |
| 1892 | style_footer(); |
| 1893 | return; |
| 1894 | } |
| 1895 | }else{ |
| 1896 | rid = name_to_rid_www("name"); |
| 1897 | } |
| 1898 | } |
| 1899 | |
| 1900 | login_check_credentials(); |
| 1901 | if( !g.perm.Read ){ login_needed(g.anon.Read); return; } |
| 1902 | if( rid==0 ){ |
| 1903 | style_header("No such artifact"); |
| 1904 | @ Artifact '%h(zName)' does not exist in this repository. |
| 1905 | style_footer(); |
| 1906 | return; |
| 1907 | } |
| 1908 | if( descOnly || P("verbose")!=0 ){ |
| 1909 | url_add_parameter(&url, "verbose", "1"); |
| 1910 | objdescFlags |= OBJDESC_DETAIL; |
| 1911 | } |
| 1912 | zUuid = db_text("?", "SELECT uuid FROM blob WHERE rid=%d", rid); |
| 1913 | if( isFile ){ |
| 1914 | @ <h2>Latest version of file '%h(zName)':</h2> |
| 1915 | style_submenu_element("Artifact", "%R/artifact/%S", zUuid); |
| 1916 | }else if( g.perm.Setup ){ |
| 1917 | @ <h2>Artifact %s(zUuid) (%d(rid)):</h2> |
| 1918 | }else{ |
| 1919 | @ <h2>Artifact %s(zUuid):</h2> |
| 1920 | } |
| 1921 | blob_zero(&downloadName); |
| @@ -1932,11 +1932,12 @@ | |
| 1932 | g.zTop, zUuid); |
| 1933 | }else{ |
| 1934 | style_submenu_element("Shun", "%s/shun?shun=%s#addshun", g.zTop, zUuid); |
| 1935 | } |
| 1936 | } |
| 1937 | style_header("%s", isFile ? "File Content" : |
| 1938 | descOnly ? "Artifact Description" : "Artifact Content"); |
| 1939 | if( g.perm.Admin ){ |
| 1940 | Stmt q; |
| 1941 | db_prepare(&q, |
| 1942 | "SELECT coalesce(user.login,rcvfrom.uid)," |
| 1943 | " datetime(rcvfrom.mtime,toLocal()), rcvfrom.ipaddr" |
| @@ -1959,42 +1960,47 @@ | |
| 1960 | asText = P("txt")!=0; |
| 1961 | zMime = mimetype_from_name(blob_str(&downloadName)); |
| 1962 | if( zMime ){ |
| 1963 | if( fossil_strcmp(zMime, "text/html")==0 ){ |
| 1964 | if( asText ){ |
| 1965 | style_submenu_element("Html", "%s", url_render(&url, "txt", 0, 0, 0)); |
| 1966 | }else{ |
| 1967 | renderAsHtml = 1; |
| 1968 | style_submenu_element("Text", "%s", url_render(&url, "txt", "1", 0, 0)); |
| 1969 | } |
| 1970 | }else if( fossil_strcmp(zMime, "text/x-fossil-wiki")==0 |
| 1971 | || fossil_strcmp(zMime, "text/x-markdown")==0 ){ |
| 1972 | if( asText ){ |
| 1973 | style_submenu_element("Wiki", "%s", url_render(&url, "txt", 0, 0, 0)); |
| 1974 | }else{ |
| 1975 | renderAsWiki = 1; |
| 1976 | style_submenu_element("Text", "%s", url_render(&url, "txt", "1", 0, 0)); |
| 1977 | } |
| 1978 | } |
| 1979 | } |
| 1980 | if( (objType & (OBJTYPE_WIKI|OBJTYPE_TICKET))!=0 ){ |
| 1981 | style_submenu_element("Parsed", "%R/info/%s", zUuid); |
| 1982 | } |
| 1983 | if( descOnly ){ |
| 1984 | style_submenu_element("Content", "%R/artifact/%s", zUuid); |
| 1985 | }else{ |
| 1986 | if( zLn==0 ){ |
| 1987 | style_submenu_element("Line Numbers", "%s", |
| 1988 | url_render(&url, "ln", "", 0, 0)); |
| 1989 | }else{ |
| 1990 | style_submenu_element("Line Numbers", "%s", |
| 1991 | url_render(&url, "ln", 0, 0, 0)); |
| 1992 | } |
| 1993 | @ <hr /> |
| 1994 | content_get(rid, &content); |
| 1995 | if( renderAsWiki ){ |
| 1996 | wiki_render_by_mimetype(&content, zMime); |
| 1997 | }else if( renderAsHtml ){ |
| 1998 | @ <iframe src="%R/raw/%T(blob_str(&downloadName))?name=%s(zUuid)" |
| 1999 | @ width="100%%" frameborder="0" marginwidth="0" marginheight="0" |
| 2000 | @ sandbox="allow-same-origin" |
| 2001 | @ onload="this.height=this.contentDocument.documentElement.scrollHeight;"> |
| 2002 | @ </iframe> |
| 2003 | }else{ |
| 2004 | style_submenu_element("Hex", "%s/hexdump?name=%s", g.zTop, zUuid); |
| 2005 | blob_to_utf8_no_bom(&content, 0); |
| 2006 | zMime = mimetype_from_content(&content); |
| 2007 |