47923a6d48801fdde6ee99d374ada6834f9ccd58
[phpeclipse.git] / net.sourceforge.phpeclipse / src / net / sourceforge / phpeclipse / obfuscator / ObfuscatorPass2Exporter.java
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
7  * 
8  * Contributors:
9  *     IBM Corporation - initial API and implementation
10  *******************************************************************************/
11 package net.sourceforge.phpeclipse.obfuscator;
12
13 import java.io.BufferedInputStream;
14 import java.io.BufferedWriter;
15 import java.io.File;
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;
23
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
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;
38
39 /**
40  * Helper class for exporting resources to the file system.
41  */
42 public class ObfuscatorPass2Exporter implements ITerminalSymbols {
43         private Scanner fScanner;
44
45         private int fToken;
46
47         private int fCounter;
48
49         protected HashMap fIdentifierMap;
50
51         public ObfuscatorPass2Exporter(Scanner scanner, HashMap identifierMap) {
52                 fScanner = scanner;
53                 fIdentifierMap = identifierMap;
54                 fCounter = 0;
55         }
56
57         /**
58          * gets the next token from input
59          */
60         private void getNextToken() {
61
62                 try {
63                         fToken = fScanner.getNextToken();
64                         if (Scanner.DEBUG) {
65                                 int currentEndPosition = fScanner.getCurrentTokenEndPosition();
66                                 int currentStartPosition = fScanner
67                                                 .getCurrentTokenStartPosition();
68
69                                 System.out.print(currentStartPosition + ","
70                                                 + currentEndPosition + ": ");
71                                 System.out.println(fScanner.toStringAction(fToken));
72                         }
73                         return;
74                 } catch (InvalidInputException e) {
75
76                 }
77                 fToken = TokenNameERROR;
78         }
79
80         private boolean obfuscate(StringBuffer buf) {
81                 char[] ident;
82                 String identifier;
83                 PHPIdentifier value;
84
85                 int startPosition = 0;
86                 int lastPosition = 0;
87
88                 IPreferenceStore store = PHPeclipsePlugin.getDefault()
89                                 .getPreferenceStore();
90                 try {
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);
99                                         if (value != null) {
100                                                 String obfuscatedIdentifier = value.getIdentifier();
101                                                 if (obfuscatedIdentifier == null) {
102                                                         buf.append("$v" + Integer.toString(fCounter));
103                                                         value.setIdentifier("$v"
104                                                                         + Integer.toString(fCounter++));
105                                                 } else {
106                                                         buf.append(obfuscatedIdentifier);
107                                                 }
108                                                 // System.out.println(hexString.toString());
109                                         } else {
110                                                 buf.append(identifier);
111                                         }
112                                         startPosition = fScanner.currentPosition;
113                                         getNextToken();
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);
121                                         if (value != null) {
122                                                 String obfuscatedIdentifier = value.getIdentifier();
123                                                 if (obfuscatedIdentifier == null) {
124                                                         buf.append("_" + Integer.toString(fCounter));
125                                                         value.setIdentifier("_"
126                                                                         + Integer.toString(fCounter++));
127                                                 } else {
128                                                         buf.append(obfuscatedIdentifier);
129                                                 }
130                                                 // System.out.println(hexString.toString());
131                                         } else {
132                                                 buf.append(identifier);
133                                         }
134                                         startPosition = fScanner.currentPosition;
135                                         getNextToken();
136
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
142                                                         - startPosition);
143                                         startPosition = fScanner.currentPosition;
144                                         getNextToken();
145                                 } else if (fToken == TokenNameStringDoubleQuote) {
146                                         char currentCharacter;
147                                         int i = fScanner.startPosition;
148                                         ArrayList varList = new ArrayList();
149
150                                         lastPosition = fScanner.startPosition;
151                                         int len = lastPosition - startPosition;
152                                         buf.append(fScanner.source, startPosition, len);
153
154                                         while (i < fScanner.currentPosition) {
155                                                 currentCharacter = fScanner.source[i++];
156                                                 if (currentCharacter == '$'
157                                                                 && fScanner.source[i - 2] != '\\') {
158                                                         StringBuffer varName = new StringBuffer();
159                                                         varName.append("$");
160                                                         while (i < fScanner.currentPosition) {
161                                                                 currentCharacter = fScanner.source[i++];
162                                                                 if (!Scanner
163                                                                                 .isPHPIdentifierPart(currentCharacter)) {
164                                                                         break; // while loop
165                                                                 }
166                                                                 varName.append(currentCharacter);
167                                                         }
168                                                         varList.add(varName.toString());
169                                                 }
170                                         }
171                                         StringBuffer stringLiteral = new StringBuffer();
172                                         stringLiteral.append(fScanner.source,
173                                                         fScanner.startPosition, fScanner.currentPosition
174                                                                         - fScanner.startPosition);
175                                         String stringIdent;
176                                         String replacement;
177                                         int index;
178
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);
183                                                 if (value != null) {
184                                                         String obfuscatedIdentifier = value.getIdentifier();
185                                                         if (obfuscatedIdentifier == null) {
186                                                                 replacement = "$v" + Integer.toString(fCounter);
187                                                                 value.setIdentifier("$v"
188                                                                                 + Integer.toString(fCounter++));
189                                                         } else {
190                                                                 replacement = obfuscatedIdentifier;
191                                                         }
192                                                         // System.out.println(hexString.toString());
193                                                 } else {
194                                                         replacement = stringIdent;
195                                                 }
196                                                 index = stringLiteral.indexOf(stringIdent);
197                                                 if (index >= 0) {
198                                                         if (index > 0
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);
205                                                         }
206                                                 }
207                                         }
208                                         buf.append(stringLiteral);
209                                         startPosition = fScanner.currentPosition;
210                                         getNextToken();
211                                 }
212                                 if (fToken == TokenNameMINUS_GREATER) { // i.e. $this->var_name
213                                         getNextToken();
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("$"
222                                                                 + identifier);
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++));
230                                                         } else {
231                                                                 if (obfuscatedIdentifier.charAt(0) == '$') {
232                                                                         buf.append(obfuscatedIdentifier
233                                                                                         .substring(1));
234                                                                 } else {
235                                                                         buf.append(obfuscatedIdentifier);
236                                                                 }
237                                                         }
238                                                 } else {
239                                                         buf.append(identifier);
240                                                 }
241                                                 startPosition = fScanner.currentPosition;
242                                                 getNextToken();
243                                         }
244
245                                 } else {
246                                         getNextToken();
247                                 }
248                         }
249                         if (startPosition < fScanner.source.length) {
250                                 buf.append(fScanner.source, startPosition,
251                                                 fScanner.source.length - startPosition);
252                         }
253                         return true;
254                 } catch (SyntaxError sytaxErr) {
255                         // do nothing
256                 }
257
258                 return false;
259         }
260
261         /**
262          * Creates the specified file system directory at
263          * <code>destinationPath</code>. This creates a new file system
264          * directory.
265          */
266         public void createFolder(IPath destinationPath) {
267                 new File(destinationPath.toOSString()).mkdir();
268         }
269
270         /**
271          * Writes the passed resource to the specified location recursively
272          */
273         public void write(IResource resource, IPath destinationPath)
274                         throws CoreException, IOException {
275                 if (resource.getType() == IResource.FILE)
276                         writeFile((IFile) resource, destinationPath);
277                 else
278                         writeChildren((IContainer) resource, destinationPath);
279         }
280
281         /**
282          * Exports the passed container's children
283          */
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()));
291                         }
292                 }
293         }
294
295         /**
296          * Writes the passed file resource to the specified destination on the local
297          * file system
298          */
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;
304                         try {
305                                 stream = new BufferedInputStream(file.getContents());
306                                 charArray = Util.getInputStreamAsCharArray(stream, -1, null);
307                         } catch (IOException e) {
308                                 return;
309                         } finally {
310                                 try {
311                                         if (stream != null) {
312                                                 stream.close();
313                                         }
314                                 } catch (IOException e) {
315                                 }
316                         }
317
318                         if (charArray == null) {
319                                 // TODO show error message
320                                 return;
321                         }
322
323                         fScanner.setSource(charArray);
324                         fScanner.setPHPMode(false);
325                         fToken = TokenNameEOF;
326                         getNextToken();
327
328                         StringBuffer buf = new StringBuffer();
329                         if (!obfuscate(buf)) {
330                                 copyFile(file, destinationPath);
331                         } else {
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());
337                                 bw.close();
338                         }
339
340                 } else {
341                         copyFile(file, destinationPath);
342                 }
343         }
344
345         private void copyFile(IFile file, IPath destinationPath)
346                         throws FileNotFoundException, CoreException, IOException {
347                 FileOutputStream output = null;
348                 InputStream contentStream = null;
349
350                 try {
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);
356
357                         while (n > 0) {
358                                 output.write(readBuffer);
359                                 n = contentStream.read(readBuffer);
360                         }
361                 } finally {
362                         if (output != null)
363                                 output.close();
364                         if (contentStream != null)
365                                 contentStream.close();
366                 }
367         }
368
369         /**
370          * Writes the passed resource to the specified location recursively
371          */
372         protected void writeResource(IResource resource, IPath destinationPath)
373                         throws CoreException, IOException {
374                 if (resource.getType() == IResource.FILE)
375                         writeFile((IFile) resource, destinationPath);
376                 else {
377                         createFolder(destinationPath);
378                         writeChildren((IContainer) resource, destinationPath);
379                 }
380         }
381 }