Changeset 19437 in josm for trunk


Ignore:
Timestamp:
2025-08-26T11:27:22+02:00 (6 weeks ago)
Author:
GerdP
Message:

fix #24446: Error loading way-history
Turned out that the OSM server counts the number of unicode code points, not the number of characters when checking the maximum lengths of keys and tags in tags.

  • implement new methods in Util to calculate the number of code points or check agains a given limit
  • fix long standing bug in ApiPreconditionCheckerHook.java which was introduced with r2906 (key -> value)
Location:
trunk/src/org/openstreetmap/josm
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/org/openstreetmap/josm/actions/upload/ApiPreconditionCheckerHook.java

    r17585 r19437  
    2323import org.openstreetmap.josm.io.OsmTransferCanceledException;
    2424import org.openstreetmap.josm.tools.Logging;
     25import org.openstreetmap.josm.tools.Utils;
    2526
    2627/**
     
    6465                String key = entry.getKey();
    6566                String value = entry.getValue();
    66                 if (key.length() > Tagged.MAX_TAG_LENGTH) {
     67                if (!Utils.checkCodePointCount(value, Tagged.MAX_TAG_LENGTH)) {
    6768                    if (osmPrimitive.isDeleted()) {
    6869                        // if OsmPrimitive is going to be deleted we automatically shorten the value
     
    7374                                )
    7475                        );
    75                         osmPrimitive.put(key, value.substring(0, Tagged.MAX_TAG_LENGTH));
     76                        osmPrimitive.put(key, Utils.shortenString(value, Tagged.MAX_TAG_LENGTH));
    7677                        continue;
    7778                    }
    7879                    JOptionPane.showMessageDialog(MainApplication.getMainFrame(),
    7980                            tr("Length of value for tag ''{0}'' on object {1} exceeds the max. allowed length {2}. Values length is {3}.",
    80                                     key, Long.toString(osmPrimitive.getId()), Tagged.MAX_TAG_LENGTH, value.length()
     81                                    key, Long.toString(osmPrimitive.getId()), Tagged.MAX_TAG_LENGTH, Utils.getCodePointCount(value)
    8182                            ),
    8283                            tr("Precondition violation"),
  • trunk/src/org/openstreetmap/josm/data/osm/Changeset.java

    r19366 r19437  
    1717import org.openstreetmap.josm.data.coor.LatLon;
    1818import org.openstreetmap.josm.tools.CheckParameterUtil;
     19import org.openstreetmap.josm.tools.Utils;
    1920
    2021/**
     
    313314        CheckParameterUtil.ensureParameterNotNull(keys, "keys");
    314315        keys.values().stream()
    315                 .filter(value -> value != null && value.length() > MAX_CHANGESET_TAG_LENGTH)
     316                .filter(value -> !Utils.checkCodePointCount(value, MAX_CHANGESET_TAG_LENGTH))
    316317                .findFirst()
    317318                .ifPresent(value -> {
     
    340341    public void put(String key, String value) {
    341342        CheckParameterUtil.ensureParameterNotNull(key, "key");
    342         if (value != null && value.length() > MAX_CHANGESET_TAG_LENGTH) {
    343             throw new IllegalArgumentException("Changeset tag value is too long: "+value);
     343        if (!Utils.checkCodePointCount(value, MAX_CHANGESET_TAG_LENGTH)) {
     344            throw new IllegalArgumentException("Changeset tag value is too long: " + value);
    344345        }
     346
    345347        this.tags.put(key, value);
    346348    }
  • trunk/src/org/openstreetmap/josm/data/validation/tests/TagChecker.java

    r19328 r19437  
    10161016            withErrors.put(p, "UUCV");
    10171017        }
    1018         if ((value.length() > Tagged.MAX_TAG_LENGTH) && !withErrors.contains(p, "LV")) {
     1018        final int codePoints = Utils.getCodePointCount(value);
     1019        if (codePoints > Tagged.MAX_TAG_LENGTH && !withErrors.contains(p, "LV")) {
    10191020            errors.add(TestError.builder(this, Severity.ERROR, LONG_VALUE)
    1020                     .message(tr("Tag value longer than {0} characters ({1} characters)", Tagged.MAX_TAG_LENGTH, value.length()), s, key)
     1021                    .message(tr("Tag value longer than {0} characters ({1} characters)", Tagged.MAX_TAG_LENGTH, codePoints), s, key)
    10211022                    .primitives(p)
    10221023                    .build());
     
    10651066            withErrors.put(p, "ICK");
    10661067        }
    1067         if (key.length() > Tagged.MAX_TAG_LENGTH && !withErrors.contains(p, "LK")) {
     1068        final int codePoints = Utils.getCodePointCount(key);
     1069        if (codePoints > Tagged.MAX_TAG_LENGTH && !withErrors.contains(p, "LK")) {
    10681070            errors.add(TestError.builder(this, Severity.ERROR, LONG_KEY)
    1069                     .message(tr("Tag key longer than {0} characters ({1} characters)", Tagged.MAX_TAG_LENGTH, key.length()), s, key)
     1071                    .message(tr("Tag key longer than {0} characters ({1} characters)", Tagged.MAX_TAG_LENGTH, codePoints), s, key)
    10701072                    .primitives(p)
    10711073                    .build());
  • trunk/src/org/openstreetmap/josm/tools/TextTagParser.java

    r19112 r19437  
    155155                if (r == 2 || r == 3) return false; if (r == 4) return true;
    156156            }
    157             if (value.length() > MAX_VALUE_LENGTH) {
    158                 r = callback.warning(tr("Value is too long (max {0} characters):", MAX_VALUE_LENGTH), value, "tags.paste.valuetoolong");
     157            if (!Utils.checkCodePointCount(value, MAX_VALUE_LENGTH)) {
     158                r = callback.warning(tr("Value is too long (max {0} characters):", MAX_VALUE_LENGTH), value, "");
    159159                if (r == 2 || r == 3) return false; if (r == 4) return true;
    160160            }
  • trunk/src/org/openstreetmap/josm/tools/Utils.java

    r19378 r19437  
    20262026        }
    20272027    }
     2028
     2029    /**
     2030     * Calculate the number of unicode code points. See #24446
     2031     * @param s the string
     2032     * @return 0 if s is null or empty, else the number of code points
     2033     * @since 19437
     2034     */
     2035    public static int getCodePointCount(String s) {
     2036        if (s == null)
     2037            return 0;
     2038        return s.codePointCount(0, s.length());
     2039    }
     2040
     2041    /**
     2042     * Check if a given string has more than the allowed number of code points.
     2043     * See #24446. The OSM server checks this number, not the value returned by String.length()
     2044     * @param s the string
     2045     * @param maxLen the maximum number of code points
     2046     * @return true if s is null or within the given limit, false else
     2047     * @since 19437
     2048     */
     2049    public static boolean checkCodePointCount(String s, int maxLen) {
     2050        return getCodePointCount(s) <= maxLen;
     2051    }
    20282052}
Note: See TracChangeset for help on using the changeset viewer.