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;
32 import org.eclipse.core.resources.IContainer;
33 import org.eclipse.core.resources.IFile;
34 import org.eclipse.core.resources.IResource;
35 import org.eclipse.core.runtime.CoreException;
36 import org.eclipse.core.runtime.IPath;
37 import org.eclipse.jface.preference.IPreferenceStore;
40 * Helper class for exporting resources to the file system.
42 public class ObfuscatorPass2Exporter implements ITerminalSymbols {
43 private Scanner fScanner;
49 protected HashMap fIdentifierMap;
51 public ObfuscatorPass2Exporter(Scanner scanner, HashMap identifierMap) {
53 fIdentifierMap = identifierMap;
58 * gets the next token from input
60 private void getNextToken() {
63 fToken = fScanner.getNextToken();
65 int currentEndPosition = fScanner.getCurrentTokenEndPosition();
66 int currentStartPosition = fScanner
67 .getCurrentTokenStartPosition();
69 System.out.print(currentStartPosition + ","
70 + currentEndPosition + ": ");
71 System.out.println(fScanner.toStringAction(fToken));
74 } catch (InvalidInputException e) {
77 fToken = TokenNameERROR;
80 private boolean obfuscate(StringBuffer buf) {
85 int startPosition = 0;
88 IPreferenceStore store = PHPeclipsePlugin.getDefault()
89 .getPreferenceStore();
91 while (fToken != TokenNameEOF && fToken != TokenNameERROR) {
92 if (fToken == TokenNameVariable) {
93 identifier = new String(fScanner
94 .getCurrentIdentifierSource());
95 lastPosition = fScanner.startPosition;
96 int len = lastPosition - startPosition;
97 buf.append(fScanner.source, startPosition, len);
98 value = (PHPIdentifier) fIdentifierMap.get(identifier);
100 String obfuscatedIdentifier = value.getIdentifier();
101 if (obfuscatedIdentifier == null) {
102 buf.append("$v" + Integer.toString(fCounter));
103 value.setIdentifier("$v"
104 + Integer.toString(fCounter++));
106 buf.append(obfuscatedIdentifier);
108 // System.out.println(hexString.toString());
110 buf.append(identifier);
112 startPosition = fScanner.currentPosition;
114 } else if (fToken == TokenNameIdentifier) {
115 identifier = new String(fScanner
116 .getCurrentIdentifierSource());
117 lastPosition = fScanner.startPosition;
118 int len = lastPosition - startPosition;
119 buf.append(fScanner.source, startPosition, len);
120 value = (PHPIdentifier) fIdentifierMap.get(identifier);
122 String obfuscatedIdentifier = value.getIdentifier();
123 if (obfuscatedIdentifier == null) {
124 buf.append("_" + Integer.toString(fCounter));
125 value.setIdentifier("_"
126 + Integer.toString(fCounter++));
128 buf.append(obfuscatedIdentifier);
130 // System.out.println(hexString.toString());
132 buf.append(identifier);
134 startPosition = fScanner.currentPosition;
137 } else if (fToken == TokenNameCOMMENT_LINE
138 || fToken == TokenNameCOMMENT_BLOCK
139 || fToken == TokenNameCOMMENT_PHPDOC) {
140 lastPosition = fScanner.startPosition;
141 buf.append(fScanner.source, startPosition, lastPosition
143 startPosition = fScanner.currentPosition;
145 } else if (fToken == TokenNameStringDoubleQuote) {
146 char currentCharacter;
147 int i = fScanner.startPosition;
148 ArrayList varList = new ArrayList();
150 lastPosition = fScanner.startPosition;
151 int len = lastPosition - startPosition;
152 buf.append(fScanner.source, startPosition, len);
154 while (i < fScanner.currentPosition) {
155 currentCharacter = fScanner.source[i++];
156 if (currentCharacter == '$'
157 && fScanner.source[i - 2] != '\\') {
158 StringBuffer varName = new StringBuffer();
160 while (i < fScanner.currentPosition) {
161 currentCharacter = fScanner.source[i++];
163 .isPHPIdentifierPart(currentCharacter)) {
166 varName.append(currentCharacter);
168 varList.add(varName.toString());
171 StringBuffer stringLiteral = new StringBuffer();
172 stringLiteral.append(fScanner.source,
173 fScanner.startPosition, fScanner.currentPosition
174 - fScanner.startPosition);
179 for (int j = 0; j < varList.size(); j++) {
180 stringIdent = (String) varList.get(j);
181 len = stringIdent.length();
182 value = (PHPIdentifier) fIdentifierMap.get(stringIdent);
184 String obfuscatedIdentifier = value.getIdentifier();
185 if (obfuscatedIdentifier == null) {
186 replacement = "$v" + Integer.toString(fCounter);
187 value.setIdentifier("$v"
188 + Integer.toString(fCounter++));
190 replacement = obfuscatedIdentifier;
192 // System.out.println(hexString.toString());
194 replacement = stringIdent;
196 index = stringLiteral.indexOf(stringIdent);
199 && stringLiteral.charAt(index - 1) != '\\') {
200 stringLiteral.replace(index, index
201 + stringIdent.length(), replacement);
202 } else if (index == 0) {
203 stringLiteral.replace(index, index
204 + stringIdent.length(), replacement);
208 buf.append(stringLiteral);
209 startPosition = fScanner.currentPosition;
212 if (fToken == TokenNameMINUS_GREATER) { // i.e. $this->var_name
214 if (fToken == TokenNameIdentifier) {
215 // assuming this is a dereferenced variable
216 identifier = new String(fScanner
217 .getCurrentIdentifierSource());
218 lastPosition = fScanner.startPosition;
219 int len = lastPosition - startPosition;
220 buf.append(fScanner.source, startPosition, len);
221 value = (PHPIdentifier) fIdentifierMap.get("$"
223 if (value != null && value.isVariable()) {
224 String obfuscatedIdentifier = value.getIdentifier();
225 if (obfuscatedIdentifier == null) {
226 // note: don't place a $ before the identifier
227 buf.append("v" + Integer.toString(fCounter));
228 value.setIdentifier("$v"
229 + Integer.toString(fCounter++));
231 if (obfuscatedIdentifier.charAt(0) == '$') {
232 buf.append(obfuscatedIdentifier
235 buf.append(obfuscatedIdentifier);
239 buf.append(identifier);
241 startPosition = fScanner.currentPosition;
249 if (startPosition < fScanner.source.length) {
250 buf.append(fScanner.source, startPosition,
251 fScanner.source.length - startPosition);
254 } catch (SyntaxError sytaxErr) {
262 * Creates the specified file system directory at
263 * <code>destinationPath</code>. This creates a new file system
266 public void createFolder(IPath destinationPath) {
267 new File(destinationPath.toOSString()).mkdir();
271 * Writes the passed resource to the specified location recursively
273 public void write(IResource resource, IPath destinationPath)
274 throws CoreException, IOException {
275 if (resource.getType() == IResource.FILE)
276 writeFile((IFile) resource, destinationPath);
278 writeChildren((IContainer) resource, destinationPath);
282 * Exports the passed container's children
284 protected void writeChildren(IContainer folder, IPath destinationPath)
285 throws CoreException, IOException {
286 if (folder.isAccessible()) {
287 IResource[] children = folder.members();
288 for (int i = 0; i < children.length; i++) {
289 IResource child = children[i];
290 writeResource(child, destinationPath.append(child.getName()));
296 * Writes the passed file resource to the specified destination on the local
299 protected void writeFile(IFile file, IPath destinationPath)
300 throws IOException, CoreException {
301 if (PHPFileUtil.isPHPFile(file)) {
302 InputStream stream = null;
303 char[] charArray = null;
305 stream = new BufferedInputStream(file.getContents());
306 charArray = Util.getInputStreamAsCharArray(stream, -1, null);
307 } catch (IOException e) {
311 if (stream != null) {
314 } catch (IOException e) {
318 if (charArray == null) {
319 // TODO show error message
323 fScanner.setSource(charArray);
324 fScanner.setPHPMode(false);
325 fToken = TokenNameEOF;
328 StringBuffer buf = new StringBuffer();
329 if (!obfuscate(buf)) {
330 copyFile(file, destinationPath);
332 // charArray = buf.toString().toCharArray();
333 // File targetFile = new File(destinationPath.toOSString());
334 BufferedWriter bw = new BufferedWriter(new FileWriter(
335 destinationPath.toOSString()));
336 bw.write(buf.toString());
341 copyFile(file, destinationPath);
345 private void copyFile(IFile file, IPath destinationPath)
346 throws FileNotFoundException, CoreException, IOException {
347 FileOutputStream output = null;
348 InputStream contentStream = null;
351 output = new FileOutputStream(destinationPath.toOSString());
352 contentStream = file.getContents(false);
353 int chunkSize = contentStream.available();
354 byte[] readBuffer = new byte[chunkSize];
355 int n = contentStream.read(readBuffer);
358 output.write(readBuffer);
359 n = contentStream.read(readBuffer);
364 if (contentStream != null)
365 contentStream.close();
370 * Writes the passed resource to the specified location recursively
372 protected void writeResource(IResource resource, IPath destinationPath)
373 throws CoreException, IOException {
374 if (resource.getType() == IResource.FILE)
375 writeFile((IFile) resource, destinationPath);
377 createFolder(destinationPath);
378 writeChildren((IContainer) resource, destinationPath);