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