Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Fix bug in decoding data URIs; Add tests in javase/, zxingorg/
  • Loading branch information
srowen committed Jul 24, 2018
1 parent e1b127c commit d907537
Show file tree
Hide file tree
Showing 12 changed files with 290 additions and 9 deletions.
Expand Up @@ -21,7 +21,6 @@
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.net.URI;
import java.net.URLDecoder;

/**
* Encapsulates reading URIs as images.
Expand Down Expand Up @@ -60,8 +59,7 @@ public static BufferedImage readDataURIImage(URI uri) throws IOException {
if (base64Start < 0) {
throw new IOException("Unsupported data URI encoding");
}
String base64DataEncoded = uriString.substring(base64Start + BASE64TOKEN.length());
String base64Data = URLDecoder.decode(base64DataEncoded, "UTF-8");
String base64Data = uriString.substring(base64Start + BASE64TOKEN.length());
byte[] imageBytes = Base64Decoder.getInstance().decode(base64Data);
return ImageIO.read(new ByteArrayInputStream(imageBytes));
}
Expand Down
@@ -0,0 +1,50 @@
/*
* Copyright 2018 ZXing authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.google.zxing.client.j2se;

import com.beust.jcommander.JCommander;
import org.junit.Assert;
import org.junit.Test;

import java.net.URI;
import java.util.Collections;
import java.util.LinkedList;
import java.util.Queue;

/**
* Tests {@link DecodeWorker}.
*/
public final class DecodeWorkerTestCase extends Assert {

private static final String IMAGE_DATA_URI =
"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACEAAAAhAQAAAAB/n//CAAAAkklEQVR42mP4DwQNDJjkB4" +
"E77A0M369N/d7A8CV6rjiQjPMFkWG1QPL7RVGg%2BAfREKCa/5/vA9V/nFSQ3sDwb7/KdiDJqX4dSH4pXN/A8DfyDVD2" +
"988HQPUfPVaqA0XKz%2BgD9bIk1AP1fgwvB7KlS9VBdqXbA82PT9AH2fiaH2SXGdDM71fDgeIfhIvKsbkTTAIAKYVr0N" +
"z5IloAAAAASUVORK5CYII=";


@Test
public void testWorker() throws Exception {
DecoderConfig config = new DecoderConfig();
JCommander jCommander = new JCommander(config);
jCommander.parse("--pure_barcode", IMAGE_DATA_URI);
Queue<URI> inputs = new LinkedList<>(Collections.singletonList(new URI(IMAGE_DATA_URI)));
DecodeWorker worker = new DecodeWorker(config, inputs);
assertEquals(1, worker.call().intValue());
}

}
Expand Up @@ -28,7 +28,7 @@
public final class ImageReaderTestCase extends Assert {

@Test
public void testFoo() throws Exception {
public void testDataURI() throws Exception {
String uri =
"data:image/gif;base64,R0lGODlhEAAQAMQAAORHHOVSKudfOulrSOp3WOyDZu6QdvCchPGolfO0o/XBs/fNwfjZ0frl3/zy7////w" +
"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAkAABAALAAAAAAQABAAAAVVICSOZGlCQAosJ6" +
Expand Down
Expand Up @@ -68,10 +68,9 @@ public void onModuleLoad() {

setupLeftPanel();
topPanel.getElement().setId("leftpanel");
Widget leftPanel = topPanel;

HorizontalPanel mainPanel = new HorizontalPanel();
mainPanel.add(leftPanel);
mainPanel.add(topPanel);

SimplePanel div2 = new SimplePanel();
div2.add(result);
Expand Down
6 changes: 5 additions & 1 deletion zxingorg/src/main/java/com/google/zxing/web/DoSFilter.java
Expand Up @@ -39,13 +39,17 @@
@WebFilter({"/w/decode", "/w/chart"})
public final class DoSFilter implements Filter {

static final int MAX_ACCESS_PER_TIME = 500;
static final long ACCESS_TIME_MS = TimeUnit.MILLISECONDS.convert(5, TimeUnit.MINUTES);
static final int MAX_ENTRIES = 10_000;

private Timer timer;
private DoSTracker sourceAddrTracker;

@Override
public void init(FilterConfig filterConfig) {
timer = new Timer("DoSFilter");
sourceAddrTracker = new DoSTracker(timer, 500, TimeUnit.MILLISECONDS.convert(5, TimeUnit.MINUTES), 10_000);
sourceAddrTracker = new DoSTracker(timer, MAX_ACCESS_PER_TIME, ACCESS_TIME_MS, MAX_ENTRIES);
timer.scheduleAtFixedRate(
new TimerTask() {
@Override
Expand Down
Expand Up @@ -38,7 +38,7 @@ final class DoSTracker {
DoSTracker(Timer timer, final int maxAccessesPerTime, long accessTimeMS, int maxEntries) {
this.maxAccessesPerTime = maxAccessesPerTime;
this.numRecentAccesses = new LRUMap<>(maxEntries);
timer.scheduleAtFixedRate(new TimerTask() {
timer.schedule(new TimerTask() {
@Override
public void run() {
synchronized (numRecentAccesses) {
Expand Down
@@ -0,0 +1,42 @@
/*
* Copyright 2018 ZXing authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.google.zxing.web;

import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
import org.junit.Assert;
import org.junit.Test;

import java.nio.charset.StandardCharsets;

/**
* Tests {@link ChartServletRequestParameters}.
*/
public final class ChartServletRequestParametersTestCase extends Assert {

@Test
public void testParams() {
ChartServletRequestParameters params =
new ChartServletRequestParameters(10, 20, StandardCharsets.UTF_8, ErrorCorrectionLevel.H, 5, "foo");
assertEquals(10, params.getWidth());
assertEquals(20, params.getHeight());
assertEquals(StandardCharsets.UTF_8, params.getOutputEncoding());
assertEquals(ErrorCorrectionLevel.H, params.getEcLevel());
assertEquals(5, params.getMargin());
assertEquals("foo", params.getText());
}

}
48 changes: 48 additions & 0 deletions zxingorg/src/test/java/com/google/zxing/web/DoSFilterTestCase.java
@@ -0,0 +1,48 @@
/*
* Copyright 2018 ZXing authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.google.zxing.web;

import org.junit.Assert;
import org.junit.Test;
import org.springframework.mock.web.MockFilterChain;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.mock.web.MockHttpServletResponse;

import javax.servlet.http.HttpServletResponse;

/**
* Tests {@link DoSFilter}.
*/
public final class DoSFilterTestCase extends Assert {

@Test
public void testRedirect() throws Exception {
MockHttpServletRequest request = new MockHttpServletRequest();
request.setRequestURI("/");
request.setRemoteAddr("1.2.3.4");
MockHttpServletResponse response = new MockHttpServletResponse();
DoSFilter filter = new DoSFilter();
filter.init(null);
for (int i = 0; i < DoSFilter.MAX_ACCESS_PER_TIME; i++) {
filter.doFilter(request, response, new MockFilterChain());
assertEquals(HttpServletResponse.SC_OK, response.getStatus());
}
filter.doFilter(request, response, new MockFilterChain());
assertEquals(HttpServletResponse.SC_FORBIDDEN, response.getStatus());
}

}
@@ -0,0 +1,58 @@
/*
* Copyright 2018 ZXing authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.google.zxing.web;

import org.junit.Assert;
import org.junit.Test;

import java.util.Timer;

/**
* Tests {@link DoSTracker}.
*/
public final class DoSTrackerTestCase extends Assert {

@Test
public void testDoS() throws Exception {
Timer timer = new Timer();
long timerTimeMS = 200;
DoSTracker tracker = new DoSTracker(timer, 2, timerTimeMS, 3);
assertFalse(tracker.isBanned("A"));
assertFalse(tracker.isBanned("A"));
assertTrue(tracker.isBanned("A"));

assertFalse(tracker.isBanned("B"));
assertFalse(tracker.isBanned("C"));
assertFalse(tracker.isBanned("D"));
assertFalse(tracker.isBanned("A"));

assertFalse(tracker.isBanned("A"));
assertTrue(tracker.isBanned("A"));
Thread.sleep(timerTimeMS * 3);
assertFalse(tracker.isBanned("A"));

assertFalse(tracker.isBanned("A"));
assertTrue(tracker.isBanned("A"));
assertTrue(tracker.isBanned("A"));
assertTrue(tracker.isBanned("A"));
assertTrue(tracker.isBanned("A"));
assertTrue(tracker.isBanned("A"));
Thread.sleep(timerTimeMS * 2);
assertTrue(tracker.isBanned("A"));
}

}
Expand Up @@ -42,7 +42,6 @@ public void setUp() {
request.setRequestURI("/path");
response = new MockHttpServletResponse();
chain = new MockFilterChain();

}

@Test
Expand Down
39 changes: 39 additions & 0 deletions zxingorg/src/test/java/com/google/zxing/web/LRUMapTestCase.java
@@ -0,0 +1,39 @@
/*
* Copyright 2018 ZXing authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.google.zxing.web;

import org.junit.Assert;
import org.junit.Test;

/**
* Tests {@link LRUMap}.
*/
public final class LRUMapTestCase extends Assert {

@Test
public void testLRU() {
LRUMap<String,String> map = new LRUMap<>(2);
map.put("foo", "bar");
map.put("bar", "baz");
assertEquals("bar", map.get("foo"));
assertEquals("baz", map.get("bar"));
map.put("baz", "bing");
assertEquals("bing", map.get("baz"));
assertNull(map.get("foo"));
}

}
@@ -0,0 +1,44 @@
/*
* Copyright 2018 ZXing authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.google.zxing.web;

import com.google.common.net.HttpHeaders;
import org.junit.Assert;
import org.junit.Test;
import org.springframework.mock.web.MockFilterChain;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.mock.web.MockHttpServletResponse;

import javax.servlet.http.HttpServletResponse;

/**
* Tests {@link WelcomeFilter}.
*/
public final class WelcomeFilterTestCase extends Assert {

@Test
public void testRedirect() {
MockHttpServletRequest request = new MockHttpServletRequest();
request.setRequestURI("/");
MockHttpServletResponse response = new MockHttpServletResponse();
MockFilterChain chain = new MockFilterChain();
new WelcomeFilter().doFilter(request, response, chain);
assertEquals(HttpServletResponse.SC_MOVED_PERMANENTLY, response.getStatus());
assertEquals("/w/decode.jspx", response.getHeader(HttpHeaders.LOCATION));
}

}

0 comments on commit d907537

Please sign in to comment.