1 package org.cacert.gigi.localisation;
4 import java.io.IOException;
5 import java.lang.reflect.Method;
6 import java.util.Stack;
8 import org.eclipse.jdt.internal.compiler.ASTVisitor;
9 import org.eclipse.jdt.internal.compiler.ast.AllocationExpression;
10 import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration;
11 import org.eclipse.jdt.internal.compiler.ast.ConditionalExpression;
12 import org.eclipse.jdt.internal.compiler.ast.ConstructorDeclaration;
13 import org.eclipse.jdt.internal.compiler.ast.ExplicitConstructorCall;
14 import org.eclipse.jdt.internal.compiler.ast.Expression;
15 import org.eclipse.jdt.internal.compiler.ast.MessageSend;
16 import org.eclipse.jdt.internal.compiler.ast.MethodDeclaration;
17 import org.eclipse.jdt.internal.compiler.ast.NullLiteral;
18 import org.eclipse.jdt.internal.compiler.ast.QualifiedAllocationExpression;
19 import org.eclipse.jdt.internal.compiler.ast.StringLiteral;
20 import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
21 import org.eclipse.jdt.internal.compiler.lookup.ClassScope;
22 import org.eclipse.jdt.internal.compiler.lookup.MethodBinding;
23 import org.eclipse.jdt.internal.compiler.util.Util;
25 public final class TranslationCollectingVisitor extends ASTVisitor {
29 private CompilationUnitDeclaration unit;
33 private TranslationCollector translationCollector;
35 Stack<QualifiedAllocationExpression> anonymousConstructorCall = new Stack<>();
37 private boolean hadErrors = false;
39 public boolean hadErrors() {
43 public TranslationCollectingVisitor(CompilationUnitDeclaration unit, TaintSource[] target, TranslationCollector c) {
46 this.translationCollector = c;
50 public boolean visit(MethodDeclaration methodDeclaration, org.eclipse.jdt.internal.compiler.lookup.ClassScope scope) {
51 cm = methodDeclaration.binding;
56 public void endVisit(MethodDeclaration methodDeclaration, org.eclipse.jdt.internal.compiler.lookup.ClassScope scope) {
61 public boolean visit(ConstructorDeclaration constructorDeclaration, ClassScope scope) {
62 cm = constructorDeclaration.binding;
63 return super.visit(constructorDeclaration, scope);
67 public void endVisit(ConstructorDeclaration constructorDeclaration, ClassScope scope) {
72 public boolean visit(AllocationExpression allocationExpression, BlockScope scope) {
73 TaintSource test = new TaintSource(allocationExpression.binding);
74 for (TaintSource taintSource : ts) {
75 if (taintSource.equals(test)) {
76 check(null, scope, allocationExpression.arguments[taintSource.getTgt()], allocationExpression.toString());
80 return super.visit(allocationExpression, scope);
84 public boolean visit(QualifiedAllocationExpression qualifiedAllocationExpression, BlockScope scope) {
85 anonymousConstructorCall.push(qualifiedAllocationExpression);
86 return super.visit(qualifiedAllocationExpression, scope);
90 public void endVisit(QualifiedAllocationExpression qualifiedAllocationExpression, BlockScope scope) {
91 if (anonymousConstructorCall.pop() != qualifiedAllocationExpression) {
92 throw new Error("stack illegally manipulated");
97 public boolean visit(ExplicitConstructorCall explicitConstructor, BlockScope scope) {
99 TaintSource t = new TaintSource(explicitConstructor.binding);
101 for (TaintSource t0 : ts) {
103 Expression[] ags = explicitConstructor.arguments;
104 if (anonymousConstructorCall.size() > 0) {
105 ags = anonymousConstructorCall.peek().arguments;
108 System.err.println(explicitConstructor);
111 Expression e = ags[t0.getTgt()];
112 check(null, scope, e, explicitConstructor.toString());
116 return super.visit(explicitConstructor, scope);
120 public boolean visit(org.eclipse.jdt.internal.compiler.ast.MessageSend call, org.eclipse.jdt.internal.compiler.lookup.BlockScope scope) {
121 if (call.binding == null) {
122 System.err.println("Unbound:" + call + " in " + call.sourceStart());
125 // System.out.println("Message");
126 TaintSource t = new TaintSource(call.binding);
128 for (TaintSource t0 : ts) {
130 Expression[] ags = call.arguments;
132 System.err.println(call);
135 Expression e = ags[t0.getTgt()];
136 check(call, scope, e, call.toString());
143 private void check(org.eclipse.jdt.internal.compiler.ast.MessageSend call, org.eclipse.jdt.internal.compiler.lookup.BlockScope scope, Expression e, String caller) {
144 if (e instanceof StringLiteral) {
145 int[] lineEnds = null;
146 int lineNumber = Util.getLineNumber(e.sourceStart, lineEnds = unit.compilationResult.getLineSeparatorPositions(), 0, lineEnds.length - 1);
148 String content = new String(((StringLiteral) e).source());
149 File f0 = new File(new String(unit.compilationResult.fileName)).getAbsoluteFile();
150 File f2 = translationCollector.base.getAbsoluteFile();
152 translationCollector.add(content, f0.getCanonicalPath().substring(f2.getCanonicalPath().length() + 1) + ":" + lineNumber);
153 } catch (IOException e1) {
154 e1.printStackTrace();
159 if (e instanceof NullLiteral) {
163 if (e instanceof MessageSend) {
164 MessageSend m2 = (MessageSend) e;
165 TaintSource ts = new TaintSource(m2.binding);
166 if (ts.equals(new TaintSource("org.cacert.gigi.pages", "Page", "getTitle()", 0))) {
169 if (m2.receiver.resolvedType.isCompatibleWith(scope.getJavaLangEnum())) {
170 testEnum(m2.receiver, m2.binding);
171 System.err.println("ENUM-SRC: !" + m2.receiver);
174 if (e.resolvedType.isCompatibleWith(scope.getJavaLangEnum())) {
176 System.err.println("ENUM-Not-Hanled");
179 TaintSource b = cm == null ? null : new TaintSource(cm);
180 for (TaintSource taintSource : ts) {
181 if (taintSource.equals(b) || (taintSource.getMaskOnly() != null && taintSource.getMaskOnly().equals(b))) {
185 if (e instanceof ConditionalExpression) {
186 check(call, scope, ((ConditionalExpression) e).valueIfFalse, caller);
187 check(call, scope, ((ConditionalExpression) e).valueIfTrue, caller);
191 System.err.println();
193 System.err.println(new String(scope.enclosingClassScope().referenceType().compilationResult.fileName));
194 System.err.println("Cannot Handle: " + e + " in " + (call == null ? "constructor" : call.sourceStart) + " => " + caller);
195 System.err.println(e.getClass());
196 System.err.println("To ignore: " + (b == null ? "don't know" : b.toConfLine()));
200 private void testEnum(Expression e, MethodBinding binding) {
201 if (binding.parameters.length != 0) {
202 System.err.println("ERROR: meth");
205 System.err.println(e.resolvedType.getClass());
206 String s2 = new String(e.resolvedType.qualifiedPackageName()) + "." + (new String(e.resolvedType.qualifiedSourceName()).replace('.', '$'));
208 Class<?> c = Class.forName(s2);
209 Enum<?>[] e1 = (Enum[]) c.getMethod("values").invoke(null);
210 Method m = c.getMethod(new String(binding.selector));
211 for (int j = 0; j < e1.length; j++) {
212 System.err.println(m.invoke(e1[j]));
214 } catch (ClassNotFoundException e1) {
215 e1.printStackTrace();
216 } catch (ReflectiveOperationException e1) {
217 e1.printStackTrace();
219 System.err.println("ENUM-done: " + e + "!");