1 /* 2 * Copyright (c) 2011-2022, jcabi.com 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 1) Redistributions of source code must retain the above 8 * copyright notice, this list of conditions and the following 9 * disclaimer. 2) Redistributions in binary form must reproduce the above 10 * copyright notice, this list of conditions and the following 11 * disclaimer in the documentation and/or other materials provided 12 * with the distribution. 3) Neither the name of the jcabi.com nor 13 * the names of its contributors may be used to endorse or promote 14 * products derived from this software without specific prior written 15 * permission. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT 19 * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 20 * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 21 * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 22 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 23 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 24 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 26 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 28 * OF THE POSSIBILITY OF SUCH DAMAGE. 29 */ 30 package com.jcabi.w3c; 31 32 import com.jcabi.manifests.Manifests; 33 import java.io.ByteArrayOutputStream; 34 import java.io.IOException; 35 import java.net.URI; 36 import java.nio.charset.Charset; 37 import java.nio.charset.StandardCharsets; 38 import java.util.List; 39 import lombok.ToString; 40 import org.apache.http.entity.ContentType; 41 import org.apache.http.entity.mime.MultipartEntityBuilder; 42 43 /** 44 * Abstract implementation of (X)HTML validator. 45 * 46 * @since 0.1 47 */ 48 @ToString 49 @SuppressWarnings("PMD.AbstractClassWithoutAbstractMethod") 50 abstract class AbstractBaseValidator { 51 52 /** 53 * User agent. 54 */ 55 protected static final String USER_AGENT = String.format( 56 "ReXSL-W3C %s %s %s", 57 Manifests.read("JCabi-Version"), 58 Manifests.read("JCabi-Build"), 59 Manifests.read("JCabi-Date") 60 ); 61 62 /** 63 * Boundary for HTTP POST form data (just some random data). 64 */ 65 protected static final String BOUNDARY = "vV9olNqRj00PC4OIlM7"; 66 67 /** 68 * Convert HTML to HTTP FORM entity. 69 * @param name Name of HTTP form field 70 * @param content The content of it 71 * @param type Media type of it 72 * @return The HTTP post body 73 * @throws IOException if fails 74 */ 75 protected static String entity(final String name, final String content, 76 final String type) throws IOException { 77 final ByteArrayOutputStream baos = new ByteArrayOutputStream(); 78 MultipartEntityBuilder.create() 79 .setStrictMode() 80 .setCharset(StandardCharsets.UTF_8) 81 .setBoundary(AbstractBaseValidator.BOUNDARY) 82 .addBinaryBody( 83 name, 84 content.getBytes(StandardCharsets.UTF_8), 85 ContentType.create(type, StandardCharsets.UTF_8), 86 "file" 87 ) 88 .addTextBody("output", "soap12") 89 .build() 90 .writeTo(baos); 91 return baos.toString(StandardCharsets.UTF_8.toString()); 92 } 93 94 /** 95 * Build a success response. 96 * @param type Media type of resource just processed 97 * @return The validation response just built 98 */ 99 protected static ValidationResponse success(final String type) { 100 final DefaultValidationResponse resp = new DefaultValidationResponse( 101 true, 102 URI.create("http://localhost/success"), 103 type, 104 Charset.defaultCharset() 105 ); 106 return resp; 107 } 108 109 /** 110 * Get text from list of strings, returned by 111 * {@link XML#xpath(String)}. 112 * 113 * <p>This method is required to simplify manipulations with XPath returned 114 * list of strings (returned by {@link XML#xpath(String)} above). 115 * The list of strings normally (!) contains one element or no elements. If 116 * there are no elements it means that the XPath is not found in the 117 * document. In this case we should return an empty string. If any elements 118 * are found - we're interested only in the first one. All others are 119 * ignored, because simply should not exist (if our XPath query is correct). 120 * 121 * @param lines The lines to work with 122 * @return The value 123 * @see #intOf(List) 124 */ 125 protected static String textOf(final List<String> lines) { 126 final String text; 127 if (lines.isEmpty()) { 128 text = ""; 129 } else { 130 text = lines.get(0); 131 } 132 return text; 133 } 134 135 /** 136 * Get text from list of strings. 137 * 138 * <p>See explanation of {@link #textOf(List)}. 139 * 140 * @param lines The lines to work with 141 * @return The value 142 * @see #textOf(List) 143 */ 144 protected static int intOf(final List<String> lines) { 145 final int value; 146 if (lines.isEmpty()) { 147 value = 0; 148 } else { 149 value = Integer.parseInt(lines.get(0)); 150 } 151 return value; 152 } 153 154 /** 155 * Convert text to charset. 156 * @param text Text representation of charset 157 * @return The charset 158 */ 159 protected static Charset charset(final String text) { 160 final Charset charset; 161 if (text.isEmpty()) { 162 charset = Charset.defaultCharset(); 163 } else { 164 charset = Charset.forName(text); 165 } 166 return charset; 167 } 168 169 }