/* * This file is part of VLCJ. * * VLCJ is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * VLCJ is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with VLCJ. If not, see <http://www.gnu.org/licenses/>. * * Copyright 2009-2016 Caprica Software Limited. */ package uk.co.caprica.vlcj.player; import java.io.File; import java.net.URI; import java.net.URISyntaxException; import java.util.regex.Pattern; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * Utility class to help detect the type of media resource locator. * <p> * This is needed since local files must be played differently to non-local MRLs * like streaming URLs or "screen://". * <p> * This is essentially an internal class. */ public final class MediaResourceLocator { /** * Log. */ private static final Logger logger = LoggerFactory.getLogger(MediaResourceLocator.class); /** * Simple pattern to detect locations. */ private static final Pattern MRL_LOCATION_PATTERN = Pattern.compile(".+://.*"); /** * Private constructor to prevent direct instantiation. */ private MediaResourceLocator() { } /** * Does the MRL represent a "location"? * * @param mrl media resource locator * @return <code>true</code> if the supplied MRL should be treated as a "location"; <code>false</code> for a file */ public static boolean isLocation(String mrl) { return MRL_LOCATION_PATTERN.matcher(mrl).matches(); } /** * Encode, if needed, a local file MRL that may contain Unicode characters as a file URL with * "percent" encoding. * <p> * This method deals only with the special case of an MRL for a local file name containing * Unicode characters. Such MRLs must be encoded as file URLs, by adding a "file://" prefix * before percent-encoding the filename. * <p> * Without this, vlc will not be able to play the file since it is using native API that can * not handle unencoded Unicode characters. * <p> * This method does not deal with any MRLs that are URLs since Unicode characters are forbidden * by specification for any URL. * <p> * What this means in practical terms is that if an MRL is specified that contains a "scheme" * like "http", or "file" then that MRL will <em>not</em> be encoded by this method, even if it * contains Unicode characters. This situation, if it arises, is considered a client * application vaildation failure. * * @param mrl MRL * @return the original MRL if no encoding is required, or a percent-encoded file URL */ public static String encodeMrl(String mrl) { logger.debug("encodeMrl(mrl={})", mrl); // Assume no change needed String result = mrl; // If the supplied MRL contains any Unicode characters... if (containsUnicode(mrl)) { logger.debug("MRL contains Unicode characters"); try { URI uri = new URI(mrl); logger.debug("uri={}", uri); String scheme = uri.getScheme(); logger.debug("scheme={}", uri.getScheme()); // If there is no URI scheme, then this is a local file... if (scheme == null) { logger.debug("MRL has no scheme, assuming a local file name that should be encoded"); // Encode the local file as ASCII, and fix the scheme prefix result = new File(mrl).toURI().toASCIIString().replaceFirst("file:/", "file:///"); } else { logger.debug("Ignoring MRL with scheme '{}'", scheme); } } catch(URISyntaxException e) { // Can't do anything, return the original string logger.debug("Can not obtain a valid URI from the MRL"); } } else { logger.debug("MRL does not contain any Unicode characters"); } logger.debug("result={}", result); return result; } /** * Does a String contain any Unicode characters? * * @param value string to test * @return <code>true</code> if the supplied String contains any Unicode characters; <code>false</code> if it does not */ private static boolean containsUnicode(String value) { boolean result = false; for (int i = 0; i < value.length(); i++) { if (value.charAt(i) >= '\u0080') { result = true; break; } } return result; } }