Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
| Comment: | Enhancements to SEE integration. |
|---|---|
| Downloads: | Tarball | ZIP archive |
| Timelines: | family | ancestors | descendants | both | enhSee |
| Files: | files | file ages | folders |
| SHA3-256: |
d72ab72962fbd17d40e58bd2445c0d85 |
| User & Date: | mistachkin 2023-05-18 21:15:51.217 |
Context
|
2023-05-18
| ||
| 23:24 | Comment fixes. check-in: 1ff19a468d user: mistachkin tags: enhSee | |
| 21:15 | Enhancements to SEE integration. check-in: d72ab72962 user: mistachkin tags: enhSee | |
| 17:02 | Update Pikchr to omit the artifical enlargement of "mono" text. check-in: b1c0409a56 user: drh tags: trunk | |
Changes
Changes to src/db.c.
| ︙ | ︙ | |||
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 54 55 56 57 |
** and located at the root of the local copy of the source tree.
**
*/
#include "config.h"
#if defined(_WIN32)
# if USE_SEE
# include <windows.h>
# endif
#else
# include <pwd.h>
#endif
#if USE_SEE && !defined(SQLITE_HAS_CODEC)
# define SQLITE_HAS_CODEC
#endif
#include <sqlite3.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <time.h>
#include "db.h"
#if INTERFACE
/*
** An single SQL statement is represented as an instance of the following
** structure.
*/
struct Stmt {
Blob sql; /* The SQL for this statement */
sqlite3_stmt *pStmt; /* The results of sqlite3_prepare_v2() */
| > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 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 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 |
** and located at the root of the local copy of the source tree.
**
*/
#include "config.h"
#if defined(_WIN32)
# if USE_SEE
# include <windows.h>
# define GETPID (int)GetCurrentProcessId
# endif
#else
# include <pwd.h>
# if USE_SEE
# define GETPID getpid
# endif
#endif
#if USE_SEE && !defined(SQLITE_HAS_CODEC)
# define SQLITE_HAS_CODEC
#endif
#if USE_SEE && defined(__linux__)
# include <sys/uio.h>
#endif
#include <sqlite3.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <time.h>
/* BUGBUG: This (PID_T) does not work inside of INTERFACE block. */
#if USE_SEE
#if defined(_WIN32)
typedef DWORD PID_T;
#else
typedef pid_t PID_T;
#endif
#endif
#include "db.h"
#if INTERFACE
/*
** Type definitions used for handling the saved encryption key for SEE.
*/
#if !defined(_WIN32)
typedef void *LPVOID;
typedef size_t SIZE_T;
#endif
/*
** Operations for db_maybe_handle_saved_encryption_key_for_process, et al.
*/
#define SEE_KEY_READ ((int)0)
#define SEE_KEY_WRITE ((int)1)
#define SEE_KEY_ZERO ((int)2)
/*
** An single SQL statement is represented as an instance of the following
** structure.
*/
struct Stmt {
Blob sql; /* The SQL for this statement */
sqlite3_stmt *pStmt; /* The results of sqlite3_prepare_v2() */
|
| ︙ | ︙ | |||
1537 1538 1539 1540 1541 1542 1543 | ** This is a pointer to the saved database encryption key string. */ static char *zSavedKey = 0; /* ** This is the size of the saved database encryption key, in bytes. */ | | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 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 1651 1652 1653 1654 1655 1656 1657 1658 |
** This is a pointer to the saved database encryption key string.
*/
static char *zSavedKey = 0;
/*
** This is the size of the saved database encryption key, in bytes.
*/
static size_t savedKeySize = 0;
/*
** This function returns non-zero if there is a saved database encryption
** key available.
*/
int db_have_saved_encryption_key(){
return db_is_valid_saved_encryption_key(zSavedKey, savedKeySize);
}
/*
** This function returns non-zero if the specified saved database encryption
** key is valid.
*/
int db_is_valid_saved_encryption_key(const char *p, size_t n){
if( p==0 ) return 0;
if( n==0 ) return 0;
if( p[0]==0 ) return 0;
return 1;
}
/*
** This function returns the saved database encryption key -OR- zero if
** no database encryption key is saved.
*/
char *db_get_saved_encryption_key(){
return zSavedKey;
}
/*
** This function returns the size of the saved database encryption key
** -OR- zero if no database encryption key is saved.
*/
size_t db_get_saved_encryption_key_size(){
return savedKeySize;
}
/*
** This function arranges for the saved database encryption key buffer
** to be allocated and then sets up the environment variable to allow
** a child process to initialize it with the actual database encryption
** key.
*/
void db_setup_for_saved_encryption_key(){
void *p = NULL;
size_t n = 0;
size_t pageSize = 0;
Blob pidKey;
assert( !db_have_saved_encryption_key() );
db_unsave_encryption_key();
fossil_get_page_size(&pageSize);
assert( pageSize>0 );
p = fossil_secure_alloc_page(&n);
assert( p!=NULL );
assert( n==pageSize );
blob_zero(&pidKey);
blob_appendf(&pidKey, "%lu:%p:%u", (unsigned long)GETPID(), p, n);
fossil_setenv("FOSSIL_SEE_PID_KEY", blob_str(&pidKey));
zSavedKey = p;
savedKeySize = n;
}
/*
** This function arranges for the database encryption key to be securely
** saved in non-pagable memory (on platforms where this is possible).
*/
static void db_save_encryption_key(
Blob *pKey
){
void *p = NULL;
size_t n = 0;
size_t pageSize = 0;
size_t blobSize = 0;
assert( !db_have_saved_encryption_key() );
blobSize = blob_size(pKey);
if( blobSize==0 ) return;
fossil_get_page_size(&pageSize);
assert( pageSize>0 );
if( blobSize>pageSize ){
fossil_panic("key blob too large: %u versus %u", blobSize, pageSize);
}
|
| ︙ | ︙ | |||
1597 1598 1599 1600 1601 1602 1603 | savedKeySize = 0; } /* ** This function sets the saved database encryption key to the specified ** string value, allocating or freeing the underlying memory if needed. */ | | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | | | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | | < > > | > | | | | > | < < < < | | | | | > | | | | > | > > > > > > > > > > > > > > > > > > > | | | > > > < > | > > > > > > > > | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 1882 1883 1884 1885 1886 1887 1888 1889 1890 1891 1892 1893 1894 1895 1896 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 1931 1932 1933 1934 1935 1936 1937 1938 1939 1940 1941 1942 1943 1944 1945 1946 1947 1948 1949 1950 1951 1952 1953 1954 1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 1970 1971 1972 1973 1974 1975 1976 1977 1978 1979 1980 1981 1982 1983 1984 1985 1986 1987 1988 1989 1990 1991 1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 2026 2027 2028 2029 2030 2031 2032 2033 2034 2035 2036 2037 2038 2039 2040 2041 2042 |
savedKeySize = 0;
}
/*
** This function sets the saved database encryption key to the specified
** string value, allocating or freeing the underlying memory if needed.
*/
static void db_set_saved_encryption_key(
Blob *pKey
){
if( zSavedKey!=NULL ){
size_t blobSize = blob_size(pKey);
if( blobSize==0 ){
db_unsave_encryption_key();
}else{
if( blobSize>savedKeySize ){
fossil_panic("key blob too large: %u versus %u",
blobSize, savedKeySize);
}
fossil_secure_zero(zSavedKey, savedKeySize);
memcpy(zSavedKey, blob_str(pKey), blobSize);
}
}else{
db_save_encryption_key(pKey);
}
}
/*
** WEBPAGE: setseekey
**
** Sets the sets the saved database encryption key to one that gets passed
** via the "key" query string parameter. If the saved database encryption
** key has already been set, does nothing. This web page does not produce
** any output on success or failure.
**
** Query parameters:
**
** key The string to set as the saved database encryption
** key.
*/
void db_set_see_key_page(void){
Blob key;
const char *zKey;
if( db_have_saved_encryption_key() ){
fossil_errorlog("SEE: encryption key was already set\n");
return;
}
zKey = P("key");
blob_init(&key, 0, 0);
if( zKey!=0 ){
PID_T processId;
blob_set(&key, zKey);
db_set_saved_encryption_key(&key);
processId = db_maybe_handle_saved_encryption_key_for_process(
SEE_KEY_WRITE
);
fossil_errorlog("SEE: set encryption key for process %lu, length %u\n",
(unsigned long)processId, blob_size(&key));
}else{
fossil_errorlog("SEE: no encryption key specified\n");
}
blob_reset(&key);
}
/*
** WEBPAGE: unsetseekey
**
** Unsets the saved database encryption key to zeros. If the saved database
** encryption key has already been set, does nothing. This web page does not
** produce any output on success or failure.
*/
void db_unset_see_key_page(void){
PID_T processId;
login_check_credentials();
if( !g.perm.Setup ){ login_needed(0); return; }
processId = db_maybe_handle_saved_encryption_key_for_process(
SEE_KEY_ZERO
);
fossil_errorlog("SEE: unset encryption key for process %lu\n",
(unsigned long)processId);
}
/*
** This function reads the saved database encryption key from the
** specified Fossil parent process. This is only necessary (or
** functional) on Windows or Linux.
*/
static void db_read_saved_encryption_key_from_process(
PID_T processId, /* Identifier for Fossil parent process. */
LPVOID pAddress, /* Pointer to saved key buffer in the parent process. */
SIZE_T nSize /* Size of saved key buffer in the parent process. */
){
void *p = NULL;
size_t n = 0;
size_t pageSize = 0;
fossil_get_page_size(&pageSize);
assert( pageSize>0 );
if( nSize>pageSize ){
fossil_panic("key too large: %u versus %u", nSize, pageSize);
}
p = fossil_secure_alloc_page(&n);
assert( p!=NULL );
assert( n==pageSize );
assert( n>=nSize );
{
#if defined(_WIN32)
HANDLE hProcess = OpenProcess(PROCESS_VM_READ, FALSE, processId);
if( hProcess!=NULL ){
SIZE_T nRead = 0;
if( ReadProcessMemory(hProcess, pAddress, p, nSize, &nRead) ){
CloseHandle(hProcess);
if( nRead==nSize ){
db_unsave_encryption_key();
zSavedKey = p;
savedKeySize = n;
}else{
fossil_secure_free_page(p, n);
fossil_panic("bad size read, %u out of %u bytes at %p from pid %lu",
nRead, nSize, pAddress, processId);
}
}else{
CloseHandle(hProcess);
fossil_secure_free_page(p, n);
fossil_panic("failed read, %u bytes at %p from pid %lu: %lu", nSize,
pAddress, processId, GetLastError());
}
}else{
fossil_secure_free_page(p, n);
fossil_panic("failed to open pid %lu: %lu", processId, GetLastError());
}
#elif defined(__linux__)
ssize_t nRead;
struct iovec liov = {0};
struct iovec riov = {0};
liov.iov_base = p;
liov.iov_len = n;
riov.iov_base = pAddress;
riov.iov_len = nSize;
nRead = process_vm_readv(processId, &liov, 1, &riov, 1, 0);
if( nRead==nSize ){
db_unsave_encryption_key();
zSavedKey = p;
savedKeySize = n;
}else{
fossil_secure_free_page(p, n);
fossil_panic("bad size read, %zd out of %zu bytes at %p from pid %lu",
nRead, nSize, pAddress, (unsigned long)processId);
}
#else
fossil_secure_free_page(p, n);
fossil_panic("db_read_saved_encryption_key_from_process unsupported");
#endif
}
}
/*
** This function writes the saved database encryption key into the
** specified Fossil parent process. This is only necessary (or
** functional) on Windows or Linux.
*/
static void db_write_saved_encryption_key_to_process(
PID_T processId, /* Identifier for Fossil parent process. */
LPVOID pAddress, /* Pointer to saved key buffer in the parent process. */
SIZE_T nSize /* Size of saved key buffer in the parent process. */
){
void *p = db_get_saved_encryption_key();
size_t n = db_get_saved_encryption_key_size();
size_t pageSize = 0;
fossil_get_page_size(&pageSize);
assert( pageSize>0 );
if( nSize>pageSize ){
fossil_panic("key too large: %u versus %u", nSize, pageSize);
}
assert( p!=NULL );
assert( n==pageSize );
assert( n>=nSize );
{
#if defined(_WIN32)
HANDLE hProcess = OpenProcess(PROCESS_VM_OPERATION|PROCESS_VM_WRITE,
FALSE, processId);
if( hProcess!=NULL ){
SIZE_T nWrite = 0;
if( WriteProcessMemory(hProcess, pAddress, p, nSize, &nWrite) ){
CloseHandle(hProcess);
if( nWrite!=nSize ){
fossil_panic("bad size write, %u out of %u bytes at %p from pid %lu",
nRead, nSize, pAddress, processId);
}
}else{
CloseHandle(hProcess);
fossil_panic("failed write, %u bytes at %p from pid %lu: %lu", nSize,
pAddress, processId, GetLastError());
}
}else{
fossil_panic("failed to open pid %lu: %lu", processId, GetLastError());
}
#elif defined(__linux__)
ssize_t nWrite;
struct iovec liov = {0};
struct iovec riov = {0};
liov.iov_base = p;
liov.iov_len = n;
riov.iov_base = pAddress;
riov.iov_len = nSize;
nWrite = process_vm_writev(processId, &liov, 1, &riov, 1, 0);
if( nWrite!=nSize ){
fossil_panic("bad size write, %zd out of %zu bytes at %p from pid %lu",
nWrite, nSize, pAddress, (unsigned long)processId);
}
#else
fossil_panic("db_write_saved_encryption_key_to_process unsupported");
#endif
}
}
/*
** This function zero the saved database encryption key in the specified
** Fossil parent process. This is only necessary (or functional) on
** Windows or Linux.
*/
static void db_zero_saved_encryption_key_in_process(
PID_T processId, /* Identifier for Fossil parent process. */
LPVOID pAddress, /* Pointer to saved key buffer in the parent process. */
SIZE_T nSize /* Size of saved key buffer in the parent process. */
){
void *p = NULL;
size_t n = 0;
size_t pageSize = 0;
fossil_get_page_size(&pageSize);
assert( pageSize>0 );
if( nSize>pageSize ){
fossil_panic("key too large: %u versus %u", nSize, pageSize);
}
p = fossil_secure_alloc_page(&n);
assert( p!=NULL );
assert( n==pageSize );
assert( n>=nSize );
{
#if defined(_WIN32)
HANDLE hProcess = OpenProcess(PROCESS_VM_OPERATION|PROCESS_VM_WRITE,
FALSE, processId);
if( hProcess!=NULL ){
SIZE_T nWrite = 0;
if( WriteProcessMemory(hProcess, pAddress, p, nSize, &nWrite) ){
CloseHandle(hProcess);
fossil_secure_free_page(p, n);
if( nWrite!=nSize ){
fossil_panic("bad size zero, %u out of %u bytes at %p from pid %lu",
nRead, nSize, pAddress, processId);
}
}else{
CloseHandle(hProcess);
fossil_secure_free_page(p, n);
fossil_panic("failed zero, %u bytes at %p from pid %lu: %lu", nSize,
pAddress, processId, GetLastError());
}
}else{
fossil_secure_free_page(p, n);
fossil_panic("failed to open pid %lu: %lu", processId, GetLastError());
}
#elif defined(__linux__)
ssize_t nWrite;
struct iovec liov = {0};
struct iovec riov = {0};
liov.iov_base = p;
liov.iov_len = n;
riov.iov_base = pAddress;
riov.iov_len = nSize;
nWrite = process_vm_writev(processId, &liov, 1, &riov, 1, 0);
if( nWrite!=nSize ){
fossil_secure_free_page(p, n);
fossil_panic("bad size zero, %zd out of %zu bytes at %p from pid %lu",
nWrite, nSize, pAddress, (unsigned long)processId);
}
#else
fossil_secure_free_page(p, n);
fossil_panic("db_zero_saved_encryption_key_in_process unsupported");
#endif
}
}
/*
** This function evaluates the specified TH1 script and attempts to parse
** its result as a colon-delimited triplet containing a process identifier,
** address, and size (in bytes) of the database encryption key. This is
** only necessary (or functional) on Windows or Linux.
*/
static PID_T db_handle_saved_encryption_key_for_process_via_th1(
const char *zConfig, /* The TH1 script to evaluate. */
int eType /* Non-zero to write key to parent process -OR-
* zero to read it from the parent process. */
){
PID_T processId = 0;
int rc;
char *zResult;
char *zPwd = file_getcwd(0, 0);
Th_FossilInit(TH_INIT_DEFAULT | TH_INIT_NEED_CONFIG | TH_INIT_NO_REPO);
rc = Th_Eval(g.interp, 0, zConfig, -1);
zResult = (char*)Th_GetResult(g.interp, 0);
if( rc!=TH_OK ){
fossil_fatal("script for pid key failed: %s", zResult);
}
if( zResult ){
LPVOID pAddress = NULL;
SIZE_T nSize = 0;
parse_pid_key_value(zResult, &processId, &pAddress, &nSize);
if( eType==SEE_KEY_READ ){
db_read_saved_encryption_key_from_process(processId, pAddress, nSize);
}else if( eType==SEE_KEY_WRITE ){
db_write_saved_encryption_key_to_process(processId, pAddress, nSize);
}else if( eType==SEE_KEY_ZERO ){
db_zero_saved_encryption_key_in_process(processId, pAddress, nSize);
}else{
fossil_panic("unsupported SEE key operation %d", eType);
}
}
file_chdir(zPwd, 0);
fossil_free(zPwd);
return processId;
}
/*
** This function sets the saved database encryption key to one that gets
** read from the specified Fossil parent process, if applicable. This is
** only necessary (or functional) on Windows or Linux.
*/
PID_T db_maybe_handle_saved_encryption_key_for_process(int eType){
PID_T processId = 0;
g.zPidKey = find_option("usepidkey",0,1);
if( !g.zPidKey ){
g.zPidKey = fossil_getenv("FOSSIL_SEE_PID_KEY");
}
if( g.zPidKey ){
LPVOID pAddress = NULL;
SIZE_T nSize = 0;
parse_pid_key_value(g.zPidKey, &processId, &pAddress, &nSize);
if( eType==SEE_KEY_READ ){
db_read_saved_encryption_key_from_process(processId, pAddress, nSize);
}else if( eType==SEE_KEY_WRITE ){
db_write_saved_encryption_key_to_process(processId, pAddress, nSize);
}else if( eType==SEE_KEY_ZERO ){
db_zero_saved_encryption_key_in_process(processId, pAddress, nSize);
}else{
fossil_panic("unsupported SEE key operation %d", eType);
}
}else{
const char *zSeeDbConfig = find_option("seedbcfg",0,1);
if( !zSeeDbConfig ){
zSeeDbConfig = fossil_getenv("FOSSIL_SEE_DB_CONFIG");
}
if( zSeeDbConfig ){
processId = db_handle_saved_encryption_key_for_process_via_th1(
zSeeDbConfig, eType
);
}
}
return processId;
}
#endif /* USE_SEE */
/*
** If the database file zDbFile has a name that suggests that it is
** encrypted, then prompt for the database encryption key and return it
** in the blob *pKey. Or, if the encryption key has previously been
** requested, just return a copy of the previous result. The blob in
|
| ︙ | ︙ |
Changes to src/file.c.
| ︙ | ︙ | |||
2275 2276 2277 2278 2279 2280 2281 2282 2283 2284 2285 2286 2287 2288 |
*/
void file_test_valid_for_windows(void){
int i;
for(i=2; i<g.argc; i++){
fossil_print("%s %s\n", file_is_win_reserved(g.argv[i]), g.argv[i]);
}
}
/*
** Remove surplus "/" characters from the beginning of a full pathname.
** Extra leading "/" characters are benign on unix. But on Windows
** machines, they must be removed. Example: Convert "/C:/fossil/xyx.fossil"
** into "C:/fossil/xyz.fossil". Cygwin should behave as Windows here.
*/
| > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 2275 2276 2277 2278 2279 2280 2281 2282 2283 2284 2285 2286 2287 2288 2289 2290 2291 2292 2293 2294 2295 2296 2297 2298 2299 2300 2301 2302 2303 2304 2305 2306 2307 2308 2309 2310 2311 2312 2313 2314 2315 2316 2317 2318 2319 2320 2321 2322 2323 2324 2325 2326 2327 2328 2329 2330 2331 |
*/
void file_test_valid_for_windows(void){
int i;
for(i=2; i<g.argc; i++){
fossil_print("%s %s\n", file_is_win_reserved(g.argv[i]), g.argv[i]);
}
}
/*
** Returns non-zero if the specified file extension belongs to a Fossil
** repository file.
*/
int file_is_repository_extension(const char *zPath){
if( fossil_strcmp(zPath, ".fossil")==0 ) return 1;
#if USE_SEE
if( fossil_strcmp(zPath, ".efossil")==0 ) return 1;
#endif
return 0;
}
/*
** Returns non-zero if the specified path appears to match a file extension
** that should belong to a Fossil repository file.
*/
int file_contains_repository_extension(const char *zPath){
if( sqlite3_strglob("*.fossil*",zPath)==0 ) return 1;
#if USE_SEE
if( sqlite3_strglob("*.efossil*",zPath)==0 ) return 1;
#endif
return 0;
}
/*
** Returns non-zero if the specified path ends with a file extension that
** should belong to a Fossil repository file.
*/
int file_ends_with_repository_extension(const char *zPath, int bQual){
if( bQual ){
if( sqlite3_strglob("*/*.fossil", zPath)==0 ) return 1;
#if USE_SEE
if( sqlite3_strglob("*/*.efossil", zPath)==0 ) return 1;
#endif
}else{
if( sqlite3_strglob("*.fossil", zPath)==0 ) return 1;
#if USE_SEE
if( sqlite3_strglob("*.efossil", zPath)==0 ) return 1;
#endif
}
return 0;
}
/*
** Remove surplus "/" characters from the beginning of a full pathname.
** Extra leading "/" characters are benign on unix. But on Windows
** machines, they must be removed. Example: Convert "/C:/fossil/xyx.fossil"
** into "C:/fossil/xyz.fossil". Cygwin should behave as Windows here.
*/
|
| ︙ | ︙ |
Changes to src/main.c.
| ︙ | ︙ | |||
22 23 24 25 26 27 28 29 30 31 32 33 34 35 | #include "config.h" #if defined(_WIN32) # include <windows.h> # include <io.h> # define isatty(h) _isatty(h) # define GETPID (int)GetCurrentProcessId #endif #include "main.h" #include <string.h> #include <time.h> #include <fcntl.h> #include <sys/types.h> #include <sys/stat.h> #include <stdlib.h> /* atexit() */ | > > > > > > > > > > | 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 | #include "config.h" #if defined(_WIN32) # include <windows.h> # include <io.h> # define isatty(h) _isatty(h) # define GETPID (int)GetCurrentProcessId #endif /* BUGBUG: This (PID_T) does not work inside of INTERFACE block. */ #if USE_SEE #if defined(_WIN32) typedef DWORD PID_T; #else typedef pid_t PID_T; #endif #endif #include "main.h" #include <string.h> #include <time.h> #include <fcntl.h> #include <sys/types.h> #include <sys/stat.h> #include <stdlib.h> /* atexit() */ |
| ︙ | ︙ | |||
214 215 216 217 218 219 220 |
Blob httpHeader; /* Complete text of the HTTP request header */
UrlData url; /* Information about current URL */
const char *zLogin; /* Login name. NULL or "" if not logged in. */
const char *zCkoutAlias; /* doc/ uses this branch as an alias for "ckout" */
const char *zMainMenuFile; /* --mainmenu FILE from server/ui/cgi */
const char *zSSLIdentity; /* Value of --ssl-identity option, filename of
** SSL client identity */
| | | | 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 |
Blob httpHeader; /* Complete text of the HTTP request header */
UrlData url; /* Information about current URL */
const char *zLogin; /* Login name. NULL or "" if not logged in. */
const char *zCkoutAlias; /* doc/ uses this branch as an alias for "ckout" */
const char *zMainMenuFile; /* --mainmenu FILE from server/ui/cgi */
const char *zSSLIdentity; /* Value of --ssl-identity option, filename of
** SSL client identity */
#if USE_SEE
const char *zPidKey; /* Saved value of the --usepidkey option. Only
* applicable when using SEE on Windows or Linux. */
#endif
int useLocalauth; /* No login required if from 127.0.0.1 */
int noPswd; /* Logged in without password (on 127.0.0.1) */
int userUid; /* Integer user id */
int isHuman; /* True if access by a human, not a spider or bot */
int comFmtFlags; /* Zero or more "COMMENT_PRINT_*" bit flags, should be
** accessed through get_comment_format(). */
|
| ︙ | ︙ | |||
798 799 800 801 802 803 804 |
g.zErrlog = find_option("errorlog", 0, 1);
fossil_init_flags_from_options();
if( find_option("utc",0,0) ) g.fTimeFormat = 1;
if( find_option("localtime",0,0) ) g.fTimeFormat = 2;
if( zChdir && file_chdir(zChdir, 0) ){
fossil_fatal("unable to change directories to %s", zChdir);
}
| | < < < < < < < < < < < < < < | < < < | 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 |
g.zErrlog = find_option("errorlog", 0, 1);
fossil_init_flags_from_options();
if( find_option("utc",0,0) ) g.fTimeFormat = 1;
if( find_option("localtime",0,0) ) g.fTimeFormat = 2;
if( zChdir && file_chdir(zChdir, 0) ){
fossil_fatal("unable to change directories to %s", zChdir);
}
#if USE_SEE
db_maybe_handle_saved_encryption_key_for_process(SEE_KEY_READ);
#endif
if( find_option("help",0,0)!=0 ){
/* If --help is found anywhere on the command line, translate the command
* to "fossil help cmdname" where "cmdname" is the first argument that
* does not begin with a "-" character. If all arguments start with "-",
* translate to "fossil help argv[1] argv[2]...". */
int i, nNewArgc;
|
| ︙ | ︙ | |||
1268 1269 1270 1271 1272 1273 1274 | #if defined(HAVE_PLEDGE) blob_append(pOut, "HAVE_PLEDGE\n", -1); #endif #if defined(USE_MMAN_H) blob_append(pOut, "USE_MMAN_H\n", -1); #endif #if defined(USE_SEE) | | > | 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 |
#if defined(HAVE_PLEDGE)
blob_append(pOut, "HAVE_PLEDGE\n", -1);
#endif
#if defined(USE_MMAN_H)
blob_append(pOut, "USE_MMAN_H\n", -1);
#endif
#if defined(USE_SEE)
blob_appendf(pOut, "USE_SEE (%s)\n",
db_have_saved_encryption_key() ? "SET" : "UNSET");
#endif
#if defined(FOSSIL_ALLOW_OUT_OF_ORDER_DATES)
blob_append(pOut, "FOSSIL_ALLOW_OUT_OF_ORDER_DATES\n");
#endif
if( g.db==0 ) sqlite3_open(":memory:", &g.db);
db_prepare(&q,
|
| ︙ | ︙ | |||
1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 |
json_bootstrap_early();
}
#endif
/* If the repository has not been opened already, then find the
** repository based on the first element of PATH_INFO and open it.
*/
if( !g.repositoryOpen ){
char *zRepo; /* Candidate repository name */
char *zToFree = 0; /* Malloced memory that needs to be freed */
const char *zCleanRepo; /* zRepo with surplus leading "/" removed */
const char *zOldScript = PD("SCRIPT_NAME", ""); /* Original SCRIPT_NAME */
char *zNewScript; /* Revised SCRIPT_NAME after processing */
int j, k; /* Loop variables */
i64 szFile; /* File size of the candidate repository */
| > | 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 |
json_bootstrap_early();
}
#endif
/* If the repository has not been opened already, then find the
** repository based on the first element of PATH_INFO and open it.
*/
if( !g.repositoryOpen ){
const char *zRepoExt = ".fossil";
char *zRepo; /* Candidate repository name */
char *zToFree = 0; /* Malloced memory that needs to be freed */
const char *zCleanRepo; /* zRepo with surplus leading "/" removed */
const char *zOldScript = PD("SCRIPT_NAME", ""); /* Original SCRIPT_NAME */
char *zNewScript; /* Revised SCRIPT_NAME after processing */
int j, k; /* Loop variables */
i64 szFile; /* File size of the candidate repository */
|
| ︙ | ︙ | |||
1735 1736 1737 1738 1739 1740 1741 |
}
while( 1 ){
size_t nBase = strlen(zBase);
while( zPathInfo[i] && zPathInfo[i]!='/' ){ i++; }
/* The candidate repository name is some prefix of the PATH_INFO
** with ".fossil" appended */
| | | 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 |
}
while( 1 ){
size_t nBase = strlen(zBase);
while( zPathInfo[i] && zPathInfo[i]!='/' ){ i++; }
/* The candidate repository name is some prefix of the PATH_INFO
** with ".fossil" appended */
zRepo = zToFree = mprintf("%s%.*s%s",zBase,i,zPathInfo,zRepoExt);
if( g.fHttpTrace ){
@ <!-- Looking for repository named "%h(zRepo)" -->
fprintf(stderr, "# looking for repository named \"%s\"\n", zRepo);
}
/* For safety -- to prevent an attacker from accessing arbitrary disk
|
| ︙ | ︙ | |||
1806 1807 1808 1809 1810 1811 1812 |
/* If no file named by zRepo exists, remove the added ".fossil" suffix
** and check to see if there is a file or directory with the same
** name as the raw PATH_INFO text.
*/
if( szFile<0 && i>0 ){
const char *zMimetype;
| | | 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 |
/* If no file named by zRepo exists, remove the added ".fossil" suffix
** and check to see if there is a file or directory with the same
** name as the raw PATH_INFO text.
*/
if( szFile<0 && i>0 ){
const char *zMimetype;
assert( file_is_repository_extension(&zRepo[j]) );
zRepo[j] = 0; /* Remove the ".fossil" suffix */
/* The PATH_INFO prefix seen so far is a valid directory.
** Continue the loop with the next element of the PATH_INFO */
if( zPathInfo[i]=='/' && file_isdir(zCleanRepo, ExtFILE)==1 ){
fossil_free(zToFree);
i++;
|
| ︙ | ︙ | |||
1831 1832 1833 1834 1835 1836 1837 |
** general-purpose web server. The "--file GLOB" mechanism is
** designed to allow the delivery of a few static images or HTML
** pages.
*/
if( pFileGlob!=0
&& file_isfile(zCleanRepo, ExtFILE)
&& glob_match(pFileGlob, file_cleanup_fullpath(zRepo+nBase))
| | | 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 |
** general-purpose web server. The "--file GLOB" mechanism is
** designed to allow the delivery of a few static images or HTML
** pages.
*/
if( pFileGlob!=0
&& file_isfile(zCleanRepo, ExtFILE)
&& glob_match(pFileGlob, file_cleanup_fullpath(zRepo+nBase))
&& !file_contains_repository_extension(zRepo)
&& (zMimetype = mimetype_from_name(zRepo))!=0
&& strcmp(zMimetype, "application/x-fossil-artifact")!=0
){
Blob content;
blob_read_from_file(&content, file_cleanup_fullpath(zRepo), ExtFILE);
cgi_set_content_type(zMimetype);
cgi_set_content(&content);
|
| ︙ | ︙ | |||
1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 |
/* If we reach this point, it means that the search of the PATH_INFO
** string is finished. Either zRepo contains the name of the
** repository to be used, or else no repository could be found and
** some kind of error response is required.
*/
if( szFile<1024 ){
set_base_url(0);
if( (zPathInfo[0]==0 || strcmp(zPathInfo,"/")==0)
&& allowRepoList
&& repo_list_page() ){
/* Will return a list of repositories */
}else if( zNotFound ){
cgi_redirect(zNotFound);
| > > > > > > > | 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 |
/* If we reach this point, it means that the search of the PATH_INFO
** string is finished. Either zRepo contains the name of the
** repository to be used, or else no repository could be found and
** some kind of error response is required.
*/
if( szFile<1024 ){
#if USE_SEE
if( strcmp(zRepoExt,".fossil")==0 ){
fossil_free(zToFree);
zRepoExt = ".efossil";
continue;
}
#endif
set_base_url(0);
if( (zPathInfo[0]==0 || strcmp(zPathInfo,"/")==0)
&& allowRepoList
&& repo_list_page() ){
/* Will return a list of repositories */
}else if( zNotFound ){
cgi_redirect(zNotFound);
|
| ︙ | ︙ | |||
1891 1892 1893 1894 1895 1896 1897 1898 1899 1900 1901 1902 1903 1904 |
*/
zNewScript = mprintf("%s%.*s", zOldScript, i, zPathInfo);
if( g.zTop ) g.zTop = mprintf("%R%.*s", i, zPathInfo);
if( g.zBaseURL ) g.zBaseURL = mprintf("%s%.*s", g.zBaseURL, i, zPathInfo);
cgi_replace_parameter("PATH_INFO", &zPathInfo[i+1]);
zPathInfo += i;
cgi_replace_parameter("SCRIPT_NAME", zNewScript);
db_open_repository(file_cleanup_fullpath(zRepo));
if( g.fHttpTrace ){
@ <!-- repository: "%h(zRepo)" -->
@ <!-- translated PATH_INFO: "%h(zPathInfo)" -->
@ <!-- translated SCRIPT_NAME: "%h(zNewScript)" -->
fprintf(stderr,
"# repository: [%s]\n"
| > > > > > > > > > | 1893 1894 1895 1896 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 |
*/
zNewScript = mprintf("%s%.*s", zOldScript, i, zPathInfo);
if( g.zTop ) g.zTop = mprintf("%R%.*s", i, zPathInfo);
if( g.zBaseURL ) g.zBaseURL = mprintf("%s%.*s", g.zBaseURL, i, zPathInfo);
cgi_replace_parameter("PATH_INFO", &zPathInfo[i+1]);
zPathInfo += i;
cgi_replace_parameter("SCRIPT_NAME", zNewScript);
#if USE_SEE
if( strcmp(zPathInfo,"/setseekey")==0
&& strcmp(zRepoExt,".efossil")==0
&& !db_have_saved_encryption_key() ){
db_set_see_key_page();
cgi_reply();
fossil_exit(0);
}
#endif
db_open_repository(file_cleanup_fullpath(zRepo));
if( g.fHttpTrace ){
@ <!-- repository: "%h(zRepo)" -->
@ <!-- translated PATH_INFO: "%h(zPathInfo)" -->
@ <!-- translated SCRIPT_NAME: "%h(zNewScript)" -->
fprintf(stderr,
"# repository: [%s]\n"
|
| ︙ | ︙ | |||
2613 2614 2615 2616 2617 2618 2619 |
}else{
db_open_repository(zRepo);
}
}
}
}
| | | | | | > | > | > | | | 2624 2625 2626 2627 2628 2629 2630 2631 2632 2633 2634 2635 2636 2637 2638 2639 2640 2641 2642 2643 2644 2645 2646 2647 2648 2649 2650 2651 2652 2653 2654 2655 2656 2657 2658 2659 2660 2661 2662 2663 2664 2665 2666 2667 2668 2669 2670 2671 2672 2673 2674 2675 2676 2677 2678 2679 2680 2681 2682 2683 2684 2685 2686 2687 2688 2689 2690 2691 2692 2693 2694 2695 2696 |
}else{
db_open_repository(zRepo);
}
}
}
}
#if USE_SEE
/*
** This function attempts to parse a string value in the following
** format:
**
** "%lu:%p:%u"
**
** There are three parts, which must be delimited by colons. The
** first part is an unsigned long integer in base-10 (decimal) format.
** The second part is a numerical representation of a native pointer,
** in the appropriate implementation defined format. The third part
** is an unsigned integer in base-10 (decimal) format.
**
** If the specified value cannot be parsed, for any reason, a fatal
** error will be raised and the process will be terminated.
*/
void parse_pid_key_value(
const char *zPidKey, /* The value to be parsed. */
PID_T *pProcessId, /* The extracted process identifier. */
LPVOID *ppAddress, /* The extracted pointer value. */
SIZE_T *pnSize /* The extracted size value. */
){
unsigned long processId = 0;
unsigned int nSize = 0;
if( sscanf(zPidKey, "%lu:%p:%u", &processId, ppAddress, &nSize)==3 ){
*pProcessId = (PID_T)processId;
*pnSize = (SIZE_T)nSize;
}else{
fossil_fatal("failed to parse pid key");
}
}
#endif
/*
** WEBPAGE: test-pid
**
** Return the process identifier of the running Fossil server instance.
**
** Query parameters:
**
** usepidkey When present and available, also return the
** address and size, within this server process,
** of the saved database encryption key. This
** is only supported when using SEE on Windows
** or Linux.
*/
void test_pid_page(void){
login_check_credentials();
if( !g.perm.Setup ){ login_needed(0); return; }
#if USE_SEE
if( P("usepidkey")!=0 ){
if( g.zPidKey ){
@ %s(g.zPidKey)
return;
}else{
const char *zSavedKey = db_get_saved_encryption_key();
size_t savedKeySize = db_get_saved_encryption_key_size();
if( zSavedKey!=0 && savedKeySize>0 ){
@ %lu(GETPID()):%p(zSavedKey):%u(savedKeySize)
return;
}
}
}
#endif
@ %d(GETPID())
}
|
| ︙ | ︙ | |||
2768 2769 2770 2771 2772 2773 2774 |
** --pkey FILE Read the private key used for TLS from FILE
** --repolist If REPOSITORY is directory, URL "/" lists all repos
** --scgi Interpret input as SCGI rather than HTTP
** --skin LABEL Use override skin LABEL. Use an empty string ("")
** to force use of the current local skin config.
** --th-trace Trace TH1 execution (for debugging purposes)
** --usepidkey Use saved encryption key from parent process. This is
| | | 2782 2783 2784 2785 2786 2787 2788 2789 2790 2791 2792 2793 2794 2795 2796 |
** --pkey FILE Read the private key used for TLS from FILE
** --repolist If REPOSITORY is directory, URL "/" lists all repos
** --scgi Interpret input as SCGI rather than HTTP
** --skin LABEL Use override skin LABEL. Use an empty string ("")
** to force use of the current local skin config.
** --th-trace Trace TH1 execution (for debugging purposes)
** --usepidkey Use saved encryption key from parent process. This is
** only necessary when using SEE on Windows or Linux.
**
** See also: [[cgi]], [[server]], [[winsrv]]
*/
void cmd_http(void){
const char *zIpAddr = 0;
const char *zNotFound;
const char *zHost;
|
| ︙ | ︙ | |||
3109 3110 3111 3112 3113 3114 3115 | ** --pkey FILE Read the private key used for TLS from FILE ** -P|--port TCPPORT Listen to request on port TCPPORT ** --repolist If REPOSITORY is dir, URL "/" lists repos ** --scgi Accept SCGI rather than HTTP ** --skin LABEL Use override skin LABEL ** --th-trace Trace TH1 execution (for debugging purposes) ** --usepidkey Use saved encryption key from parent process. This is | | | 3123 3124 3125 3126 3127 3128 3129 3130 3131 3132 3133 3134 3135 3136 3137 |
** --pkey FILE Read the private key used for TLS from FILE
** -P|--port TCPPORT Listen to request on port TCPPORT
** --repolist If REPOSITORY is dir, URL "/" lists repos
** --scgi Accept SCGI rather than HTTP
** --skin LABEL Use override skin LABEL
** --th-trace Trace TH1 execution (for debugging purposes)
** --usepidkey Use saved encryption key from parent process. This is
** only necessary when using SEE on Windows or Linux.
**
** See also: [[cgi]], [[http]], [[winsrv]]
*/
void cmd_webserver(void){
int iPort, mxPort; /* Range of TCP ports allowed */
const char *zPort; /* Value of the --port option */
const char *zBrowser; /* Name of web browser program */
|
| ︙ | ︙ | |||
3138 3139 3140 3141 3142 3143 3144 3145 3146 3147 3148 3149 3150 3151 |
int fNoBrowser = 0; /* Do not auto-launch web-browser */
const char *zInitPage = 0; /* Start on this page. --page option */
int findServerArg = 2; /* argv index for find_server_repository() */
char *zRemote = 0; /* Remote host on which to run "fossil ui" */
const char *zJsMode; /* The --jsmode parameter */
const char *zFossilCmd =0; /* Name of "fossil" binary on remote system */
#if defined(_WIN32)
const char *zStopperFile; /* Name of file used to terminate server */
zStopperFile = find_option("stopper", 0, 1);
#endif
if( g.zErrlog==0 ){
| > > > > | 3152 3153 3154 3155 3156 3157 3158 3159 3160 3161 3162 3163 3164 3165 3166 3167 3168 3169 |
int fNoBrowser = 0; /* Do not auto-launch web-browser */
const char *zInitPage = 0; /* Start on this page. --page option */
int findServerArg = 2; /* argv index for find_server_repository() */
char *zRemote = 0; /* Remote host on which to run "fossil ui" */
const char *zJsMode; /* The --jsmode parameter */
const char *zFossilCmd =0; /* Name of "fossil" binary on remote system */
#if USE_SEE
db_setup_for_saved_encryption_key();
#endif
#if defined(_WIN32)
const char *zStopperFile; /* Name of file used to terminate server */
zStopperFile = find_option("stopper", 0, 1);
#endif
if( g.zErrlog==0 ){
|
| ︙ | ︙ |
Changes to src/repolist.c.
| ︙ | ︙ | |||
141 142 143 144 145 146 147 |
** directory.
*/
blob_init(&base, g.zRepositoryName, -1);
sqlite3_open(":memory:", &g.db);
db_multi_exec("CREATE TABLE sfile(pathname TEXT);");
db_multi_exec("CREATE TABLE vfile(pathname);");
vfile_scan(&base, blob_size(&base), 0, 0, 0, ExtFILE);
| | > > > > | 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 |
** directory.
*/
blob_init(&base, g.zRepositoryName, -1);
sqlite3_open(":memory:", &g.db);
db_multi_exec("CREATE TABLE sfile(pathname TEXT);");
db_multi_exec("CREATE TABLE vfile(pathname);");
vfile_scan(&base, blob_size(&base), 0, 0, 0, ExtFILE);
db_multi_exec("DELETE FROM sfile WHERE pathname NOT GLOB '*[^/].fossil'"
#if USE_SEE
" AND pathname NOT GLOB '*[^/].efossil'"
#endif
);
allRepo = 0;
}
n = db_int(0, "SELECT count(*) FROM sfile");
if( n==0 ){
sqlite3_close(g.db);
g.db = 0;
g.repositoryOpen = 0;
|
| ︙ | ︙ | |||
168 169 170 171 172 173 174 175 176 177 178 179 |
"</thead><tbody>\n");
db_prepare(&q, "SELECT pathname"
" FROM sfile ORDER BY pathname COLLATE nocase;");
rNow = db_double(0, "SELECT julianday('now')");
while( db_step(&q)==SQLITE_ROW ){
const char *zName = db_column_text(&q, 0);
int nName = (int)strlen(zName);
char *zUrl;
char *zAge;
char *zFull;
RepoInfo x;
sqlite3_int64 iAge;
| > > > > > | | | > > > > | | | > > > | > > > > | 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 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 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 |
"</thead><tbody>\n");
db_prepare(&q, "SELECT pathname"
" FROM sfile ORDER BY pathname COLLATE nocase;");
rNow = db_double(0, "SELECT julianday('now')");
while( db_step(&q)==SQLITE_ROW ){
const char *zName = db_column_text(&q, 0);
int nName = (int)strlen(zName);
int nSuffix = 7; /* ".fossil" */
char *zUrl;
char *zAge;
char *zFull;
RepoInfo x;
sqlite3_int64 iAge;
#if USE_SEE
int bEncrypted = sqlite3_strglob("*.efossil", zName)==0;
if( bEncrypted ) nSuffix = 8; /* ".efossil" */
#endif
if( nName<nSuffix ) continue;
zUrl = sqlite3_mprintf("%.*s", nName-nSuffix, zName);
if( zName[0]=='/'
#ifdef _WIN32
|| sqlite3_strglob("[a-zA-Z]:/*", zName)==0
#endif
){
zFull = mprintf("%s", zName);
}else if ( allRepo ){
zFull = mprintf("/%s", zName);
}else{
zFull = mprintf("%s/%s", g.zRepositoryName, zName);
}
x.zRepoName = zFull;
remote_repo_info(&x);
if( x.isRepolistSkin ){
if( zSkinRepo==0 ){
zSkinRepo = mprintf("%s", x.zRepoName);
zSkinUrl = mprintf("%s", zUrl);
}
}
fossil_free(zFull);
if( !x.isValid
#if USE_SEE
&& !bEncrypted
#endif
){
continue;
}
if( x.isRepolistSkin==2 && !allRepo ){
/* Repositories with repolist-skin==2 are omitted from directory
** scan lists, but included in "fossil all ui" lists */
continue;
}
if( rNow <= x.rMTime ){
x.rMTime = rNow;
}else if( x.rMTime<0.0 ){
x.rMTime = rNow;
}
iAge = (sqlite3_int64)((rNow - x.rMTime)*86400);
zAge = human_readable_age(rNow - x.rMTime);
if( x.rMTime==0.0 ){
/* This repository has no entry in the "event" table.
** Its age will still be maximum, so data-sortkey will work. */
zAge = mprintf("unknown");
}
blob_append_sql(&html, "<tr><td valign='top'>");
if( !file_ends_with_repository_extension(zName,0) ){
/* The "fossil server DIRECTORY" and "fossil ui DIRECTORY" commands
** do not work for repositories whose names do not end in ".fossil".
** So do not hyperlink those cases. */
blob_append_sql(&html,"%h",zName);
} else if( sqlite3_strglob("*/.*", zName)==0 ){
/* Do not show hyperlinks for hidden repos */
blob_append_sql(&html, "%h (hidden)", zName);
} else if( allRepo && sqlite3_strglob("[a-zA-Z]:/?*", zName)!=0 ){
blob_append_sql(&html,
"<a href='%R/%T/home' target='_blank'>/%h</a>\n",
zUrl, zName);
}else if( file_ends_with_repository_extension(zName,1) ){
/* As described in
** https://fossil-scm.org/forum/info/f50f647c97c72fc1: if
** foo.fossil and foo/bar.fossil both exist and we create a
** link to foo/bar/... then the URI dispatcher will instead
** see that as a link to foo.fossil. In such cases, do not
** emit a link to foo/bar.fossil. */
char * zDirPart = file_dirname(zName);
if( db_exists("SELECT 1 FROM sfile "
"WHERE pathname=(%Q || '.fossil') COLLATE nocase"
#if USE_SEE
" OR pathname=(%Q || '.efossil') COLLATE nocase"
#endif
, zDirPart
#if USE_SEE
, zDirPart
#endif
) ){
blob_append_sql(&html,
"<s>%h</s> (directory/repo name collision)\n",
zName);
}else{
blob_append_sql(&html,
"<a href='%R/%T/home' target='_blank'>%h</a>\n",
zUrl, zName);
|
| ︙ | ︙ |
Changes to src/sqlcmd.c.
| ︙ | ︙ | |||
285 286 287 288 289 290 291 |
** is pointed to by the value placed in pzKey must be obtained from malloc.
*/
void fossil_key(const char **pzKey, int *pnKey){
char *zSavedKey = db_get_saved_encryption_key();
char *zKey;
size_t savedKeySize = db_get_saved_encryption_key_size();
| | | 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 |
** is pointed to by the value placed in pzKey must be obtained from malloc.
*/
void fossil_key(const char **pzKey, int *pnKey){
char *zSavedKey = db_get_saved_encryption_key();
char *zKey;
size_t savedKeySize = db_get_saved_encryption_key_size();
if( !db_is_valid_saved_encryption_key(zSavedKey, savedKeySize) ) return;
zKey = (char*)malloc( savedKeySize );
if( zKey ){
memcpy(zKey, zSavedKey, savedKeySize);
*pzKey = zKey;
if( fossil_getenv("FOSSIL_USE_SEE_TEXTKEY")==0 ){
*pnKey = (int)strlen(zKey);
}else{
|
| ︙ | ︙ |
Changes to src/winhttp.c.
| ︙ | ︙ | |||
623 624 625 626 627 628 629 |
if( builtin_get_js_delivery_mode()!=0 /* JS_INLINE==0 may change? */ ){
blob_appendf(&options, " --jsmode ");
blob_append_escaped_arg(&options, builtin_get_js_delivery_mode_name(), 0);
}
#if USE_SEE
zSavedKey = db_get_saved_encryption_key();
savedKeySize = db_get_saved_encryption_key_size();
| | | 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 |
if( builtin_get_js_delivery_mode()!=0 /* JS_INLINE==0 may change? */ ){
blob_appendf(&options, " --jsmode ");
blob_append_escaped_arg(&options, builtin_get_js_delivery_mode_name(), 0);
}
#if USE_SEE
zSavedKey = db_get_saved_encryption_key();
savedKeySize = db_get_saved_encryption_key_size();
if( db_is_valid_saved_encryption_key(zSavedKey, savedKeySize) ){
blob_appendf(&options, " --usepidkey %lu:%p:%u", GetCurrentProcessId(),
zSavedKey, savedKeySize);
}
#endif
if( WSAStartup(MAKEWORD(2,0), &wd) ){
fossil_panic("unable to initialize winsock");
}
|
| ︙ | ︙ |