/*
* @(#)DataSource.java 1.31 02/08/21
*
* Copyright (c) 1996-2002 Sun Microsystems, Inc. All rights reserved.
*/
package com.sun.media.protocol.file;
import java.security.*;
import java.util.Hashtable;
import java.lang.reflect.Method;
import java.lang.reflect.Constructor;
import java.io.*;
import java.net.*;
import javax.media.*;
import javax.media.protocol.*;
import com.sun.media.*;
import com.sun.media.util.*;
import com.ms.security.PermissionID;
import com.ms.security.PolicyEngine;
public class DataSource extends PullDataSource implements SourceCloneable {
private RandomAccessFile raf;
private boolean connected = false;
private long length = -1;
private String contentType = null;
private PullSourceStream[] pssArray = new PullSourceStream[1];
private static JMFSecurity jmfSecurity = null;
private static boolean securityPrivelege=false;
private Method m[] = new Method[1];
private Class cl[] = new Class[1];
private Object args[][] = new Object[1][0];
private static Hashtable mimeTable;
// private String listOfAllowedMediaFileExtensions =
// "au wav aif aiff mid midi rmf gsm mpa mp2 mp3 g728 g729 g729a mov avi mpg mpv viv mvr swf spl ra ram";
static {
try {
jmfSecurity = JMFSecurityManager.getJMFSecurity();
securityPrivelege = true;
mimeTable = MimeManager.getDefaultMimeTable();
} catch (SecurityException e) {
}
}
public String getContentType() {
if (!connected)
return null;
return contentType;
}
public void connect() throws IOException {
if (connected)
return;
MediaLocator locator = getLocator();
if (locator == null) {
System.err.println("medialocator is null");
throw(new IOException(this + ": connect() failed"));
}
//////////////////////////////////////////////////////////////////////
// Getting the URL only to get the content type.
// Is there a better way?
URL url;
try {
url = locator.getURL();
} catch (MalformedURLException e) {
System.err.println(getLocator() +
": Don't know how to deal with non-URL locator yet!");
throw(new IOException(this + ": connect() failed"));
}
String fileName = getFileName(locator);
// For applets, check to see if the media file has a file extension
// If not, throw an IOException with the following message:
// "For security reasons, from an applet, cannot read a media file with no extension"
// If there is a file extension, make sure it is registered in the
// mimetable.
// If not throw an IOException.
if (jmfSecurity != null) {
int i = fileName.lastIndexOf(".");
if (i != -1) {
String ext = fileName.substring(i+1).toLowerCase();
if (!mimeTable.containsKey(ext)) {
// Treat aif as a special case due to bug in IE VM
if (!ext.equalsIgnoreCase("aif"))
throw new IOException("Permission Denied: From an applet cannot read media file with extension " + ext);
}
} else {
throw new IOException("For security reasons, from an applet, cannot read a media file with no extension");
}
}
try {
if ( /*securityPrivelege && */ (jmfSecurity != null) ) {
try {
if (jmfSecurity.getName().startsWith("jmf-security")) {
jmfSecurity.requestPermission(m, cl, args, JMFSecurity.READ_FILE);
m[0].invoke(cl[0], args[0]);
} else if (jmfSecurity.getName().startsWith("internet")) {
PolicyEngine.checkPermission(PermissionID.FILEIO);
PolicyEngine.assertPermission(PermissionID.FILEIO);
}
} catch (Throwable e) {
if (JMFSecurityManager.DEBUG) {
System.err.println("Unable to get read file" +
" privilege " + e);
}
jmfSecurity.permissionFailureNotification(JMFSecurity.READ_FILE);
throw new IOException("No permissions to read file");
}
}
if ( (jmfSecurity != null) && (jmfSecurity.getName().startsWith("jdk12"))) {
try {
Constructor cons = jdk12RandomAccessFileAction.cons;
raf = (RandomAccessFile) jdk12.doPrivM.invoke(
jdk12.ac,
new Object[] {
cons.newInstance(
new Object[] {
fileName, "r"
})
});
} catch (Throwable e) {
throw new IOException(JMFI18N.getResource("error.filenotfound"));
}
} else {
raf = new RandomAccessFile(fileName, "r");
}
length = raf.length();
if (length < 0)
length = SourceStream.LENGTH_UNKNOWN;
PullSourceStream pss = new RAFPullSourceStream();
pssArray[0] = pss;
// TODO: jdk1.2 check if you need permission to call getContentType
URLConnection urlC = url.openConnection();
try {
contentType = urlC.getContentType();
} catch (Throwable t) {
contentType = null;
}
contentType = ContentType.getCorrectedContentType(contentType,
locator.getRemainder());
/*
* shivak : if we get a "unknown" type or if it is "mpeg" (for MPEG1)
* we parse the stream for MPEG 1/2 types and return the content type
*/
/*
disabled for JMF 2.1.
if ( contentType.equals("content/unknown") ||
contentType.equals("video/mpeg") ) {
contentType = MediaStreamParser.parseStream(raf,contentType) ;
}
*/
contentType = ContentDescriptor.mimeTypeToPackageName(contentType);
// How do I close the URLConnection??
//////////////////////////////////////////////////////////////////////
connected = true;
} catch (Throwable e) {
throw new IOException(JMFI18N.getResource("error.filenotfound"));
}
}
public void disconnect() {
try {
if (raf != null) {
raf.close();
}
} catch (IOException e) {
}
if ( pssArray != null ) {
pssArray[0] = null;
}
connected = false;
}
public void start() throws IOException {
}
public void stop() throws IOException {
}
public void setLocator (MediaLocator ml) {
// If it's file protocol, we'll try to strip out special characters
// in the URL syntax:
// %xx = the ASCII represented by the hexadecimal number "xx".
if (ml != null && ml.getProtocol() != null && ml.getProtocol().equals("file")) {
int idx;
MediaLocator saved = ml;
String file = ml.getRemainder();
boolean changed = false;
if (file == null) {
super.setLocator(ml);
return;
}
try {
idx = 0;
while ((idx = file.indexOf("%", idx)) >= 0) {
if (file.length() > idx + 2) {
byte [] bytes = new byte[1];
try {
bytes[0] = (byte)Integer.valueOf(
file.substring(idx + 1, idx + 3), 16).intValue();
file = file.substring(0, idx) + new String(bytes) +
file.substring(idx + 3);
changed = true;
} catch (NumberFormatException ne) {
}
}
idx++;
}
if (changed)
ml = new MediaLocator(ml.getProtocol() + ":" + file);
} catch (Exception e) {
ml = saved;
}
}
super.setLocator(ml);
}
public PullSourceStream[] getStreams() {
return pssArray;
}
public Time getDuration() {
return Duration.DURATION_UNKNOWN;
}
public Object[] getControls() {
return new Object[0];
}
public Object getControl(String controlType) {
return null;
}
public javax.media.protocol.DataSource createClone() {
DataSource ds = new com.sun.media.protocol.file.DataSource();
ds.setLocator(getLocator());
if (connected) {
try {
ds.connect();
} catch (IOException e) {
return null;
}
}
return ds;
}
class RAFPullSourceStream implements PullSourceStream, Seekable {
public long seek(long where) {
try {
raf.seek(where);
return tell();
} catch (IOException e) {
System.out.println("seek: " + e);
return -1;
}
}
public long tell() {
try {
return raf.getFilePointer();
} catch (IOException e) {
System.out.println("tell: " + e);
return -1;
}
}
public boolean isRandomAccess() {
return true;
}
public boolean willReadBlock() {
return false;
}
public int read(byte[] buffer, int offset, int length)
throws IOException {
return raf.read(buffer, offset, length);
}
// TODO
public ContentDescriptor getContentDescriptor() {
// System.out.println("in getContentDescriptor"); // TODO
return null;
}
public long getContentLength() {
return length;
}
public boolean endOfStream() {
return false; // TODO
}
public Object[] getControls() {
return new Object[0];
}
public Object getControl(String controlType) {
return null;
}
}
public static String getFileName(MediaLocator locator) {
try {
URL url = locator.getURL();
String fileName = locator.getRemainder();
// Parse filename to de-normalize it.
String saved = fileName;
try {
// Change %xy to a character
int idx = 0;
while ((idx = fileName.indexOf("%", idx)) >= 0) {
if (fileName.length() > idx + 2) {
byte [] bytes = new byte[1];
try {
bytes[0] = (byte)Integer.valueOf(
fileName.substring(idx + 1, idx + 3), 16).intValue();
fileName = fileName.substring(0, idx) +
new String(bytes) +
fileName.substring(idx + 3);
} catch (NumberFormatException ne) {
}
}
idx++;
}
// Change | to :
idx = 0;
while ((idx = fileName.indexOf("|")) >= 0) {
if (idx > 0) {
fileName = fileName.substring(0, idx) + ":" +
fileName.substring(idx + 1);
} else {
fileName = fileName.substring(1);
}
}
while (fileName.startsWith("///")) {
fileName = fileName.substring(2);
}
if (System.getProperty("os.name").startsWith("Windows")) {
while (fileName.charAt(0) == '/' &&
fileName.charAt(2) == ':') {
fileName = fileName.substring(1);
}
}
} catch (Exception e) {
fileName = saved;
}
return fileName;
} catch (Throwable t) {
return null;
}
}
}
|