1 package net.sourceforge.phpeclipse.mover.obfuscator;
3 import java.io.BufferedReader;
4 import java.io.BufferedWriter;
6 import java.io.FileInputStream;
7 import java.io.FileOutputStream;
8 import java.io.FileReader;
9 import java.io.FileWriter;
10 import java.io.IOException;
11 import java.security.MessageDigest;
12 import java.security.NoSuchAlgorithmException;
13 import java.util.ArrayList;
14 import java.util.HashMap;
16 import net.sourceforge.phpdt.core.compiler.ITerminalSymbols;
17 import net.sourceforge.phpdt.core.compiler.InvalidInputException;
18 import net.sourceforge.phpdt.internal.compiler.parser.Scanner;
19 import net.sourceforge.phpdt.internal.compiler.parser.SyntaxError;
20 import net.sourceforge.phpeclipse.PHPeclipsePlugin;
21 import net.sourceforge.phpeclipse.mover.DefaultMover;
22 import net.sourceforge.phpeclipse.views.PHPConsole;
24 import org.eclipse.jface.preference.IPreferenceStore;
27 * Obfuscate the file with the PHP Scanner
29 public class PHPObfuscatorMover extends DefaultMover implements ITerminalSymbols {
31 private Scanner fScanner;
33 private MessageDigest fAlgorithm;
36 protected HashMap fIdentifierMap;
39 * buffer, for obvious reasons access to this buffer must
42 protected byte[] bytes = new byte[1024];
44 * Creates a PHPAnalyzer
45 * @param console reports error to the PHPConsole
47 public PHPObfuscatorMover(PHPConsole console, Scanner scanner, HashMap identifierMap) {
49 this.fScanner = scanner;
50 this.fIdentifierMap = identifierMap;
53 this.fAlgorithm = MessageDigest.getInstance("MD5");
54 } catch (NoSuchAlgorithmException e) {
55 System.out.println(e.toString());
60 * Return the name the file would have after moving. In this case,
61 * it's left unchanged.
62 * @param file file the mover would have to move
63 * @return the extension it would give the file in the target directory
65 public String getTargetName(File file) {
66 return file.getName();
70 * gets the next token from input
72 private void getNextToken() {
75 fToken = fScanner.getNextToken();
77 int currentEndPosition = fScanner.getCurrentTokenEndPosition();
78 int currentStartPosition = fScanner.getCurrentTokenStartPosition();
80 System.out.print(currentStartPosition + "," + currentEndPosition + ": ");
81 System.out.println(fScanner.toStringAction(fToken));
84 } catch (InvalidInputException e) {
87 fToken = TokenNameERROR;
90 private boolean obfuscate(StringBuffer buf) {
95 int startPosition = 0;
98 IPreferenceStore store = PHPeclipsePlugin.getDefault().getPreferenceStore();
100 while (fToken != TokenNameEOF && fToken != TokenNameERROR) {
101 if (fToken == TokenNameVariable) {
102 identifier = new String(fScanner.getCurrentIdentifierSource());
103 lastPosition = fScanner.startPosition;
104 int len = lastPosition - startPosition;
105 buf.append(fScanner.source, startPosition, len);
106 value = (PHPIdentifier) fIdentifierMap.get(identifier);
108 String obfuscatedIdentifier = value.getIdentifier();
109 if (obfuscatedIdentifier == null) {
110 buf.append("$v" + Integer.toString(fCounter));
111 value.setIdentifier("$v" + Integer.toString(fCounter++));
113 buf.append(obfuscatedIdentifier);
115 // System.out.println(hexString.toString());
117 buf.append(identifier);
119 startPosition = fScanner.currentPosition;
121 } else if (fToken == TokenNameIdentifier) {
122 identifier = new String(fScanner.getCurrentIdentifierSource());
123 lastPosition = fScanner.startPosition;
124 int len = lastPosition - startPosition;
125 buf.append(fScanner.source, startPosition, len);
126 value = (PHPIdentifier) fIdentifierMap.get(identifier);
128 String obfuscatedIdentifier = value.getIdentifier();
129 if (obfuscatedIdentifier == null) {
130 buf.append("_" + Integer.toString(fCounter));
131 value.setIdentifier("_" + Integer.toString(fCounter++));
133 buf.append(obfuscatedIdentifier);
135 // System.out.println(hexString.toString());
137 buf.append(identifier);
139 startPosition = fScanner.currentPosition;
142 } else if (fToken == TokenNameCOMMENT_LINE || fToken == TokenNameCOMMENT_BLOCK || fToken == TokenNameCOMMENT_PHPDOC) {
143 lastPosition = fScanner.startPosition;
144 buf.append(fScanner.source, startPosition, lastPosition - startPosition);
145 startPosition = fScanner.currentPosition;
147 } else if (fToken == TokenNameStringLiteral) {
148 char currentCharacter;
149 int i = fScanner.startPosition;
150 ArrayList varList = new ArrayList();
152 lastPosition = fScanner.startPosition;
153 int len = lastPosition - startPosition;
154 buf.append(fScanner.source, startPosition, len);
156 while (i < fScanner.currentPosition) {
157 currentCharacter = fScanner.source[i++];
158 if (currentCharacter == '$' && fScanner.source[i-2]!='\\') {
159 StringBuffer varName = new StringBuffer();
161 while (i < fScanner.currentPosition) {
162 currentCharacter = fScanner.source[i++];
163 if (!Scanner.isPHPIdentifierPart(currentCharacter)) {
166 varName.append(currentCharacter);
168 varList.add(varName.toString());
171 StringBuffer stringLiteral = new StringBuffer();
172 stringLiteral.append(fScanner.source, fScanner.startPosition, fScanner.currentPosition - fScanner.startPosition);
177 for (int j = 0; j < varList.size(); j++) {
178 stringIdent = (String) varList.get(j);
179 len = stringIdent.length();
180 value = (PHPIdentifier) fIdentifierMap.get(stringIdent);
182 String obfuscatedIdentifier = value.getIdentifier();
183 if (obfuscatedIdentifier == null) {
184 replacement = "$v" + Integer.toString(fCounter);
185 value.setIdentifier("$v" + Integer.toString(fCounter++));
187 replacement = obfuscatedIdentifier;
189 // System.out.println(hexString.toString());
191 replacement = stringIdent;
193 index = stringLiteral.indexOf(stringIdent);
195 if (index > 0 && stringLiteral.charAt(index-1)!='\\') {
196 stringLiteral.replace(index, index + stringIdent.length(), replacement);
197 } else if (index==0) {
198 stringLiteral.replace(index, index + stringIdent.length(), replacement);
202 buf.append(stringLiteral);
203 startPosition = fScanner.currentPosition;
206 if (fToken == TokenNameMINUS_GREATER) { // i.e. $this->var_name
208 if (fToken == TokenNameIdentifier) {
209 // assuming this is a dereferenced variable
210 identifier = new String(fScanner.getCurrentIdentifierSource());
211 lastPosition = fScanner.startPosition;
212 int len = lastPosition - startPosition;
213 buf.append(fScanner.source, startPosition, len);
214 value = (PHPIdentifier) fIdentifierMap.get("$" + identifier);
215 if (value != null && value.isVariable()) {
216 String obfuscatedIdentifier = value.getIdentifier();
217 if (obfuscatedIdentifier == null) {
218 // note: don't place a $ before the identifier
219 buf.append("v" + Integer.toString(fCounter));
220 value.setIdentifier("$v" + Integer.toString(fCounter++));
222 if (obfuscatedIdentifier.charAt(0) == '$') {
223 buf.append(obfuscatedIdentifier.substring(1));
225 buf.append(obfuscatedIdentifier);
229 buf.append(identifier);
231 startPosition = fScanner.currentPosition;
239 if (startPosition < fScanner.source.length) {
240 buf.append(fScanner.source, startPosition, fScanner.source.length - startPosition);
243 } catch (SyntaxError sytaxErr) {
250 public File copy(File sourceFile, File targetDir) {
252 File targetFile = new File(targetDir, getTargetName(sourceFile));
253 // if (targetFile.exists())
254 // if (targetFile.lastModified() >= sourceFile.lastModified())
256 synchronized (bytes) {
257 FileInputStream in = new FileInputStream(sourceFile);
258 FileOutputStream out = new FileOutputStream(targetFile);
259 for (int len = in.read(bytes); len != -1; len = in.read(bytes)) {
260 out.write(bytes, 0, len);
266 } catch (IOException e) {
267 fConsole.write(e.toString());
274 * @param sourceFile the file to move
275 * @param targetDir the directory to copy the result to
276 * @return file or null if the file was ignored
278 public File move(File sourceFile, File targetDir) {
282 String fileName = sourceFile.getAbsolutePath().toLowerCase();
283 if (fileName.endsWith(".php")
284 || fileName.endsWith(".php3")
285 || fileName.endsWith(".php4")
286 || fileName.endsWith(".phtml")
287 || fileName.endsWith(".inc")) {
288 StringBuffer buf = new StringBuffer();
289 long filelen = sourceFile.length();
290 char[] charArray = new char[(int) filelen];
292 BufferedReader br = new BufferedReader(new FileReader(sourceFile.getAbsolutePath()));
293 br.read(charArray, 0, (int) filelen);
297 // while ((line = br.readLine()) != null) {
298 // System.arraycopy(line.toCharArray(), 0, charArray, offset, line.length());
299 // offset += line.length();
303 fScanner.setSource(charArray);
304 fScanner.setPHPMode(false);
305 fToken = TokenNameEOF;
307 buf = new StringBuffer();
308 if (!obfuscate(buf)) {
309 return copy(sourceFile, targetDir);
311 File targetFile = new File(targetDir, getTargetName(sourceFile));
312 BufferedWriter bw = new BufferedWriter(new FileWriter(targetFile));
313 bw.write(buf.toString());
319 return copy(sourceFile, targetDir);
322 } catch (IOException e) {
323 fConsole.write(e.toString());