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;
47 protected HashMap fIdentifierMap;
49 public ObfuscatorPass2Exporter(Scanner scanner, HashMap identifierMap) {
51 fIdentifierMap = identifierMap;
56 * gets the next token from input
58 private void getNextToken() {
61 fToken = fScanner.getNextToken();
63 int currentEndPosition = fScanner.getCurrentTokenEndPosition();
64 int currentStartPosition = fScanner.getCurrentTokenStartPosition();
66 System.out.print(currentStartPosition + "," + currentEndPosition + ": ");
67 System.out.println(fScanner.toStringAction(fToken));
70 } catch (InvalidInputException e) {
73 fToken = TokenNameERROR;
76 private boolean obfuscate(StringBuffer buf) {
81 int startPosition = 0;
84 IPreferenceStore store = PHPeclipsePlugin.getDefault().getPreferenceStore();
86 while (fToken != TokenNameEOF && fToken != TokenNameERROR) {
87 if (fToken == TokenNameVariable) {
88 identifier = new String(fScanner.getCurrentIdentifierSource());
89 lastPosition = fScanner.startPosition;
90 int len = lastPosition - startPosition;
91 buf.append(fScanner.source, startPosition, len);
92 value = (PHPIdentifier) fIdentifierMap.get(identifier);
94 String obfuscatedIdentifier = value.getIdentifier();
95 if (obfuscatedIdentifier == null) {
96 buf.append("$v" + Integer.toString(fCounter));
97 value.setIdentifier("$v" + Integer.toString(fCounter++));
99 buf.append(obfuscatedIdentifier);
101 // System.out.println(hexString.toString());
103 buf.append(identifier);
105 startPosition = fScanner.currentPosition;
107 } else if (fToken == TokenNameIdentifier) {
108 identifier = new String(fScanner.getCurrentIdentifierSource());
109 lastPosition = fScanner.startPosition;
110 int len = lastPosition - startPosition;
111 buf.append(fScanner.source, startPosition, len);
112 value = (PHPIdentifier) fIdentifierMap.get(identifier);
114 String obfuscatedIdentifier = value.getIdentifier();
115 if (obfuscatedIdentifier == null) {
116 buf.append("_" + Integer.toString(fCounter));
117 value.setIdentifier("_" + Integer.toString(fCounter++));
119 buf.append(obfuscatedIdentifier);
121 // System.out.println(hexString.toString());
123 buf.append(identifier);
125 startPosition = fScanner.currentPosition;
128 } else if (fToken == TokenNameCOMMENT_LINE || fToken == TokenNameCOMMENT_BLOCK || fToken == TokenNameCOMMENT_PHPDOC) {
129 lastPosition = fScanner.startPosition;
130 buf.append(fScanner.source, startPosition, lastPosition - startPosition);
131 startPosition = fScanner.currentPosition;
133 } else if (fToken == TokenNameStringLiteral) {
134 char currentCharacter;
135 int i = fScanner.startPosition;
136 ArrayList varList = new ArrayList();
138 lastPosition = fScanner.startPosition;
139 int len = lastPosition - startPosition;
140 buf.append(fScanner.source, startPosition, len);
142 while (i < fScanner.currentPosition) {
143 currentCharacter = fScanner.source[i++];
144 if (currentCharacter == '$' && fScanner.source[i - 2] != '\\') {
145 StringBuffer varName = new StringBuffer();
147 while (i < fScanner.currentPosition) {
148 currentCharacter = fScanner.source[i++];
149 if (!Scanner.isPHPIdentifierPart(currentCharacter)) {
152 varName.append(currentCharacter);
154 varList.add(varName.toString());
157 StringBuffer stringLiteral = new StringBuffer();
158 stringLiteral.append(fScanner.source, fScanner.startPosition, fScanner.currentPosition - fScanner.startPosition);
163 for (int j = 0; j < varList.size(); j++) {
164 stringIdent = (String) varList.get(j);
165 len = stringIdent.length();
166 value = (PHPIdentifier) fIdentifierMap.get(stringIdent);
168 String obfuscatedIdentifier = value.getIdentifier();
169 if (obfuscatedIdentifier == null) {
170 replacement = "$v" + Integer.toString(fCounter);
171 value.setIdentifier("$v" + Integer.toString(fCounter++));
173 replacement = obfuscatedIdentifier;
175 // System.out.println(hexString.toString());
177 replacement = stringIdent;
179 index = stringLiteral.indexOf(stringIdent);
181 if (index > 0 && stringLiteral.charAt(index - 1) != '\\') {
182 stringLiteral.replace(index, index + stringIdent.length(), replacement);
183 } else if (index == 0) {
184 stringLiteral.replace(index, index + stringIdent.length(), replacement);
188 buf.append(stringLiteral);
189 startPosition = fScanner.currentPosition;
192 if (fToken == TokenNameMINUS_GREATER) { // i.e. $this->var_name
194 if (fToken == TokenNameIdentifier) {
195 // assuming this is a dereferenced variable
196 identifier = new String(fScanner.getCurrentIdentifierSource());
197 lastPosition = fScanner.startPosition;
198 int len = lastPosition - startPosition;
199 buf.append(fScanner.source, startPosition, len);
200 value = (PHPIdentifier) fIdentifierMap.get("$" + identifier);
201 if (value != null && value.isVariable()) {
202 String obfuscatedIdentifier = value.getIdentifier();
203 if (obfuscatedIdentifier == null) {
204 // note: don't place a $ before the identifier
205 buf.append("v" + Integer.toString(fCounter));
206 value.setIdentifier("$v" + Integer.toString(fCounter++));
208 if (obfuscatedIdentifier.charAt(0) == '$') {
209 buf.append(obfuscatedIdentifier.substring(1));
211 buf.append(obfuscatedIdentifier);
215 buf.append(identifier);
217 startPosition = fScanner.currentPosition;
225 if (startPosition < fScanner.source.length) {
226 buf.append(fScanner.source, startPosition, fScanner.source.length - startPosition);
229 } catch (SyntaxError sytaxErr) {
236 * Creates the specified file system directory at <code>destinationPath</code>.
237 * This creates a new file system directory.
239 public void createFolder(IPath destinationPath) {
240 new File(destinationPath.toOSString()).mkdir();
243 * Writes the passed resource to the specified location recursively
245 public void write(IResource resource, IPath destinationPath) throws CoreException, IOException {
246 if (resource.getType() == IResource.FILE)
247 writeFile((IFile) resource, destinationPath);
249 writeChildren((IContainer) resource, destinationPath);
252 * Exports the passed container's children
254 protected void writeChildren(IContainer folder, IPath destinationPath) throws CoreException, IOException {
255 if (folder.isAccessible()) {
256 IResource[] children = folder.members();
257 for (int i = 0; i < children.length; i++) {
258 IResource child = children[i];
259 writeResource(child, destinationPath.append(child.getName()));
264 * Writes the passed file resource to the specified destination on the local
267 protected void writeFile(IFile file, IPath destinationPath) throws IOException, CoreException {
268 if (PHPFileUtil.isPHPFile(file)) {
269 InputStream stream = null;
270 char[] charArray = null;
272 stream = new BufferedInputStream(file.getContents());
273 charArray = Util.getInputStreamAsCharArray(stream, -1, null);
274 } catch (IOException e) {
278 if (stream != null) {
281 } catch (IOException e) {
285 if (charArray == null) {
286 // TODO show error message
290 fScanner.setSource(charArray);
291 fScanner.setPHPMode(false);
292 fToken = TokenNameEOF;
295 StringBuffer buf = new StringBuffer();
296 if (!obfuscate(buf)) {
297 copyFile(file, destinationPath);
299 // charArray = buf.toString().toCharArray();
300 // File targetFile = new File(destinationPath.toOSString());
301 BufferedWriter bw = new BufferedWriter(new FileWriter(destinationPath.toOSString()));
302 bw.write(buf.toString());
307 copyFile(file, destinationPath);
311 private void copyFile(IFile file, IPath destinationPath) throws FileNotFoundException, CoreException, IOException {
312 FileOutputStream output = null;
313 InputStream contentStream = null;
316 output = new FileOutputStream(destinationPath.toOSString());
317 contentStream = file.getContents(false);
318 int chunkSize = contentStream.available();
319 byte[] readBuffer = new byte[chunkSize];
320 int n = contentStream.read(readBuffer);
323 output.write(readBuffer);
324 n = contentStream.read(readBuffer);
329 if (contentStream != null)
330 contentStream.close();
334 * Writes the passed resource to the specified location recursively
336 protected void writeResource(IResource resource, IPath destinationPath) throws CoreException, IOException {
337 if (resource.getType() == IResource.FILE)
338 writeFile((IFile) resource, destinationPath);
340 createFolder(destinationPath);
341 writeChildren((IContainer) resource, destinationPath);