View | Details | Raw Unified | Return to bug 54773
Collapse All | Expand All

(-)server.c (-11 / +86 lines)
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;

Return to bug 54773