Ticket #24446: 24446.patch

File 24446.patch, 7.8 KB (added by GerdP, 7 months ago)

Implement new methods getCodePointCount() and checkCodePointCount(), use them instead of checking String.length() against a max value

  • src/org/openstreetmap/josm/actions/upload/ApiPreconditionCheckerHook.java

     
    2222import org.openstreetmap.josm.io.OsmApiInitializationException;
    2323import org.openstreetmap.josm.io.OsmTransferCanceledException;
    2424import org.openstreetmap.josm.tools.Logging;
     25import org.openstreetmap.josm.tools.Utils;
    2526
    2627/**
    2728 * Checks certain basic conditions, that are listed in the OSM API
     
    6364            for (Map.Entry<String, String> entry: osmPrimitive.getKeys().entrySet()) {
    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
    6970                        Logging.warn(
     
    7273                                        Long.toString(osmPrimitive.getId())
    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"),
    8384                            JOptionPane.ERROR_MESSAGE
  • src/org/openstreetmap/josm/data/osm/Changeset.java

     
    1616import org.openstreetmap.josm.data.Bounds;
    1717import org.openstreetmap.josm.data.coor.LatLon;
    1818import org.openstreetmap.josm.tools.CheckParameterUtil;
     19import org.openstreetmap.josm.tools.Utils;
    1920
    2021/**
    2122 * Represents a single changeset in JOSM. For now its only used during
     
    312313    public void setKeys(Map<String, String> keys) {
    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 -> {
    318319                throw new IllegalArgumentException("Changeset tag value is too long: "+value);
     
    339340    @Override
    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    }
    347349
  • src/org/openstreetmap/josm/data/validation/tests/TagChecker.java

     
    10151015                    .build());
    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());
    10231024            withErrors.put(p, "LV");
     
    10641065                    .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());
    10721074            withErrors.put(p, "LK");
  • src/org/openstreetmap/josm/tools/TextTagParser.java

     
    154154                r = callback.warning(tr("Suspicious characters in key:"), key, "tags.paste.keydoesnotmatch");
    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            }
    161161        }
  • src/org/openstreetmap/josm/tools/Utils.java

     
    20252025            default: throw new IllegalArgumentException("Invalid length unit: " + unit);
    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 xxx
     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 xxx
     2048     */
     2049    public static boolean checkCodePointCount(String s, int maxLen) {
     2050        return getCodePointCount(s) <= maxLen;
     2051    }
    20282052}