|
Lines 1622-1629
Link Here
|
| 1622 |
char *cp; |
1622 |
char *cp; |
| 1623 |
char *timefield; |
1623 |
char *timefield; |
| 1624 |
|
1624 |
|
| 1625 |
if (error_pending ()) |
1625 |
if (error_pending ()) return; |
| 1626 |
return; |
|
|
| 1627 |
|
1626 |
|
| 1628 |
if (outside_dir (arg)) |
1627 |
if (outside_dir (arg)) |
| 1629 |
return; |
1628 |
return; |
|
Lines 1637-1645
Link Here
|
| 1637 |
&& strlen (arg) == cp - name |
1636 |
&& strlen (arg) == cp - name |
| 1638 |
&& strncmp (arg, name, cp - name) == 0) |
1637 |
&& strncmp (arg, name, cp - name) == 0) |
| 1639 |
{ |
1638 |
{ |
| 1640 |
timefield = strchr (cp + 1, '/') + 1; |
1639 |
if (!(timefield = strchr (cp + 1, '/')) || *++timefield == '\0') |
| 1641 |
if (*timefield != '=') |
1640 |
{ |
|
|
1641 |
/* We didn't find the record separator or it is followed by |
| 1642 |
* the end of the string, so just exit. |
| 1643 |
*/ |
| 1644 |
if (alloc_pending (80)) |
| 1645 |
sprintf (pending_error_text, |
| 1646 |
"E Malformed Entry encountered."); |
| 1647 |
return; |
| 1648 |
} |
| 1649 |
/* If the time field is not currently empty, then one of |
| 1650 |
* serve_modified, serve_is_modified, & serve_unchanged were |
| 1651 |
* already called for this file. We would like to ignore the |
| 1652 |
* reinvocation silently or, better yet, exit with an error |
| 1653 |
* message, but we just avoid the copy-forward and overwrite the |
| 1654 |
* value from the last invocation instead. See the comment below |
| 1655 |
* for more. |
| 1656 |
*/ |
| 1657 |
if (*timefield == '/') |
| 1642 |
{ |
1658 |
{ |
|
|
1659 |
/* Copy forward one character. Space was allocated for this |
| 1660 |
* already in serve_entry(). */ |
| 1643 |
cp = timefield + strlen (timefield); |
1661 |
cp = timefield + strlen (timefield); |
| 1644 |
cp[1] = '\0'; |
1662 |
cp[1] = '\0'; |
| 1645 |
while (cp > timefield) |
1663 |
while (cp > timefield) |
|
Lines 1647-1654
Link Here
|
| 1647 |
*cp = cp[-1]; |
1665 |
*cp = cp[-1]; |
| 1648 |
--cp; |
1666 |
--cp; |
| 1649 |
} |
1667 |
} |
| 1650 |
*timefield = '='; |
|
|
| 1651 |
} |
1668 |
} |
|
|
1669 |
/* If *TIMEFIELD wasn't "/", we assume that it was because of |
| 1670 |
* multiple calls to Is-Modified & Unchanged by the client and |
| 1671 |
* just overwrite the value from the last call. Technically, we |
| 1672 |
* should probably either ignore calls after the first or send the |
| 1673 |
* client an error, since the client/server protocol specification |
| 1674 |
* specifies that only one call to either Is-Modified or Unchanged |
| 1675 |
* is allowed, but broken versions of WinCVS & TortoiseCVS rely on |
| 1676 |
* this behavior. |
| 1677 |
*/ |
| 1678 |
*timefield = '='; |
| 1652 |
break; |
1679 |
break; |
| 1653 |
} |
1680 |
} |
| 1654 |
} |
1681 |
} |
|
Lines 1665-1672
Link Here
|
| 1665 |
/* Have we found this file in "entries" yet. */ |
1692 |
/* Have we found this file in "entries" yet. */ |
| 1666 |
int found; |
1693 |
int found; |
| 1667 |
|
1694 |
|
| 1668 |
if (error_pending ()) |
1695 |
if (error_pending ()) return; |
| 1669 |
return; |
|
|
| 1670 |
|
1696 |
|
| 1671 |
if (outside_dir (arg)) |
1697 |
if (outside_dir (arg)) |
| 1672 |
return; |
1698 |
return; |
|
Lines 1681-1689
Link Here
|
| 1681 |
&& strlen (arg) == cp - name |
1707 |
&& strlen (arg) == cp - name |
| 1682 |
&& strncmp (arg, name, cp - name) == 0) |
1708 |
&& strncmp (arg, name, cp - name) == 0) |
| 1683 |
{ |
1709 |
{ |
| 1684 |
timefield = strchr (cp + 1, '/') + 1; |
1710 |
if (!(timefield = strchr (cp + 1, '/')) || *++timefield == '\0') |
| 1685 |
if (!(timefield[0] == 'M' && timefield[1] == '/')) |
|
|
| 1686 |
{ |
1711 |
{ |
|
|
1712 |
/* We didn't find the record separator or it is followed by |
| 1713 |
* the end of the string, so just exit. |
| 1714 |
*/ |
| 1715 |
if (alloc_pending (80)) |
| 1716 |
sprintf (pending_error_text, |
| 1717 |
"E Malformed Entry encountered."); |
| 1718 |
return; |
| 1719 |
} |
| 1720 |
/* If the time field is not currently empty, then one of |
| 1721 |
* serve_modified, serve_is_modified, & serve_unchanged were |
| 1722 |
* already called for this file. We would like to ignore the |
| 1723 |
* reinvocation silently or, better yet, exit with an error |
| 1724 |
* message, but we just avoid the copy-forward and overwrite the |
| 1725 |
* value from the last invocation instead. See the comment below |
| 1726 |
* for more. |
| 1727 |
*/ |
| 1728 |
if (*timefield == '/') |
| 1729 |
{ |
| 1730 |
/* Copy forward one character. Space was allocated for this |
| 1731 |
* already in serve_entry(). */ |
| 1687 |
cp = timefield + strlen (timefield); |
1732 |
cp = timefield + strlen (timefield); |
| 1688 |
cp[1] = '\0'; |
1733 |
cp[1] = '\0'; |
| 1689 |
while (cp > timefield) |
1734 |
while (cp > timefield) |
|
Lines 1691-1698
Link Here
|
| 1691 |
*cp = cp[-1]; |
1736 |
*cp = cp[-1]; |
| 1692 |
--cp; |
1737 |
--cp; |
| 1693 |
} |
1738 |
} |
| 1694 |
*timefield = 'M'; |
|
|
| 1695 |
} |
1739 |
} |
|
|
1740 |
/* If *TIMEFIELD wasn't "/", we assume that it was because of |
| 1741 |
* multiple calls to Is-Modified & Unchanged by the client and |
| 1742 |
* just overwrite the value from the last call. Technically, we |
| 1743 |
* should probably either ignore calls after the first or send the |
| 1744 |
* client an error, since the client/server protocol specification |
| 1745 |
* specifies that only one call to either Is-Modified or Unchanged |
| 1746 |
* is allowed, but broken versions of WinCVS & TortoiseCVS rely on |
| 1747 |
* this behavior. |
| 1748 |
*/ |
| 1749 |
*timefield = 'M'; |
| 1696 |
if (kopt != NULL) |
1750 |
if (kopt != NULL) |
| 1697 |
{ |
1751 |
{ |
| 1698 |
if (alloc_pending (strlen (name) + 80)) |
1752 |
if (alloc_pending (strlen (name) + 80)) |
|
Lines 1747-1754
Link Here
|
| 1747 |
{ |
1801 |
{ |
| 1748 |
struct an_entry *p; |
1802 |
struct an_entry *p; |
| 1749 |
char *cp; |
1803 |
char *cp; |
|
|
1804 |
int i = 0; |
| 1750 |
if (error_pending()) return; |
1805 |
if (error_pending()) return; |
| 1751 |
p = (struct an_entry *) xmalloc (sizeof (struct an_entry)); |
1806 |
|
|
|
1807 |
/* Verify that the entry is well-formed. This can avoid problems later. |
| 1808 |
* At the moment we only check that the Entry contains five slashes in |
| 1809 |
* approximately the correct locations since some of the code makes |
| 1810 |
* assumptions about this. |
| 1811 |
*/ |
| 1812 |
cp = arg; |
| 1813 |
if (*cp == 'D') cp++; |
| 1814 |
while (i++ < 5) |
| 1815 |
{ |
| 1816 |
if (!cp || *cp != '/') |
| 1817 |
{ |
| 1818 |
if (alloc_pending (80)) |
| 1819 |
sprintf (pending_error_text, |
| 1820 |
"E protocol error: Malformed Entry"); |
| 1821 |
return; |
| 1822 |
} |
| 1823 |
cp = strchr (cp + 1, '/'); |
| 1824 |
} |
| 1825 |
|
| 1826 |
p = xmalloc (sizeof (struct an_entry)); |
| 1752 |
if (p == NULL) |
1827 |
if (p == NULL) |
| 1753 |
{ |
1828 |
{ |
| 1754 |
pending_error = ENOMEM; |
1829 |
pending_error = ENOMEM; |