From: khartlage Date: Fri, 13 Jun 2003 20:51:33 +0000 (+0000) Subject: *** empty log message *** X-Git-Url: http://git.phpeclipse.com *** empty log message *** --- diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpeclipse/actions/PHPObfuscatorAction.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpeclipse/actions/PHPObfuscatorAction.java new file mode 100644 index 0000000..222b3a8 --- /dev/null +++ b/net.sourceforge.phpeclipse/src/net/sourceforge/phpeclipse/actions/PHPObfuscatorAction.java @@ -0,0 +1,168 @@ +/********************************************************************** +Copyright (c) 2000, 2002 IBM Corp. and others. +All rights reserved. This program and the accompanying materials +are made available under the terms of the Common Public License v1.0 +which accompanies this distribution, and is available at +http://www.eclipse.org/legal/cpl-v10.html + + Klaus Hartlage - www.eclipseproject.de +**********************************************************************/ +package net.sourceforge.phpeclipse.actions; + +import java.io.IOException; +import java.util.HashMap; +import java.util.Iterator; + +import net.sourceforge.phpdt.internal.compiler.parser.Scanner; +import net.sourceforge.phpeclipse.PHPeclipsePlugin; +import net.sourceforge.phpeclipse.mover.DefaultFilter; +import net.sourceforge.phpeclipse.mover.DirectoryWalker; +import net.sourceforge.phpeclipse.mover.IFilter; +import net.sourceforge.phpeclipse.mover.IMover; +import net.sourceforge.phpeclipse.mover.obfuscator.PHPAnalyzer; +import net.sourceforge.phpeclipse.mover.obfuscator.PHPIdentifier; +import net.sourceforge.phpeclipse.mover.obfuscator.PHPObfuscatorMover; +import net.sourceforge.phpeclipse.preferences.IObfuscatorPreferences; +import net.sourceforge.phpeclipse.views.PHPConsole; + +import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IFolder; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.IResource; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.jface.action.IAction; +import org.eclipse.jface.preference.IPreferenceStore; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.viewers.ISelectionProvider; +import org.eclipse.jface.viewers.StructuredSelection; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.ui.IObjectActionDelegate; +import org.eclipse.ui.IWorkbenchPart; + +public class PHPObfuscatorAction implements IObjectActionDelegate { + private static String[] PREDEFINED_PHP_VARIABLES = + { + "$this", + "$AUTH_TYPE", + "$CONTENT_LENGTH", + "$CONTENT_TYPE", + "$GATEWAY_INTERFACE", + "$GLOBALS", + "$HTTP_ACCEPT", + "$HTTP_COOKIE", + "$HTTP_COOKIE_VARS", + "$HTTP_POST_VARS", + "$HTTP_REFERER", + "$HTTP_USER_AGENT", + "$PATH_INFO", + "$PATH_TRANSLATED", + "$PHP_AUTH_PW", + "$PHP_AUTH_USER", + "$PHP_ERRORMSG", + "$PHP_SELF", + "$QUERY_STRING", + "$REMOTE_ADDR", + "$REMOTE_HOST", + "$REMOTE_IDENT", + "$REMOTE_USER", + "$REQUEST_METHOD", + "$SCRIPT_NAME", + "$SERVER_NAME", + "$SERVER_PORT", + "$SERVER_PROTOCOL", + "$SERVER_SOFTWARE" + }; + private IWorkbenchPart workbenchPart; + /** + * Constructor for Action1. + */ + public PHPObfuscatorAction() { + super(); + } + + /** + * @see IObjectActionDelegate#setActivePart(IAction, IWorkbenchPart) + */ + public void setActivePart(IAction action, IWorkbenchPart targetPart) { + workbenchPart = targetPart; + } + + public void run(IAction action) { + ISelectionProvider selectionProvider = null; + selectionProvider = workbenchPart.getSite().getSelectionProvider(); + + StructuredSelection selection = null; + selection = (StructuredSelection) selectionProvider.getSelection(); + PHPConsole console = PHPConsole.getInstance(); + + IPreferenceStore store = PHPeclipsePlugin.getDefault().getPreferenceStore(); + + Shell shell = null; + Iterator iterator = null; + iterator = selection.iterator(); + while (iterator.hasNext()) { + // obj => selected object in the view + Object obj = iterator.next(); + + // is it a resource + if (obj instanceof IResource) { + IResource resource = (IResource) obj; + IProject proj = resource.getProject(); + String sourcePath; + // String publishPath = "c:\\temp"; + String publishPath; + try { + publishPath = proj.getPersistentProperty(IObfuscatorPreferences.PUBLISH_PROPERTY_NAME); + } catch (CoreException e) { + return; + } + HashMap identifierMap = new HashMap(8096); + for (int i=0;i= sourceFile.lastModified()) + return null; + synchronized (bytes) { + FileInputStream in = new FileInputStream(sourceFile); + FileOutputStream out = new FileOutputStream(targetFile); + for (int len = in.read(bytes); len != -1; len = in.read(bytes)) { + out.write(bytes, 0, len); + } + in.close(); + out.close(); + } + return targetFile; + } catch (IOException e) { + fConsole.write(e.toString()); + } + return null; + } +} \ No newline at end of file diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpeclipse/mover/DefaultFilter.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpeclipse/mover/DefaultFilter.java new file mode 100644 index 0000000..0c2f4b9 --- /dev/null +++ b/net.sourceforge.phpeclipse/src/net/sourceforge/phpeclipse/mover/DefaultFilter.java @@ -0,0 +1,17 @@ +package net.sourceforge.phpeclipse.mover; + +import java.io.File; + +/** + * + */ +public class DefaultFilter implements IFilter { + + public boolean isFileOk(File file) { + return true; + } + + public boolean isDirectoryOk(File file) { + return true; + } +} diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpeclipse/mover/DefaultMover.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpeclipse/mover/DefaultMover.java new file mode 100644 index 0000000..b281529 --- /dev/null +++ b/net.sourceforge.phpeclipse/src/net/sourceforge/phpeclipse/mover/DefaultMover.java @@ -0,0 +1,52 @@ +package net.sourceforge.phpeclipse.mover; + + +import java.io.File; + +import net.sourceforge.phpeclipse.views.PHPConsole; + +/** + * Provides default mover implementation + * + */ +abstract public class DefaultMover + implements IMover +{ + /** + * Console for output + * */ + protected PHPConsole fConsole; + + /** + * Creates a DefaultMover + * @param console Console to report errors to + */ + public DefaultMover(PHPConsole console) + { + this.fConsole = console; + } + + /** + * compute a file extension + * @param file file to compute the extension from + * @return the file extension (excluding the .), "" if none + */ + public static String getExtension(File file) + { + String filename = file.getName(); + int index = filename.lastIndexOf('.'); + return index != -1 ? filename.substring(index + 1) : ""; + } + + /** + * compute the filename without the extension + * @param file file to compute the extension from + * @return the file name without the extension (excluding the .) + */ + public static String getDisplayName(File file) + { + String filename = file.getName(); + int index = filename.lastIndexOf('.'); + return index != -1 ? filename.substring(0,index) : filename; + } +} diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpeclipse/mover/DirectoryWalker.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpeclipse/mover/DirectoryWalker.java new file mode 100644 index 0000000..0746ad3 --- /dev/null +++ b/net.sourceforge.phpeclipse/src/net/sourceforge/phpeclipse/mover/DirectoryWalker.java @@ -0,0 +1,105 @@ +package net.sourceforge.phpeclipse.mover; + +import java.io.File; +import java.io.IOException; + +public class DirectoryWalker { + + protected IMover[] fMover; + protected IFilter[] fFilter; + /** + * creates a new DirectoryWalker + * mover and filter array should have the same length ! + */ + public DirectoryWalker(IMover[] mover, IFilter[] filter) { + this.fMover = mover; + this.fFilter = filter; + } + + /** + * creates a new DirectoryWalker with a IFilter.DEFAULT_FILTER + */ + public DirectoryWalker(IMover[] mover) { + this.fMover = mover; + this.fFilter = new IFilter[mover.length]; + for (int i = 0; i < mover.length; i++) { + this.fFilter[i] = IFilter.DEFAULT_FILTER; + } + } + /** + * walks through the source directory, processing files as it + * goes along to create the target directory + * @param source source directory + * @param target target directory + * @throws IOException error with the file system + * @throws XMException error caught by the application + */ + public void walk(String source, String target) throws IOException { + try { + + walk(new File(source), new File(target)); + } finally { + + } + } + + /** + * actual implementation of the walking + * @param source source directory + * @param target target directory + * @throws IOException error with the file system + * @return true if walking should continue, false if the messenger + * has asked for the end of the walking + */ + protected boolean walk(File source, File target) throws IOException { + + if (!(target.exists() && target.isDirectory())) + if (!target.mkdirs()) + return false; + + for (int j = 0; j < fMover.length; j++) { + File[] dirs; + File[] docs; + int idirs = 0, idocs = 0; + if (source.isDirectory()) { + File[] files = source.listFiles(); + dirs = new File[files.length]; + docs = new File[files.length]; + String fileName; + + for (int i = 0; i < files.length; i++) { + if (files[i].isDirectory()) { + if (fFilter[j].isDirectoryOk(files[i])) { + dirs[idirs++] = files[i]; + } + } else if (files[i].isFile()) { + if (fFilter[j].isFileOk(files[i])) { + docs[idocs++] = files[i]; + } + } else + return false; + } + } else { + dirs = new File[0]; + docs = new File[1]; + docs[0] = source; + idocs = 1; + } + + for (int i = 0; i < idocs; i++) { + System.out.println(docs[i].getAbsolutePath()); + + File result = fMover[j].move(docs[i], target); + } + + System.out.println("directories"); + for (int i = 0; i < idirs; i++) { + System.out.println(dirs[i].getAbsolutePath()); + if (!walk(dirs[i], new File(target, dirs[i].getName()))) + return false; + } + } + + return true; + } +} \ No newline at end of file diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpeclipse/mover/IFilter.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpeclipse/mover/IFilter.java new file mode 100644 index 0000000..77b7f3f --- /dev/null +++ b/net.sourceforge.phpeclipse/src/net/sourceforge/phpeclipse/mover/IFilter.java @@ -0,0 +1,19 @@ +package net.sourceforge.phpeclipse.mover; + +import java.io.File; + +/** + * @author khartlage + * + * To change this generated comment edit the template variable "typecomment": + * Window>Preferences>Java>Templates. + * To enable and disable the creation of type comments go to + * Window>Preferences>Java>Code Generation. + */ +public interface IFilter { + final public static DefaultFilter DEFAULT_FILTER = new DefaultFilter(); + final public static DefaultFilter PHP_FILTER = new PHPFilter(); + + public boolean isFileOk(File file); + public boolean isDirectoryOk(File file); +} diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpeclipse/mover/IMover.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpeclipse/mover/IMover.java new file mode 100644 index 0000000..9bb72b3 --- /dev/null +++ b/net.sourceforge.phpeclipse/src/net/sourceforge/phpeclipse/mover/IMover.java @@ -0,0 +1,28 @@ +package net.sourceforge.phpeclipse.mover; + +/** + * Specify how to move a file from the XML acquisition directory + * to the publishing/HTML/other one. Implementations perform actual + * styling/copying operations. + * + * @author Benoît Marchal + */ + +// Copyright 2001, Benoît Marchal. +//Changes 2003, Klaus Hartlage + +import java.io.*; + +public interface IMover +{ + + /** + * Move one file. + * @param sourceFile the file to move + * @param targetDir the directory to copy the result to + * @return new file or null if the file was ignored + */ + public File move(File sourceFile,File targetDir) + throws IOException; + +} diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpeclipse/mover/PHPFilter.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpeclipse/mover/PHPFilter.java new file mode 100644 index 0000000..eede4c9 --- /dev/null +++ b/net.sourceforge.phpeclipse/src/net/sourceforge/phpeclipse/mover/PHPFilter.java @@ -0,0 +1,25 @@ +package net.sourceforge.phpeclipse.mover; + +import java.io.File; + +/** + * Allows only php files for the mover + */ +public class PHPFilter extends DefaultFilter { + + public boolean isFileOk(File file) { + String fileName = file.getAbsolutePath().toLowerCase(); + if (fileName.endsWith(".php") + || fileName.endsWith(".php3") + || fileName.endsWith(".php4") + || fileName.endsWith(".phtml") + || fileName.endsWith(".inc")) { + return true; + } + return false; + } + + public boolean isDirectoryOk(File file) { + return true; + } +} diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpeclipse/mover/obfuscator/PHPAnalyzer.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpeclipse/mover/obfuscator/PHPAnalyzer.java new file mode 100644 index 0000000..bc7b049 --- /dev/null +++ b/net.sourceforge.phpeclipse/src/net/sourceforge/phpeclipse/mover/obfuscator/PHPAnalyzer.java @@ -0,0 +1,189 @@ +package net.sourceforge.phpeclipse.mover.obfuscator; + +/** + * Analyze the file with the PHP Scanner + */ +import java.io.BufferedReader; +import java.io.File; +import java.io.FileReader; +import java.io.IOException; +import java.util.ArrayList; +import java.util.HashMap; + +import net.sourceforge.phpdt.core.compiler.ITerminalSymbols; +import net.sourceforge.phpdt.core.compiler.InvalidInputException; +import net.sourceforge.phpdt.internal.compiler.parser.Scanner; +import net.sourceforge.phpdt.internal.compiler.parser.SyntaxError; +import net.sourceforge.phpeclipse.PHPeclipsePlugin; +import net.sourceforge.phpeclipse.mover.DefaultMover; +import net.sourceforge.phpeclipse.views.PHPConsole; + +import org.eclipse.jface.preference.IPreferenceStore; + +public class PHPAnalyzer extends DefaultMover implements ITerminalSymbols { + + protected Scanner fScanner; + protected int fToken; + + protected HashMap fIdentifierMap; + + /** + * buffer, for obvious reasons access to this buffer must + * be synchronized + */ + protected byte[] bytes = new byte[1024]; + /** + * Creates a PHPAnalyzer + * @param console reports error to the PHPConsole + */ + public PHPAnalyzer(PHPConsole console, Scanner scanner, HashMap identifierMap) { + super(console); + this.fScanner = scanner; + this.fIdentifierMap = identifierMap; + } + + /** + * gets the next token from input + */ + private void getNextToken() { + + try { + fToken = fScanner.getNextToken(); + if (Scanner.DEBUG) { + int currentEndPosition = fScanner.getCurrentTokenEndPosition(); + int currentStartPosition = fScanner.getCurrentTokenStartPosition(); + + System.out.print(currentStartPosition + "," + currentEndPosition + ": "); + System.out.println(fScanner.toStringAction(fToken)); + } + return; + } catch (InvalidInputException e) { + + } + fToken = TokenNameERROR; + } + + private void parseIdentifiers(boolean goBack) { + char[] ident; + String identifier; + PHPIdentifier value; + int counter = 0; + + IPreferenceStore store = PHPeclipsePlugin.getDefault().getPreferenceStore(); + try { + while (fToken != TokenNameEOF && fToken != TokenNameERROR) { + if (fToken == TokenNameVariable) { + identifier = new String(fScanner.getCurrentIdentifierSource()); + value = (PHPIdentifier) fIdentifierMap.get(identifier); + if (value == null) { + fIdentifierMap.put(identifier, new PHPIdentifier(null, PHPIdentifier.VARIABLE)); + } + getNextToken(); + // } else if (fToken == TokenNamefunction) { + // getNextToken(); + // if (fToken == TokenNameAND) { + // getNextToken(); + // } + // if (fToken == TokenNameIdentifier) { + // ident = fScanner.getCurrentIdentifierSource(); + // outlineInfo.addVariable(new String(ident)); + // temp = new PHPFunctionDeclaration(current, new String(ident), fScanner.getCurrentTokenStartPosition()); + // current.add(temp); + // getNextToken(); + // parseDeclarations(outlineInfo, temp, true); + // } + // } else if (fToken == TokenNameclass) { + // getNextToken(); + // if (fToken == TokenNameIdentifier) { + // ident = fScanner.getCurrentIdentifierSource(); + // outlineInfo.addVariable(new String(ident)); + // temp = new PHPClassDeclaration(current, new String(ident), fScanner.getCurrentTokenStartPosition()); + // current.add(temp); + // getNextToken(); + // + // //skip fTokens for classname, extends and others until we have the opening '{' + // while (fToken != TokenNameLBRACE && fToken != TokenNameEOF && fToken != TokenNameERROR) { + // getNextToken(); + // } + // parseDeclarations(outlineInfo, temp, true); + // // stack.pop(); + // } + } else if (fToken == TokenNameStringLiteral) { + char currentCharacter; + int i = fScanner.startPosition; + ArrayList varList = new ArrayList(); + + while (i < fScanner.currentPosition) { + currentCharacter = fScanner.source[i++]; + if (currentCharacter == '$' && fScanner.source[i - 2] != '\\') { + StringBuffer varName = new StringBuffer(); + varName.append("$"); + while (i < fScanner.currentPosition) { + currentCharacter = fScanner.source[i++]; + if (!Scanner.isPHPIdentifierPart(currentCharacter)) { + break; // while loop + } + varName.append(currentCharacter); + } + varList.add(varName.toString()); + } + } + + for (i = 0; i < varList.size(); i++) { + identifier = (String) varList.get(i); + value = (PHPIdentifier) fIdentifierMap.get(identifier); + if (value == null) { + fIdentifierMap.put(identifier, new PHPIdentifier(null, PHPIdentifier.VARIABLE)); + } + } + + getNextToken(); + } else if ((fToken == TokenNameLBRACE) || (fToken == TokenNameDOLLAR_LBRACE)) { + getNextToken(); + counter++; + } else if (fToken == TokenNameRBRACE) { + getNextToken(); + --counter; + if (counter == 0 && goBack) { + return; + } + } else { + getNextToken(); + } + } + } catch (SyntaxError sytaxErr) { + // do nothing + } + } + /** + * Move one file. + * @param sourceFile the file to move + * @param targetDir the directory to copy the result to + * @return file or null if the file was ignored + */ + public File move(File sourceFile, File targetDir) { + + StringBuffer buf = new StringBuffer(); + + try { + long filelen = sourceFile.length(); + char[] charArray = new char[(int) filelen]; + + BufferedReader br = new BufferedReader(new FileReader(sourceFile.getAbsolutePath())); + br.read(charArray, 0, (int) filelen); + br.close(); + + // String input = buf.toString(); + /* fScanner initialization */ + fScanner.setSource(charArray); + fScanner.setPHPMode(false); + fToken = TokenNameEOF; + getNextToken(); + parseIdentifiers(false); + return null; + } catch (IOException e) { + fConsole.write(e.toString()); + } + return null; + } +} \ No newline at end of file diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpeclipse/mover/obfuscator/PHPIdentifier.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpeclipse/mover/obfuscator/PHPIdentifier.java new file mode 100644 index 0000000..1f391dd --- /dev/null +++ b/net.sourceforge.phpeclipse/src/net/sourceforge/phpeclipse/mover/obfuscator/PHPIdentifier.java @@ -0,0 +1,53 @@ +package net.sourceforge.phpeclipse.mover.obfuscator; + +/** + * @author khartlage + * + * To change this generated comment edit the template variable "typecomment": + * Window>Preferences>Java>Templates. + * To enable and disable the creation of type comments go to + * Window>Preferences>Java>Code Generation. + */ +public class PHPIdentifier { + + public final static int CLASS = 1; + public final static int FUNCTION = 2; + public final static int VARIABLE = 3; + + private int fType; + private String fIdentifier; + + public PHPIdentifier(String identifier, int type) { + fType = type; + fIdentifier = identifier; + } + + public boolean isClass() { + return fType == CLASS; + } + + public boolean isFuncton() { + return fType == FUNCTION; + } + + public boolean isVariable() { + return fType == VARIABLE; + } + + public void setType(int fType) { + this.fType = fType; + } + + public int getType() { + return fType; + } + + public void setIdentifier(String fIdentifier) { + this.fIdentifier = fIdentifier; + } + + public String getIdentifier() { + return fIdentifier; + } + +} diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpeclipse/mover/obfuscator/PHPObfuscatorMover.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpeclipse/mover/obfuscator/PHPObfuscatorMover.java new file mode 100644 index 0000000..19c439b --- /dev/null +++ b/net.sourceforge.phpeclipse/src/net/sourceforge/phpeclipse/mover/obfuscator/PHPObfuscatorMover.java @@ -0,0 +1,327 @@ +package net.sourceforge.phpeclipse.mover.obfuscator; + +import java.io.BufferedReader; +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.FileReader; +import java.io.FileWriter; +import java.io.IOException; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.util.ArrayList; +import java.util.HashMap; + +import net.sourceforge.phpdt.core.compiler.ITerminalSymbols; +import net.sourceforge.phpdt.core.compiler.InvalidInputException; +import net.sourceforge.phpdt.internal.compiler.parser.Scanner; +import net.sourceforge.phpdt.internal.compiler.parser.SyntaxError; +import net.sourceforge.phpeclipse.PHPeclipsePlugin; +import net.sourceforge.phpeclipse.mover.DefaultMover; +import net.sourceforge.phpeclipse.views.PHPConsole; + +import org.eclipse.jface.preference.IPreferenceStore; + +/** + * Obfuscate the file with the PHP Scanner + */ +public class PHPObfuscatorMover extends DefaultMover implements ITerminalSymbols { + + private Scanner fScanner; + private int fToken; + private MessageDigest fAlgorithm; + private int fCounter; + + protected HashMap fIdentifierMap; + + /** + * buffer, for obvious reasons access to this buffer must + * be synchronized + */ + protected byte[] bytes = new byte[1024]; + /** + * Creates a PHPAnalyzer + * @param console reports error to the PHPConsole + */ + public PHPObfuscatorMover(PHPConsole console, Scanner scanner, HashMap identifierMap) { + super(console); + this.fScanner = scanner; + this.fIdentifierMap = identifierMap; + this.fCounter = 0; + try { + this.fAlgorithm = MessageDigest.getInstance("MD5"); + } catch (NoSuchAlgorithmException e) { + System.out.println(e.toString()); + } + } + + /** + * Return the name the file would have after moving. In this case, + * it's left unchanged. + * @param file file the mover would have to move + * @return the extension it would give the file in the target directory + */ + public String getTargetName(File file) { + return file.getName(); + } + + /** + * gets the next token from input + */ + private void getNextToken() { + + try { + fToken = fScanner.getNextToken(); + if (Scanner.DEBUG) { + int currentEndPosition = fScanner.getCurrentTokenEndPosition(); + int currentStartPosition = fScanner.getCurrentTokenStartPosition(); + + System.out.print(currentStartPosition + "," + currentEndPosition + ": "); + System.out.println(fScanner.toStringAction(fToken)); + } + return; + } catch (InvalidInputException e) { + + } + fToken = TokenNameERROR; + } + + private boolean obfuscate(StringBuffer buf) { + char[] ident; + String identifier; + PHPIdentifier value; + + int startPosition = 0; + int lastPosition = 0; + + IPreferenceStore store = PHPeclipsePlugin.getDefault().getPreferenceStore(); + try { + while (fToken != TokenNameEOF && fToken != TokenNameERROR) { + if (fToken == TokenNameVariable) { + identifier = new String(fScanner.getCurrentIdentifierSource()); + lastPosition = fScanner.startPosition; + int len = lastPosition - startPosition; + buf.append(fScanner.source, startPosition, len); + value = (PHPIdentifier) fIdentifierMap.get(identifier); + if (value != null) { + String obfuscatedIdentifier = value.getIdentifier(); + if (obfuscatedIdentifier == null) { + buf.append("$v" + Integer.toString(fCounter)); + value.setIdentifier("$v" + Integer.toString(fCounter++)); + } else { + buf.append(obfuscatedIdentifier); + } + // System.out.println(hexString.toString()); + } else { + buf.append(identifier); + } + startPosition = fScanner.currentPosition; + getNextToken(); + } else if (fToken == TokenNameIdentifier) { + identifier = new String(fScanner.getCurrentIdentifierSource()); + lastPosition = fScanner.startPosition; + int len = lastPosition - startPosition; + buf.append(fScanner.source, startPosition, len); + value = (PHPIdentifier) fIdentifierMap.get(identifier); + if (value != null) { + String obfuscatedIdentifier = value.getIdentifier(); + if (obfuscatedIdentifier == null) { + buf.append("_" + Integer.toString(fCounter)); + value.setIdentifier("_" + Integer.toString(fCounter++)); + } else { + buf.append(obfuscatedIdentifier); + } + // System.out.println(hexString.toString()); + } else { + buf.append(identifier); + } + startPosition = fScanner.currentPosition; + getNextToken(); + + } else if (fToken == TokenNameCOMMENT_LINE || fToken == TokenNameCOMMENT_BLOCK || fToken == TokenNameCOMMENT_PHPDOC) { + lastPosition = fScanner.startPosition; + buf.append(fScanner.source, startPosition, lastPosition - startPosition); + startPosition = fScanner.currentPosition; + getNextToken(); + } else if (fToken == TokenNameStringLiteral) { + char currentCharacter; + int i = fScanner.startPosition; + ArrayList varList = new ArrayList(); + + lastPosition = fScanner.startPosition; + int len = lastPosition - startPosition; + buf.append(fScanner.source, startPosition, len); + + while (i < fScanner.currentPosition) { + currentCharacter = fScanner.source[i++]; + if (currentCharacter == '$' && fScanner.source[i-2]!='\\') { + StringBuffer varName = new StringBuffer(); + varName.append("$"); + while (i < fScanner.currentPosition) { + currentCharacter = fScanner.source[i++]; + if (!Scanner.isPHPIdentifierPart(currentCharacter)) { + break; // while loop + } + varName.append(currentCharacter); + } + varList.add(varName.toString()); + } + } + StringBuffer stringLiteral = new StringBuffer(); + stringLiteral.append(fScanner.source, fScanner.startPosition, fScanner.currentPosition - fScanner.startPosition); + String stringIdent; + String replacement; + int index; + + for (int j = 0; j < varList.size(); j++) { + stringIdent = (String) varList.get(j); + len = stringIdent.length(); + value = (PHPIdentifier) fIdentifierMap.get(stringIdent); + if (value != null) { + String obfuscatedIdentifier = value.getIdentifier(); + if (obfuscatedIdentifier == null) { + replacement = "$v" + Integer.toString(fCounter); + value.setIdentifier("$v" + Integer.toString(fCounter++)); + } else { + replacement = obfuscatedIdentifier; + } + // System.out.println(hexString.toString()); + } else { + replacement = stringIdent; + } + index = stringLiteral.indexOf(stringIdent); + if (index >= 0) { + if (index > 0 && stringLiteral.charAt(index-1)!='\\') { + stringLiteral.replace(index, index + stringIdent.length(), replacement); + } else if (index==0) { + stringLiteral.replace(index, index + stringIdent.length(), replacement); + } + } + } + buf.append(stringLiteral); + startPosition = fScanner.currentPosition; + getNextToken(); + } + if (fToken == TokenNameMINUS_GREATER) { // i.e. $this->var_name + getNextToken(); + if (fToken == TokenNameIdentifier) { + // assuming this is a dereferenced variable + identifier = new String(fScanner.getCurrentIdentifierSource()); + lastPosition = fScanner.startPosition; + int len = lastPosition - startPosition; + buf.append(fScanner.source, startPosition, len); + value = (PHPIdentifier) fIdentifierMap.get("$" + identifier); + if (value != null && value.isVariable()) { + String obfuscatedIdentifier = value.getIdentifier(); + if (obfuscatedIdentifier == null) { + // note: don't place a $ before the identifier + buf.append("v" + Integer.toString(fCounter)); + value.setIdentifier("$v" + Integer.toString(fCounter++)); + } else { + if (obfuscatedIdentifier.charAt(0) == '$') { + buf.append(obfuscatedIdentifier.substring(1)); + } else { + buf.append(obfuscatedIdentifier); + } + } + } else { + buf.append(identifier); + } + startPosition = fScanner.currentPosition; + getNextToken(); + } + + } else { + getNextToken(); + } + } + if (startPosition < fScanner.source.length) { + buf.append(fScanner.source, startPosition, fScanner.source.length - startPosition); + } + return true; + } catch (SyntaxError sytaxErr) { + // do nothing + } + + return false; + } + + public File copy(File sourceFile, File targetDir) { + try { + File targetFile = new File(targetDir, getTargetName(sourceFile)); + // if (targetFile.exists()) + // if (targetFile.lastModified() >= sourceFile.lastModified()) + // return null; + synchronized (bytes) { + FileInputStream in = new FileInputStream(sourceFile); + FileOutputStream out = new FileOutputStream(targetFile); + for (int len = in.read(bytes); len != -1; len = in.read(bytes)) { + out.write(bytes, 0, len); + } + in.close(); + out.close(); + } + return targetFile; + } catch (IOException e) { + fConsole.write(e.toString()); + } + return null; + } + + /** + * Move one file. + * @param sourceFile the file to move + * @param targetDir the directory to copy the result to + * @return file or null if the file was ignored + */ + public File move(File sourceFile, File targetDir) { + + try { + + String fileName = sourceFile.getAbsolutePath().toLowerCase(); + if (fileName.endsWith(".php") + || fileName.endsWith(".php3") + || fileName.endsWith(".php4") + || fileName.endsWith(".phtml") + || fileName.endsWith(".inc")) { + StringBuffer buf = new StringBuffer(); + long filelen = sourceFile.length(); + char[] charArray = new char[(int) filelen]; + + BufferedReader br = new BufferedReader(new FileReader(sourceFile.getAbsolutePath())); + br.read(charArray, 0, (int) filelen); + + // int offset = 0; + // String line; + // while ((line = br.readLine()) != null) { + // System.arraycopy(line.toCharArray(), 0, charArray, offset, line.length()); + // offset += line.length(); + // } + br.close(); + + fScanner.setSource(charArray); + fScanner.setPHPMode(false); + fToken = TokenNameEOF; + getNextToken(); + buf = new StringBuffer(); + if (!obfuscate(buf)) { + return copy(sourceFile, targetDir); + } else { + File targetFile = new File(targetDir, getTargetName(sourceFile)); + BufferedWriter bw = new BufferedWriter(new FileWriter(targetFile)); + bw.write(buf.toString()); + bw.close(); + return targetFile; + } + + } else { + return copy(sourceFile, targetDir); + } + + } catch (IOException e) { + fConsole.write(e.toString()); + } + return null; + } +} \ No newline at end of file diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpeclipse/newPHPPreferencesMessages_DE.properties b/net.sourceforge.phpeclipse/src/net/sourceforge/phpeclipse/newPHPPreferencesMessages_DE.properties index c24da8c..d12ef41 100644 --- a/net.sourceforge.phpeclipse/src/net/sourceforge/phpeclipse/newPHPPreferencesMessages_DE.properties +++ b/net.sourceforge.phpeclipse/src/net/sourceforge/phpeclipse/newPHPPreferencesMessages_DE.properties @@ -15,6 +15,12 @@ PHPProjectPropertyPage.phpProjectClosed=Das ausgew PHPProjectPropertyPage.performOkExceptionDialogTitle=Kann nicht sichern PHPProjectPropertyPage.performOkExceptionDialogMessage=FEHLER: Kann die Projekt Eigenschaften nicht sichern +PHPObfuscatorPropertyPage.hasnature=PHP Projekt. +PHPObfuscatorPropertyPage.publish=Obfuscator Ausgabe Verzeichnis: +PHPObfuscatorPropertyPage.dialogtitle=PHP +PHPObfuscatorPropertyPage.projecterror=Kann das neue Projekt nicht anlegen. +PHPObfuscatorPropertyPage.properties=PHP Obfuscator Projekt Eigenschaften + ######################################### # Preference Pages ######################################### diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpeclipse/newPHPPreferencesMessages_FR.properties b/net.sourceforge.phpeclipse/src/net/sourceforge/phpeclipse/newPHPPreferencesMessages_FR.properties index 84ddaa1..856e04d 100644 --- a/net.sourceforge.phpeclipse/src/net/sourceforge/phpeclipse/newPHPPreferencesMessages_FR.properties +++ b/net.sourceforge.phpeclipse/src/net/sourceforge/phpeclipse/newPHPPreferencesMessages_FR.properties @@ -15,6 +15,12 @@ PHPProjectPropertyPage.phpProjectClosed=Le project choisi est un projet PHP, mai PHPProjectPropertyPage.performOkExceptionDialogTitle=Impossible de sauver PHPProjectPropertyPage.performOkExceptionDialogMessage=ERREUR: Impossible de sauver les propriétés du projet. +PHPObfuscatorPropertyPage.hasnature=Is PHP project. +PHPObfuscatorPropertyPage.publish=Obfuscator directory: +PHPObfuscatorPropertyPage.dialogtitle=PHP +PHPObfuscatorPropertyPage.projecterror=Could not create the new project. +PHPObfuscatorPropertyPage.properties=PHP Obfuscator Project Properties + ######################################### # Preference Pages ######################################### diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpeclipse/newPHPPreferencesMessages_en_GB.properties b/net.sourceforge.phpeclipse/src/net/sourceforge/phpeclipse/newPHPPreferencesMessages_en_GB.properties index 8372e22..65c5974 100644 --- a/net.sourceforge.phpeclipse/src/net/sourceforge/phpeclipse/newPHPPreferencesMessages_en_GB.properties +++ b/net.sourceforge.phpeclipse/src/net/sourceforge/phpeclipse/newPHPPreferencesMessages_en_GB.properties @@ -15,6 +15,12 @@ PHPProjectPropertyPage.phpProjectClosed=The project selected is a PHP project, b PHPProjectPropertyPage.performOkExceptionDialogTitle=Unable to save PHPProjectPropertyPage.performOkExceptionDialogMessage=ERROR: Unable to save project properties. +PHPObfuscatorPropertyPage.hasnature=Is PHP project. +PHPObfuscatorPropertyPage.publish=Obfuscator directory: +PHPObfuscatorPropertyPage.dialogtitle=PHP +PHPObfuscatorPropertyPage.projecterror=Could not create the new project. +PHPObfuscatorPropertyPage.properties=PHP Obfuscator Project Properties + ######################################### # Preference Pages ######################################### diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpeclipse/newPHPPreferencesMessages_es_ES.properties b/net.sourceforge.phpeclipse/src/net/sourceforge/phpeclipse/newPHPPreferencesMessages_es_ES.properties index 63beb7a..41442c0 100644 --- a/net.sourceforge.phpeclipse/src/net/sourceforge/phpeclipse/newPHPPreferencesMessages_es_ES.properties +++ b/net.sourceforge.phpeclipse/src/net/sourceforge/phpeclipse/newPHPPreferencesMessages_es_ES.properties @@ -15,6 +15,12 @@ PHPProjectPropertyPage.phpProjectClosed=El proyecto seleccionado es un proyecto PHPProjectPropertyPage.performOkExceptionDialogTitle=No se pudo guardar. PHPProjectPropertyPage.performOkExceptionDialogMessage=ERROR: No se pudo guardar las propiedades del proyecto. +PHPObfuscatorPropertyPage.hasnature=Is PHP project. +PHPObfuscatorPropertyPage.publish=Obfuscator directory: +PHPObfuscatorPropertyPage.dialogtitle=PHP +PHPObfuscatorPropertyPage.projecterror=Could not create the new project. +PHPObfuscatorPropertyPage.properties=PHP Obfuscator Project Properties + ######################################### # Preference Pages ######################################### diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpeclipse/phpeditor/php/PHPPartitionScanner.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpeclipse/phpeditor/php/PHPPartitionScanner.java index 072f30b..52f8def 100644 --- a/net.sourceforge.phpeclipse/src/net/sourceforge/phpeclipse/phpeditor/php/PHPPartitionScanner.java +++ b/net.sourceforge.phpeclipse/src/net/sourceforge/phpeclipse/phpeditor/php/PHPPartitionScanner.java @@ -6,14 +6,23 @@ * Created on 05.03.2003 * * @author Stefan Langer (musk) - * @version $Revision: 1.18 $ + * @version $Revision: 1.19 $ */ package net.sourceforge.phpeclipse.phpeditor.php; -import java.util.*; -import org.eclipse.jface.text.*; -import org.eclipse.jface.text.rules.*; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Map; + +import org.eclipse.jface.text.Assert; +import org.eclipse.jface.text.BadLocationException; +import org.eclipse.jface.text.IDocument; +import org.eclipse.jface.text.ITypedRegion; +import org.eclipse.jface.text.rules.ICharacterScanner; +import org.eclipse.jface.text.rules.IPartitionTokenScanner; +import org.eclipse.jface.text.rules.IToken; +import org.eclipse.jface.text.rules.Token; /** * diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpeclipse/preferences/IObfuscatorPreferences.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpeclipse/preferences/IObfuscatorPreferences.java new file mode 100644 index 0000000..49b22f1 --- /dev/null +++ b/net.sourceforge.phpeclipse/src/net/sourceforge/phpeclipse/preferences/IObfuscatorPreferences.java @@ -0,0 +1,32 @@ +package net.sourceforge.phpeclipse.preferences; + +import org.eclipse.core.runtime.QualifiedName; + +/** + * constnats for project preferences + */ +public interface IObfuscatorPreferences { + + /** + * namespace URI for the properties + */ + public static final String PROPERTY_NAMESPACE = "http://phpeclipse.org"; + + /** + * property local name for the publish directory + */ + public static final String PUBLISH_PROPERTY = "publish"; + + /** + * property qualified name for the publish directory + */ + public static final QualifiedName PUBLISH_PROPERTY_NAME = + new QualifiedName(PROPERTY_NAMESPACE,PUBLISH_PROPERTY); + + /** + * default value for the publish directory name + */ + public static final String DEFAULT_PUBLISH_DIR = "c:\\temp"; + + +} \ No newline at end of file diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpeclipse/preferences/PHPObfuscatorPropertyPage.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpeclipse/preferences/PHPObfuscatorPropertyPage.java new file mode 100644 index 0000000..3397ab3 --- /dev/null +++ b/net.sourceforge.phpeclipse/src/net/sourceforge/phpeclipse/preferences/PHPObfuscatorPropertyPage.java @@ -0,0 +1,163 @@ +package net.sourceforge.phpeclipse.preferences; + +import net.sourceforge.phpeclipse.PHPeclipsePlugin; + +import org.eclipse.core.resources.IProject; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IAdaptable; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; +import org.eclipse.jface.dialogs.ErrorDialog; +import org.eclipse.swt.SWT; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.layout.RowLayout; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Group; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Text; +import org.eclipse.ui.PlatformUI; +import org.eclipse.ui.dialogs.PropertyPage; + +/** + * + * This page will be added to the project's property page dialog when the "Properties..." popup menu item is selected + */ +public class PHPObfuscatorPropertyPage + extends PropertyPage + implements IObfuscatorPreferences +{ + private Text publishText; +// private Button hasNature, +// isBuild; + private Group group; + private ProjectProperties properties; + + private Control buildUI(Composite parent) + { + Composite composite = new Composite(parent,SWT.NULL); + RowLayout rowLayout = new RowLayout(); + rowLayout.type = SWT.VERTICAL; + rowLayout.wrap = false; + composite.setLayout(rowLayout); +// hasNature = new Button(composite,SWT.CHECK); +// hasNature.setText(PHPPreferencesMessages.getString("PHPObfuscatorPropertyPage.hasnature")); +// hasNature.addSelectionListener(new SelectionListener() +// { +// public void widgetDefaultSelected(SelectionEvent e) +// { +// group.setEnabled(hasNature.getSelection()); +// } +// +// public void widgetSelected(SelectionEvent e) +// { +// group.setEnabled(hasNature.getSelection()); +// } +// }); + group = new Group(composite,SWT.NONE); + group.setText(PHPPreferencesMessages.getString("PHPObfuscatorPropertyPage.properties")); + GridLayout gridLayout = new GridLayout(); + gridLayout.numColumns = 2; + group.setLayout(gridLayout); + + Label label = new Label(group,SWT.RIGHT); + label.setText(PHPPreferencesMessages.getString("PHPObfuscatorPropertyPage.publish")); + publishText = new Text(group,SWT.LEFT); + publishText.setLayoutData(new GridData(GridData.FILL_HORIZONTAL | GridData.GRAB_HORIZONTAL)); + return composite; + } + + public void readProperties() + throws CoreException + { + publishText.setText(properties.getPublish()); +// hasNature.setSelection(properties.hasNature()); +// group.setEnabled(hasNature.getSelection()); + group.setEnabled(true); + } + + public void writeProperties() + throws CoreException + { + // properties.setNature(hasNature.getSelection()); + properties.setPublish(publishText.getText()); + } + + public Control createContents(Composite parent) + { + Control control = buildUI(parent); + try + { + IAdaptable adaptable = getElement(); + if(adaptable instanceof IProject) + { + properties = new ProjectProperties((IProject)adaptable); + readProperties(); + } + } + catch(CoreException x) + { + ErrorDialog.openError(PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell(), + PHPPreferencesMessages.getString("PHPObfuscatorPropertyPage.dialogtitle"), + PHPPreferencesMessages.getString("PHPObfuscatorPropertyPage.propertyerror"), + makeStatus(x)); + } + return control; + } + + public boolean performOk() + { + try + { + writeProperties(); + } + catch(CoreException x) + { + ErrorDialog.openError(PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell(), + PHPPreferencesMessages.getString("PHPObfuscatorPropertyPage.dialogtitle"), + PHPPreferencesMessages.getString("PHPObfuscatorPropertyPage.propertyerror"), + makeStatus(x)); + } + return super.performOk(); + } + + public void performApply() + { + try + { + writeProperties(); + } + catch(CoreException x) + { + ErrorDialog.openError(PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell(), + PHPPreferencesMessages.getString("PHPObfuscatorPropertyPage.dialogtitle"), + PHPPreferencesMessages.getString("PHPObfuscatorPropertyPage.propertyerror"), + makeStatus(x)); + } + super.performApply(); + } + /** + * Create an IStatus object from an exception. + * @param x exception to process + * @return IStatus status object for the above exception + */ + public static IStatus makeStatus(Exception x) + { +// Throwable t = popThrowables(x); +// if(t instanceof CoreException) +// return ((CoreException)t).getStatus(); +// else + return new Status(IStatus.ERROR, + PHPeclipsePlugin.PLUGIN_ID, + IStatus.ERROR, + x.getMessage(), + x); + } + public void performDefaults() + { + // hasNature.setSelection(true); + publishText.setText(DEFAULT_PUBLISH_DIR); + super.performDefaults(); + } +} \ No newline at end of file diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpeclipse/preferences/PHPPreferencesMessages.properties b/net.sourceforge.phpeclipse/src/net/sourceforge/phpeclipse/preferences/PHPPreferencesMessages.properties index 2b558f0..058c0da 100644 --- a/net.sourceforge.phpeclipse/src/net/sourceforge/phpeclipse/preferences/PHPPreferencesMessages.properties +++ b/net.sourceforge.phpeclipse/src/net/sourceforge/phpeclipse/preferences/PHPPreferencesMessages.properties @@ -15,4 +15,3 @@ PHPProjectPropertyPage.phpProjectClosed=The project selected is a PHP project, b PHPProjectPropertyPage.performOkExceptionDialogTitle=Unable to save PHPProjectPropertyPage.performOkExceptionDialogMessage=ERROR: Unable to save project properties. - diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpeclipse/preferences/ProjectProperties.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpeclipse/preferences/ProjectProperties.java new file mode 100644 index 0000000..68761fe --- /dev/null +++ b/net.sourceforge.phpeclipse/src/net/sourceforge/phpeclipse/preferences/ProjectProperties.java @@ -0,0 +1,102 @@ +package net.sourceforge.phpeclipse.preferences; + +import net.sourceforge.phpeclipse.PHPeclipsePlugin; + +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.IProjectDescription; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.NullProgressMonitor; +import org.eclipse.core.runtime.QualifiedName; + + +public class ProjectProperties + implements IObfuscatorPreferences +{ + private IProject project; + + // private static final String DEFAULT_BUILD = String.valueOf(DEFAULT_BUILD_VALUE); + + public ProjectProperties(IProject project) + { + this.project = project; + } + + + public String getPublish() + throws CoreException + { + return getProperty(PUBLISH_PROPERTY_NAME,DEFAULT_PUBLISH_DIR); + } + + public boolean hasNature() + throws CoreException + { + return project.hasNature(PHPeclipsePlugin.PHP_NATURE_ID); + } + + public void setPublish(String publish) + throws CoreException + { + setProperty(PUBLISH_PROPERTY_NAME,publish,DEFAULT_PUBLISH_DIR); + } + + + public void setNature(boolean nature) + throws CoreException + { + if(nature) + { + if(!hasNature()) + { + IProjectDescription description = project.getDescription(); + String[] old = description.getNatureIds(), + natures= new String[old.length + 1]; + System.arraycopy(old,0,natures,0,old.length); + natures[old.length] = PHPeclipsePlugin.PHP_NATURE_ID; + description.setNatureIds(natures); + project.setDescription(description,new NullProgressMonitor()); + } + } + else + { + if(hasNature()) + { + IProjectDescription description = project.getDescription(); + String[] old = description.getNatureIds(), + natures= new String[old.length - 1]; + int i = 0, + j = 0; + while(i < old.length) + { + if(!old[i].equals(PHPeclipsePlugin.PHP_NATURE_ID)) + natures[j++] = old[i]; + i++; + } + description.setNatureIds(natures); + project.setDescription(description,new NullProgressMonitor()); + } + } + } + + protected String getProperty(QualifiedName key,String def) + throws CoreException + { + String value = project.getPersistentProperty(key); + if(value == null || value.length() == 0) + return def; + else + return value; + } + + protected void setProperty(QualifiedName key,String value,String def) + throws CoreException + { + if(value != null && value.length() != 0 && hasNature()) + { + if(value.equals(def)) + project.setPersistentProperty(key,null); + else + project.setPersistentProperty(key,value); + } + } +} \ No newline at end of file