1/*
2 * Copyright (c) 1994, 1998, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.  Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26package sun.net.www;
27import java.net.URL;
28import java.io.*;
29import java.util.StringTokenizer;
30import sun.security.action.GetPropertyAction;
31
32class MimeLauncher extends Thread {
33    java.net.URLConnection uc;
34    MimeEntry m;
35    String genericTempFileTemplate;
36    InputStream is;
37    String execPath;
38
39    MimeLauncher (MimeEntry M, java.net.URLConnection uc,
40                  InputStream is, String tempFileTemplate, String threadName) throws ApplicationLaunchException {
41        super(null, null, threadName, 0, false);
42        m = M;
43        this.uc = uc;
44        this.is = is;
45        genericTempFileTemplate = tempFileTemplate;
46
47        /* get the application to launch */
48        String launchString = m.getLaunchString();
49
50        /* get a valid path to launch application - sets
51           the execPath instance variable with the correct path.
52         */
53        if (!findExecutablePath(launchString)) {
54            /* strip off parameters i.e %s */
55            String appName;
56            int index = launchString.indexOf(' ');
57            if (index != -1) {
58                appName = launchString.substring(0, index);
59            }
60            else {
61                appName = launchString;
62            }
63            throw new ApplicationLaunchException(appName);
64        }
65    }
66
67    protected String getTempFileName(URL url, String template) {
68        String tempFilename = template;
69
70        // Replace all but last occurrance of "%s" with timestamp to insure
71        // uniqueness.  There's a subtle behavior here: if there is anything
72        // _after_ the last "%s" we need to append it so that unusual launch
73        // strings that have the datafile in the middle can still be used.
74        int wildcard = tempFilename.lastIndexOf("%s");
75        String prefix = tempFilename.substring(0, wildcard);
76
77        String suffix = "";
78        if (wildcard < tempFilename.length() - 2) {
79            suffix = tempFilename.substring(wildcard + 2);
80        }
81
82        long timestamp = System.currentTimeMillis()/1000;
83        int argIndex = 0;
84        while ((argIndex = prefix.indexOf("%s")) >= 0) {
85            prefix = prefix.substring(0, argIndex)
86                + timestamp
87                + prefix.substring(argIndex + 2);
88        }
89
90        // Add a file name and file-extension if known
91        String filename = url.getFile();
92
93        String extension = "";
94        int dot = filename.lastIndexOf('.');
95
96        // BugId 4084826:  Temp MIME file names not always valid.
97        // Fix:  don't allow slashes in the file name or extension.
98        if (dot >= 0 && dot > filename.lastIndexOf('/')) {
99            extension = filename.substring(dot);
100        }
101
102        filename = "HJ" + url.hashCode();
103
104        tempFilename = prefix + filename + timestamp + extension + suffix;
105
106        return tempFilename;
107    }
108
109    public void run() {
110        try {
111            String ofn = m.getTempFileTemplate();
112            if (ofn == null) {
113                ofn = genericTempFileTemplate;
114            }
115
116            ofn = getTempFileName(uc.getURL(), ofn);
117            try {
118                OutputStream os = new FileOutputStream(ofn);
119                byte buf[] = new byte[2048];
120                int i = 0;
121                try {
122                    while ((i = is.read(buf)) >= 0) {
123                        os.write(buf, 0, i);
124                    }
125                } catch(IOException e) {
126                  //System.err.println("Exception in write loop " + i);
127                  //e.printStackTrace();
128                } finally {
129                    os.close();
130                    is.close();
131                }
132            } catch(IOException e) {
133              //System.err.println("Exception in input or output stream");
134              //e.printStackTrace();
135            }
136
137            int inx = 0;
138            String c = execPath;
139            while ((inx = c.indexOf("%t")) >= 0) {
140                c = c.substring(0, inx) + uc.getContentType()
141                    + c.substring(inx + 2);
142            }
143
144            boolean substituted = false;
145            while ((inx = c.indexOf("%s")) >= 0) {
146                c = c.substring(0, inx) + ofn + c.substring(inx + 2);
147                substituted = true;
148            }
149            if (!substituted)
150                c = c + " <" + ofn;
151
152            // System.out.println("Execing " +c);
153
154            Runtime.getRuntime().exec(c);
155        } catch(IOException e) {
156        }
157    }
158
159    /* This method determines the path for the launcher application
160       and sets the execPath instance variable.  It uses the exec.path
161       property to obtain a list of paths that is in turn used to
162       location the application.  If a valid path is not found, it
163       returns false else true.  */
164    private boolean findExecutablePath(String str) {
165        if (str == null || str.length() == 0) {
166            return false;
167        }
168
169        String command;
170        int index = str.indexOf(' ');
171        if (index != -1) {
172            command = str.substring(0, index);
173        }
174        else {
175            command = str;
176        }
177
178        File f = new File(command);
179        if (f.isFile()) {
180            // Already executable as it is
181            execPath = str;
182            return true;
183        }
184
185        String execPathList;
186        execPathList = GetPropertyAction.privilegedGetProperty("exec.path");
187        if (execPathList == null) {
188            // exec.path property not set
189            return false;
190        }
191
192        StringTokenizer iter = new StringTokenizer(execPathList, "|");
193        while (iter.hasMoreElements()) {
194            String prefix = (String)iter.nextElement();
195            String fullCmd = prefix + File.separator + command;
196            f = new File(fullCmd);
197            if (f.isFile()) {
198                execPath = prefix + File.separator + str;
199                return true;
200            }
201        }
202
203        return false; // application not found in exec.path
204    }
205}
206