1 /*******************************************************************************
2 * Copyright (c) 2000, 2003 IBM Corporation and others.
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Common Public License v1.0
5 * which accompanies this distribution, and is available at
6 * http://www.eclipse.org/legal/cpl-v10.html
9 * IBM Corporation - initial API and implementation
10 *******************************************************************************/
11 package net.sourceforge.phpeclipse.obfuscator;
13 import java.io.BufferedInputStream;
14 import java.io.BufferedWriter;
16 import java.io.FileNotFoundException;
17 import java.io.FileOutputStream;
18 import java.io.FileWriter;
19 import java.io.IOException;
20 import java.io.InputStream;
21 import java.util.ArrayList;
22 import java.util.HashMap;
24 import net.sourceforge.phpdt.core.compiler.ITerminalSymbols;
25 import net.sourceforge.phpdt.core.compiler.InvalidInputException;
26 import net.sourceforge.phpdt.internal.compiler.parser.Scanner;
27 import net.sourceforge.phpdt.internal.compiler.parser.SyntaxError;
28 import net.sourceforge.phpdt.internal.compiler.util.Util;
29 import net.sourceforge.phpdt.internal.ui.util.PHPFileUtil;
30 //import net.sourceforge.phpeclipse.PHPeclipsePlugin;
31 //import net.sourceforge.phpeclipse.ui.WebUI;
33 import org.eclipse.core.resources.IContainer;
34 import org.eclipse.core.resources.IFile;
35 import org.eclipse.core.resources.IResource;
36 import org.eclipse.core.runtime.CoreException;
37 import org.eclipse.core.runtime.IPath;
38 //import org.eclipse.jface.preference.IPreferenceStore;
41 * Helper class for exporting resources to the file system.
43 public class ObfuscatorPass2Exporter implements ITerminalSymbols {
44 private Scanner fScanner;
50 protected HashMap fIdentifierMap;
52 public ObfuscatorPass2Exporter(Scanner scanner, HashMap identifierMap) {
54 fIdentifierMap = identifierMap;
59 * gets the next token from input
61 private void getNextToken() {
64 fToken = fScanner.getNextToken();
66 int currentEndPosition = fScanner.getCurrentTokenEndPosition();
67 int currentStartPosition = fScanner
68 .getCurrentTokenStartPosition();
70 System.out.print(currentStartPosition + ","
71 + currentEndPosition + ": ");
72 System.out.println(fScanner.toStringAction(fToken));
75 } catch (InvalidInputException e) {
78 fToken = TokenNameERROR;
81 private boolean obfuscate(StringBuffer buf) {
86 int startPosition = 0;
89 // IPreferenceStore store = WebUI.getDefault()
90 // .getPreferenceStore();
92 while (fToken != TokenNameEOF && fToken != TokenNameERROR) {
93 if (fToken == TokenNameVariable) {
94 identifier = new String(fScanner
95 .getCurrentIdentifierSource());
96 lastPosition = fScanner.startPosition;
97 int len = lastPosition - startPosition;
98 buf.append(fScanner.source, startPosition, len);
99 value = (PHPIdentifier) fIdentifierMap.get(identifier);
101 String obfuscatedIdentifier = value.getIdentifier();
102 if (obfuscatedIdentifier == null) {
103 buf.append("$v" + Integer.toString(fCounter));
104 value.setIdentifier("$v"
105 + Integer.toString(fCounter++));
107 buf.append(obfuscatedIdentifier);
109 // System.out.println(hexString.toString());
111 buf.append(identifier);
113 startPosition = fScanner.currentPosition;
115 } else if (fToken == TokenNameIdentifier) {
116 identifier = new String(fScanner
117 .getCurrentIdentifierSource());
118 lastPosition = fScanner.startPosition;
119 int len = lastPosition - startPosition;
120 buf.append(fScanner.source, startPosition, len);
121 value = (PHPIdentifier) fIdentifierMap.get(identifier);
123 String obfuscatedIdentifier = value.getIdentifier();
124 if (obfuscatedIdentifier == null) {
125 buf.append("_" + Integer.toString(fCounter));
126 value.setIdentifier("_"
127 + Integer.toString(fCounter++));
129 buf.append(obfuscatedIdentifier);
131 // System.out.println(hexString.toString());
133 buf.append(identifier);
135 startPosition = fScanner.currentPosition;
138 } else if (fToken == TokenNameCOMMENT_LINE
139 || fToken == TokenNameCOMMENT_BLOCK
140 || fToken == TokenNameCOMMENT_PHPDOC) {
141 lastPosition = fScanner.startPosition;
142 buf.append(fScanner.source, startPosition, lastPosition
144 startPosition = fScanner.currentPosition;
146 } else if (fToken == TokenNameStringDoubleQuote) {
147 char currentCharacter;
148 int i = fScanner.startPosition;
149 ArrayList varList = new ArrayList();
151 lastPosition = fScanner.startPosition;
152 int len = lastPosition - startPosition;
153 buf.append(fScanner.source, startPosition, len);
155 while (i < fScanner.currentPosition) {
156 currentCharacter = fScanner.source[i++];
157 if (currentCharacter == '$'
158 && fScanner.source[i - 2] != '\\') {
159 StringBuffer varName = new StringBuffer();
161 while (i < fScanner.currentPosition) {
162 currentCharacter = fScanner.source[i++];
164 .isPHPIdentifierPart(currentCharacter)) {
167 varName.append(currentCharacter);
169 varList.add(varName.toString());
172 StringBuffer stringLiteral = new StringBuffer();
173 stringLiteral.append(fScanner.source,
174 fScanner.startPosition, fScanner.currentPosition
175 - fScanner.startPosition);
180 for (int j = 0; j < varList.size(); j++) {
181 stringIdent = (String) varList.get(j);
182 len = stringIdent.length();
183 value = (PHPIdentifier) fIdentifierMap.get(stringIdent);
185 String obfuscatedIdentifier = value.getIdentifier();
186 if (obfuscatedIdentifier == null) {
187 replacement = "$v" + Integer.toString(fCounter);
188 value.setIdentifier("$v"
189 + Integer.toString(fCounter++));
191 replacement = obfuscatedIdentifier;
193 // System.out.println(hexString.toString());
195 replacement = stringIdent;
197 index = stringLiteral.indexOf(stringIdent);
200 && stringLiteral.charAt(index - 1) != '\\') {
201 stringLiteral.replace(index, index
202 + stringIdent.length(), replacement);
203 } else if (index == 0) {
204 stringLiteral.replace(index, index
205 + stringIdent.length(), replacement);
209 buf.append(stringLiteral);
210 startPosition = fScanner.currentPosition;
213 if (fToken == TokenNameMINUS_GREATER) { // i.e. $this->var_name
215 if (fToken == TokenNameIdentifier) {
216 // assuming this is a dereferenced variable
217 identifier = new String(fScanner
218 .getCurrentIdentifierSource());
219 lastPosition = fScanner.startPosition;
220 int len = lastPosition - startPosition;
221 buf.append(fScanner.source, startPosition, len);
222 value = (PHPIdentifier) fIdentifierMap.get("$"
224 if (value != null && value.isVariable()) {
225 String obfuscatedIdentifier = value.getIdentifier();
226 if (obfuscatedIdentifier == null) {
227 // note: don't place a $ before the identifier
228 buf.append("v" + Integer.toString(fCounter));
229 value.setIdentifier("$v"
230 + Integer.toString(fCounter++));
232 if (obfuscatedIdentifier.charAt(0) == '$') {
233 buf.append(obfuscatedIdentifier
236 buf.append(obfuscatedIdentifier);
240 buf.append(identifier);
242 startPosition = fScanner.currentPosition;
250 if (startPosition < fScanner.source.length) {
251 buf.append(fScanner.source, startPosition,
252 fScanner.source.length - startPosition);
255 } catch (SyntaxError sytaxErr) {
263 * Creates the specified file system directory at
264 * <code>destinationPath</code>. This creates a new file system
267 public void createFolder(IPath destinationPath) {
268 new File(destinationPath.toOSString()).mkdir();
272 * Writes the passed resource to the specified location recursively
274 public void write(IResource resource, IPath destinationPath)
275 throws CoreException, IOException {
276 if (resource.getType() == IResource.FILE)
277 writeFile((IFile) resource, destinationPath);
279 writeChildren((IContainer) resource, destinationPath);
283 * Exports the passed container's children
285 protected void writeChildren(IContainer folder, IPath destinationPath)
286 throws CoreException, IOException {
287 if (folder.isAccessible()) {
288 IResource[] children = folder.members();
289 for (int i = 0; i < children.length; i++) {
290 IResource child = children[i];
291 writeResource(child, destinationPath.append(child.getName()));
297 * Writes the passed file resource to the specified destination on the local
300 protected void writeFile(IFile file, IPath destinationPath)
301 throws IOException, CoreException {
302 if (PHPFileUtil.isPHPFile(file)) {
303 InputStream stream = null;
304 char[] charArray = null;
306 stream = new BufferedInputStream(file.getContents());
307 charArray = Util.getInputStreamAsCharArray(stream, -1, null);
308 } catch (IOException e) {
312 if (stream != null) {
315 } catch (IOException e) {
319 if (charArray == null) {
320 // TODO show error message
324 fScanner.setSource(charArray);
325 fScanner.setPHPMode(false);
326 fToken = TokenNameEOF;
329 StringBuffer buf = new StringBuffer();
330 if (!obfuscate(buf)) {
331 copyFile(file, destinationPath);
333 // charArray = buf.toString().toCharArray();
334 // File targetFile = new File(destinationPath.toOSString());
335 BufferedWriter bw = new BufferedWriter(new FileWriter(
336 destinationPath.toOSString()));
337 bw.write(buf.toString());
342 copyFile(file, destinationPath);
346 private void copyFile(IFile file, IPath destinationPath)
347 throws FileNotFoundException, CoreException, IOException {
348 FileOutputStream output = null;
349 InputStream contentStream = null;
352 output = new FileOutputStream(destinationPath.toOSString());
353 contentStream = file.getContents(false);
354 int chunkSize = contentStream.available();
355 byte[] readBuffer = new byte[chunkSize];
356 int n = contentStream.read(readBuffer);
359 output.write(readBuffer);
360 n = contentStream.read(readBuffer);
365 if (contentStream != null)
366 contentStream.close();
371 * Writes the passed resource to the specified location recursively
373 protected void writeResource(IResource resource, IPath destinationPath)
374 throws CoreException, IOException {
375 if (resource.getType() == IResource.FILE)
376 writeFile((IFile) resource, destinationPath);
378 createFolder(destinationPath);
379 writeChildren((IContainer) resource, destinationPath);