Package lapsePlus.views

Source Code of lapsePlus.views.SinkView$StatisticsManager

package lapsePlus.views;

/*
* SinkView.java,version 2.8, 2010
*/

import java.io.BufferedReader;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringReader;
import java.io.StringWriter;
import java.text.Collator;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.Locale;
import java.util.Vector;
import lapsePlus.CallerFinder;
import lapsePlus.LapsePlugin;
import lapsePlus.Utils;
import lapsePlus.XMLConfig;
import lapsePlus.XMLConfig.SinkDescription;
import lapsePlus.views.LapseView.SlicingFromSinkJob;

import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.jdt.core.IJavaModel;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.IMember;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.core.dom.ASTNode;
import org.eclipse.jdt.core.dom.ClassInstanceCreation;
import org.eclipse.jdt.core.dom.CompilationUnit;
import org.eclipse.jdt.core.dom.Expression;
import org.eclipse.jdt.core.dom.InfixExpression;
import org.eclipse.jdt.core.dom.MethodInvocation;
import org.eclipse.jdt.core.dom.SimpleName;
import org.eclipse.jdt.core.dom.SingleVariableDeclaration;
import org.eclipse.jdt.core.dom.StringLiteral;
import org.eclipse.jdt.core.dom.VariableDeclaration;
import org.eclipse.jdt.core.dom.VariableDeclarationFragment;
import org.eclipse.jdt.internal.core.JavaModelManager;
import org.eclipse.jdt.internal.ui.JavaPluginImages;
import org.eclipse.jdt.internal.ui.javaeditor.EditorUtility;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.action.IMenuListener;
import org.eclipse.jface.action.IMenuManager;
import org.eclipse.jface.action.IStatusLineManager;
import org.eclipse.jface.action.IToolBarManager;
import org.eclipse.jface.action.MenuManager;
import org.eclipse.jface.action.Separator;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.jface.resource.JFaceResources;
import org.eclipse.jface.util.Assert;
import org.eclipse.jface.viewers.ColumnLayoutData;
import org.eclipse.jface.viewers.ColumnPixelData;
import org.eclipse.jface.viewers.ColumnWeightData;
import org.eclipse.jface.viewers.DoubleClickEvent;
import org.eclipse.jface.viewers.IColorProvider;
import org.eclipse.jface.viewers.IDoubleClickListener;
import org.eclipse.jface.viewers.IFontProvider;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.IStructuredContentProvider;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.ITableLabelProvider;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.TableLayout;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.jface.viewers.ViewerFilter;
import org.eclipse.jface.viewers.ViewerSorter;
import org.eclipse.swt.SWT;
import org.eclipse.swt.SWTError;
import org.eclipse.swt.dnd.Clipboard;
import org.eclipse.swt.dnd.DND;
import org.eclipse.swt.dnd.TextTransfer;
import org.eclipse.swt.dnd.Transfer;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.swt.widgets.TableItem;
import org.eclipse.ui.IActionBars;
import org.eclipse.ui.IWorkbenchActionConstants;
import org.eclipse.ui.IWorkbenchPartSite;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.part.ViewPart;
import org.eclipse.ui.texteditor.ITextEditor;

public class SinkView extends ViewPart {
 
 
    static final String MARKER_ID = "lapse.SQLMarker";
    private static final int MESSAGE_FIELD = 0;
    private static final int TYPE_FIELD = 1;
    private static final int CATEGORY_FIELD = 2;
    private static final int PROJECT_FIELD = 3;
    private static final int FILE_FIELD = 4;
    private static final int LINE_FIELD = 5;
   
    /**
     * This corresponds to a particular match.
     */
    class ViewMatch {
        private String message;
        private ASTNode ast;
        private CompilationUnit unit;
        private IResource resource;
        private String type;
        private IMember member;
        private boolean error = false;
        private boolean done = false;
        private boolean safe = false;
        private boolean hasSource = true;
        private String category;

        ViewMatch(String message, ASTNode ast, CompilationUnit unit, IResource resource,
            String type, IMember member, String category, boolean error, boolean hasSource) {
            this.message = message;
            this.ast = ast;
            this.unit = unit;
            this.resource = resource;
            this.type = type;
            this.member = member;
            this.category = category;
            this.error = error;
            this.hasSource = hasSource;
        }

        public String toString() {
            return message;
        }

        public String getMessage() {
            return message;
        }

        public String getType() {
            return type;
        }

        public CompilationUnit getUnit() {
            return unit;
        }

        public IResource getResource() {
            return resource;
        }

        public ASTNode getAST() {
            return ast;
        }

        public IMember getMember() {
            return member;
        }

        public String getCategory() {
            return category;
        }

        public boolean isSource() {
            return unit != null;
        }

        public int getLineNumber() {
            return isSource() ? unit.getLineNumber(ast.getStartPosition()) : -1;
        }

        public String getFullFileName() {
            return resource.getFullPath().toString();
        }

        public String getFileName() {
            return resource.getName();
        }

        public IProject getProject() {
            return resource.getProject();
        }

        public boolean isError() {
            return error;
        }

        public boolean hasSource() {
            return hasSource;
        }

        public String toLongString() {
            return getStatusSymbol() + " " + cutto(this.getAST().toString(), 65) + "\t"
                + cutto(this.getType(), 40) + "\t"
                + cutto(this.getProject().getProject().getName(), 20) + "\t"
                + this.getResource().getFullPath().toString() + ":" + this.getLineNumber();
        }

        private String getStatusSymbol() {
            if (!isError()) {
                return "SAFE   ";
            } else if (isSafe()) {
                return "M-SAFE ";
            } else if (isDone()) {
                return "M-ERROR";
            } else {
                return "UNKNOWN";
            }
        }

        public void setDone(boolean b) {
            this.done = b;
        }

        public boolean isDone() {
            return this.done;
        }

        public boolean isSafe() {
            return this.safe;
        }

        public void setSafe(boolean b) {
            this.safe = b;
        }

        public boolean getSafe() {
            return this.safe;
        }
    }
    static TableViewer viewer;
    private Action
        runAction,
        doubleClickAction,
        doBackwardPropagationAction,
        hideSafeAction;
    private Action
        hideNoSourceAction,
        statAction,
        showSQLAction,
        showXSSAction,
        showPTAction,
        setSafeAction,
        copyToClipboardAction,
        showHttpResponseAction,
        showCommandInjectionAction,
        showLDAPAction,
        showXPathAction;
    private Clipboard fClipboard;
    private StatisticsManager statisticsManager = new StatisticsManager();
   
    class StatisticsManager {
     
        private Collection<ViewMatch> matches = new LinkedList<ViewMatch>();
        HashMap<String, Integer> map = new HashMap<String, Integer>();
        private HashMap<String, Boolean> categories = new HashMap<String, Boolean>();

        public void add(ViewMatch match) {
            matches.add(match);
        }

        public void gatherStatistics() {
            if (map.size() > 0) matches.clear(); // clear the map
           
            for (Iterator iter = matches.iterator(); iter.hasNext();) {
             
                ViewMatch match = (ViewMatch) iter.next();
               
                inc("total.all");
               
                if (match.isError()) inc("unsafe.all");
               
                if (match.hasSource() && match.isError()) inc("source+unsafe.all");
               
                inc("total." + match.getCategory());
               
                if (match.isError()) inc("unsafe." + match.getCategory());
               
                if (match.isError() && match.hasSource) inc("source+unsafe." + match.getCategory());
               
                categories.put(match.getCategory(), null);
               
                if (match.hasSource()) inc("source.all");
            }
        }

        public void printStatistics() {
            System.out.println(getStatistics());
        }

        public String getStatistics() {
            if (map.size() == 0) gatherStatistics();
            StringBuffer result = new StringBuffer();
            result.append("Statistics block:\n");
            result.append(getKey("all"));
           
            int totalAll=0;
            int sourceAll=0;
            int unsafeAll=0;
            int sourceUnsafeAll=0;
           
            if(totalAll==-1){
             
              totalAll=0;
            }
           
            if(sourceAll==-1){
              sourceAll=0;
            }
           
            if(unsafeAll==-1){
              unsafeAll=0;
            }
           
            if(sourceUnsafeAll==-1){
             
              sourceUnsafeAll=0;
            }
           
           
            for (Iterator iter = categories.keySet().iterator(); iter.hasNext();) {
                String category = (String) iter.next();
                result.append(getKey(category));
            }
           
            totalAll=get("total.all");
            sourceAll=get("source.all");
            unsafeAll=get("unsafe.all");
            sourceUnsafeAll=get("source+unsafe.all");
           
            if(totalAll==-1){
             
              totalAll=0;
            }
           
            if(sourceAll==-1){
              sourceAll=0;
            }
           
            if(unsafeAll==-1){
              unsafeAll=0;
            }
           
            if(sourceUnsafeAll==-1){
             
              sourceUnsafeAll=0;
            }
           
           
            result.append("Out of " + totalAll + " sinks, " + sourceAll
                + " occur in the source.\n");
           
           
            result.append("Out of " + unsafeAll + " unsafe sinks, "
                + sourceUnsafeAll + " occur in the source.\n");
           
           
           
            return result.toString();
        }

        private String getKey(String key) {
         
          int total=get("total." + key);
          int source=get("source+unsafe." + key);
          int unsafe=get("unsafe." + key);
         
          if(total==-1){
           
            total=0;
          }
         
          if(source==-1){
            source=0;
          }
         
          if(unsafe==-1){
            unsafe=0;
          }
         
            return ("\t" + cutto(key, 20) + "\tTotal:\t" + total + ",\tunsafe:\t"
                + unsafe + ",\tin source:\t" + source + "\n");
        }

        private void inc(String key) {
            if (map.get(key) == null) {
                map.put(key, new Integer(1));
            } else {
                Integer oldValue = (Integer) map.get(key);
                map.put(key, new Integer(oldValue.intValue() + 1));
            }
        }

        private int get(String key) {
            Integer i = ((Integer) map.get(key));
            if (i != null) {
                return i.intValue();
            } else {
                logError("Key '" + key + "' is missing.");
                return -1;
            }
        }

        /**
         * Clears all internal data structures.
         */
        public void clearMatches() {
            matches.clear();
            map.clear();
            categories.clear();
        }
    }
    class ViewContentProvider implements IStructuredContentProvider {
        Vector<ViewMatch> matches = new Vector<ViewMatch>();

        public void addMatch(ViewMatch match) {
            matches.add(match);
            statisticsManager.add(match);
            // TODO: handle markers
            /*
             * try { IMarker marker =
             * match.getResource().createMarker(MARKER_ID);
             * marker.setAttribute(IMarker.MESSAGE, match.getMessage());
             * if(match.getAST() != null){
             * marker.setAttribute(IMarker.CHAR_START,
             * match.getAST().getStartPosition());
             * marker.setAttribute(IMarker.CHAR_END, match.getAST().getLength() +
             * match.getAST().getStartPosition()); }
             * marker.setAttribute(IMarker.SEVERITY, match.isError() ?
             * IMarker.SEVERITY_ERROR : IMarker.SEVERITY_WARNING); } catch
             * (CoreException e) { e.printStackTrace(); }
             */
        }

        public void inputChanged(Viewer v, Object oldInput, Object newInput) {
        }

        public void dispose() {
        }

        public Object[] getElements(Object parent) {
            return matches.toArray();
        }

        public int getMatchCount() {
            return matches.size();
        }

        public void clearMatches() {
            matches.clear();
        }
    }
    class ViewLabelProvider extends LabelProvider
        implements
            ITableLabelProvider,
            IColorProvider,
            IFontProvider {
        Font fRegular, fBold, fItalic;

        ViewLabelProvider() {
            fRegular = PlatformUI.getWorkbench().getThemeManager().getCurrentTheme()
                .getFontRegistry().get(JFaceResources.DEFAULT_FONT);
            fBold = PlatformUI.getWorkbench().getThemeManager().getCurrentTheme().getFontRegistry()
                .getBold(JFaceResources.DIALOG_FONT);
            fItalic = PlatformUI.getWorkbench().getThemeManager().getCurrentTheme()
                .getFontRegistry().getItalic(JFaceResources.DIALOG_FONT);
        }

        public String getColumnText(Object obj, int index) {
            ViewMatch match = (ViewMatch) obj;
            String result = null;
            if (index == MESSAGE_FIELD) {
                result = match.getMessage();
            } else if (index == TYPE_FIELD) {
                result = match.getType();
            } else if (index == CATEGORY_FIELD) {
                result = match.getCategory();
            } else if (index == PROJECT_FIELD) {
                result = match.getProject().getName();
            } else if (index == FILE_FIELD) {
                result = match.getFileName();
            } else if (index == LINE_FIELD) {
                result = match.getLineNumber() != -1 ? "" + match.getLineNumber() : "";
            }
            if (result != null) {
                return result;
            } else {
                return ""; // "<unknown>";
            }
        }

        public Image getColumnImage(Object obj, int index) {
            ViewMatch match = (ViewMatch) obj;
            if (index == 0) {
                return match.isError()
                    ? JavaPluginImages.get(JavaPluginImages.IMG_OBJS_ERROR)
                    : JavaPluginImages.get(JavaPluginImages.IMG_FIELD_PUBLIC);
            }
            return null;
        }

        public Color getForeground(Object element) {
            Display display = Display.getCurrent();
            ViewMatch match = (ViewMatch) element;
            if (match.isSource() && !match.isSafe()) {
                return display.getSystemColor(SWT.COLOR_LIST_FOREGROUND);
            } else {
                return display.getSystemColor(SWT.COLOR_GRAY);
            }
        }

        public Color getBackground(Object element) {
            return Display.getCurrent().getSystemColor(SWT.COLOR_LIST_BACKGROUND);
        }

        public Font getFont(Object element) {
            ViewMatch match = (ViewMatch) element;
            if (match.isDone()) {
                return fBold;
            }
            if (match.isSafe()) {
                return fItalic;
            }
            return fRegular;
        }
    }

    /**
     * This is a callback that will allow us to create the viewer and initialize
     * it.
     */
    public void createPartControl(Composite parent) {
        fClipboard = new Clipboard(parent.getDisplay());
        // viewer = new TableViewer(parent, SWT.MULTI | SWT.H_SCROLL |
        // SWT.V_SCROLL);
        viewer = new LocationViewer(parent);
        viewer.setContentProvider(new ViewContentProvider());
        viewer.setLabelProvider(new ViewLabelProvider());
        viewer.setSorter(new ColumnBasedSorter(2));
        viewer.setInput(getViewSite());
        makeActions();
        hookContextMenu();
        viewer.addDoubleClickListener(new IDoubleClickListener() {
            public void doubleClick(DoubleClickEvent event) {
                doubleClickAction.run();
            }
        });
        viewer.addSelectionChangedListener(new ISelectionChangedListener() {
            public void selectionChanged(SelectionChangedEvent event) {
                IStructuredSelection sel = (IStructuredSelection) event.getSelection();
                if (sel != null) {
                    int size = sel.toArray().length;
                    if (size > 0) {
                        int done = 0, safe = 0;
                        Object[] selected = sel.toArray();
                        for (int i = 0; i < selected.length; i++) {
                            ViewMatch vm = (ViewMatch) selected[i];
                            if (vm.isDone()) done++;
                            if (vm.isSafe()) safe++;
                        }
                        IStatusLineManager slManager = getViewSite().getActionBars()
                            .getStatusLineManager();
                        slManager.setMessage("Selected " + size
                            + (size > 1 ? " entries." : " entry.") + done
                            + " elements are checked." + safe + " elements are safe.");
                    }
                }
            }
        });
        contributeToActionBars();
    }

    private void hookContextMenu() {
        MenuManager menuMgr = new MenuManager("#PopupMenu");
        menuMgr.setRemoveAllWhenShown(true);
        menuMgr.addMenuListener(new IMenuListener() {
            public void menuAboutToShow(IMenuManager manager) {
                SinkView.this.fillContextMenu(manager);
            }
        });
        Menu menu = menuMgr.createContextMenu(viewer.getControl());
        viewer.getControl().setMenu(menu);
        getSite().registerContextMenu(menuMgr, viewer);
    }

    private void contributeToActionBars() {
        IActionBars bars = getViewSite().getActionBars();
        // fillLocalPullDown(bars.getMenuManager());
        fillLocalToolBar(bars.getToolBarManager());
        LapseMultiActionGroup group =
            new LapseCheckboxActionGroup(
                new IAction[]{
                hideSafeAction, hideNoSourceAction, showSQLAction, showXSSAction, showPTAction,showHttpResponseAction,showCommandInjectionAction,showLDAPAction,showXPathAction},
                new boolean[]{true, true, false, false, false,false,false,false,false});
        group.addActions(bars.getMenuManager());
    }

    private void fillContextMenu(IMenuManager manager) {
       
        ViewMatch match = (ViewMatch) ((IStructuredSelection) viewer.getSelection())
            .getFirstElement();
        if (match != null && match.isError()) {
            manager.add(doBackwardPropagationAction);
        }
        manager.add(runAction);
        manager.add(copyToClipboardAction);
       
        // Other plug-ins can contribute there actions here
        manager.add(new Separator(IWorkbenchActionConstants.MB_ADDITIONS));
    }

    private void fillLocalToolBar(IToolBarManager manager) {
        manager.add(runAction);
        manager.add(setSafeAction);
        manager.add(copyToClipboardAction);
        manager.add(new Separator());
        manager.add(statAction);
        // manager.add(hideSafeAction);
        // manager.add(hideNoSourceAction);
    }

    private void computeSinks() {
        (new Job("Computing Sinks") {
         
            protected IStatus run(final IProgressMonitor monitor) {
                final ViewContentProvider cp = ((ViewContentProvider) viewer.getContentProvider());
                cp.clearMatches();
                Display.getDefault().syncExec(new Runnable() {
                    public void run() {
                        if (cp.getMatchCount() > 0) {
                            monitor.subTask("Clearing the results");
                            viewer.refresh();
                        }
                    }
                });
                statisticsManager.clearMatches();
                IJavaModel model = JavaModelManager.getJavaModelManager().getJavaModel();
                IJavaProject[] projects;
                try {
                    projects = model.getJavaProjects();
                } catch (JavaModelException e) {
                    log(e.getMessage(), e);
                    return Status.CANCEL_STATUS;
                }
                Collection/* <SinkDescription> */sinks = XMLConfig.readSinks("sinks.xml");
                //Assert.isNotNull(sinks, "Could not parse the sinks");
                int Matches = 0, Unsafe = 0;
                for (int i = 0; i < projects.length; i++) {
                    IJavaProject project = (IJavaProject) projects[i];
                    // if(!project.isOpen()) {
                    // System.out.println("Skipping " + project);
                    // continue;
                    // }
                    log("------------------ Project "+ cutto(project.getProject().getName(), 20) + "------------------ ");
                    int matches = 0, unsafe = 0;
                    for (Iterator descIter = sinks.iterator(); descIter.hasNext();) {
                        XMLConfig.SinkDescription desc = (SinkDescription) descIter.next();
                        Assert.isNotNull(desc);
                        log("Analyzing project " + project.getProject().getName()
                            + ": processing method " + desc.getID() + "...");
                        monitor.subTask("Project " + project.getProject().getName()
                            + ": processing method " + desc.getID() + "...");
                        int matchesForMethod = matches;
                        int index=desc.getMethodName().lastIndexOf('.');
                        char aux=(desc.getMethodName().charAt(index+1));
                        boolean isConstructor = aux<='Z';
                    
                        Collection callers/* <MethodUnitPair> */= CallerFinder.findCallers(
                            monitor, desc.getID(), project, isConstructor);
                    
                        for (Iterator iter = callers.iterator(); iter.hasNext();) {
                         
                            Utils.ExprUnitResourceMember element = (Utils.ExprUnitResourceMember) iter
                                .next();
                            Expression expr = element.getExpression();
                          
                          
                            // do a case on the expression:
                            String message = null;
                            boolean isError = true;
                            boolean hasSource = true;
                            if (expr != null) {
                                message = expr.toString();
                              
                                int argCount = 0;
                                Expression arg = null;
                                int argumentNumber = desc.getVulnerableParameter();
                                if (expr instanceof MethodInvocation) {
                                    MethodInvocation mi = (MethodInvocation) expr;
                                    argCount = mi.arguments().size();
                                    if (argCount > 0) {
                                        arg = (Expression) mi.arguments().get(argumentNumber);
                                    }
                                   
                                } else if (expr instanceof ClassInstanceCreation) {
                                    ClassInstanceCreation ci = (ClassInstanceCreation) expr;
                                    argCount = ci.arguments().size();
                                    if (argCount > 0) {
                                        arg = (Expression) ci.arguments().get(argumentNumber);
                                    }
                                  
                                } else {
                                    logError("Can't match " + expr + " of type " + expr.getClass());
                                 
                                    continue;
                                }
                                if (argCount > 0) {
                          
                                    isError = !isStringContant(arg, element.getCompilationUnit(),
                                        element.getResource());
                                   
                                } else {
                                    // no parameter to speak of... // TODO: this
                                    // is genrally odd
                                    isError = false;
                                }
                                hasSource = true;
                            } else {
                                message = element.getMember().getElementName();
                                hasSource = false;
                            }
                            ViewMatch match = new ViewMatch(message, expr, element
                                .getCompilationUnit(), element.getResource(), desc.getID(), element
                                .getMember(), desc.getCategoryName(), isError, hasSource);
                            cp.addMatch(match);
                            matches++;
                            if (isError) unsafe++;
                        }
//                        log(matches - matchesForMethod + ".");
//                        Display.getDefault().syncExec(new Runnable() {
//                            public void run() {
//                                log(viewer.getTable().getItemCount() + " items.");
//                            }
//                        });
                        if (matches > 0) {
                            Display.getDefault().syncExec(new Runnable() {
                                public void run() {
                                    viewer.refresh();
                                }
                            });
                        }
                    }
                    log(cutto(project.getProject().getName(), 20) + "\t:\t"
                        + matches + "\ttotal sink(s),\t" + unsafe + "\tunsafe sink(s)");
                    Unsafe += unsafe;
                    Matches += matches;
                }
                Display.getDefault().syncExec(new Runnable() {
                    public void run() {
                        viewer.refresh();
                    }
                });
                Assert.isTrue(cp.getMatchCount() == Matches,
                    "There is a mismatch between the number of metches in the view (" +
                    cp.getMatchCount() + ") and the total number of matches (" +
                    Matches + ")" );
                log("\n" + cutto("All projects", 20) + "\t:\t" + Matches
                    + "\ttotal sink(s),\t" + Unsafe + "\tunsafe sink(s)");
                //statisticsManager.printStatistics();
                return Status.OK_STATUS;
            }
        }).schedule();
    }

    /**
     * Tests whether a given expression is a String contant.
     *
     * @param arg -- argument that we want to test
     *
     * This method does pattern-matching to find constant strings. If none of
     * the patterns match, false is returned.
     */
    public static boolean isStringContant(Expression arg, CompilationUnit unit, IResource resource) {
        if (arg instanceof StringLiteral) {
            return true;
        } else if (arg instanceof InfixExpression) {
            InfixExpression infixExpr = (InfixExpression) arg;
            if (!isStringContant(infixExpr.getLeftOperand(), unit, resource)) return false;
            if (!isStringContant(infixExpr.getRightOperand(), unit, resource)) return false;
            for (Iterator iter2 = infixExpr.extendedOperands().iterator(); iter2.hasNext();) {
                if (!isStringContant((Expression) iter2.next(), unit, resource)) {
                    return false;
                }
            }
            return true;
        } else if (arg instanceof SimpleName) {
            SimpleName name = (SimpleName) arg;
            // System.err.println("TODO -> Name: " + name);
            VariableDeclaration varDecl = LapseView.name2decl(name, unit, resource);
            if (varDecl instanceof SingleVariableDeclaration) {
                SingleVariableDeclaration decl = (SingleVariableDeclaration) varDecl;
                if (decl.getInitializer() != null && decl.getInitializer() instanceof StringLiteral) {
                    StringLiteral l = (StringLiteral) decl.getInitializer();
                    return true;
                }
            } else {
                VariableDeclarationFragment decl = (VariableDeclarationFragment) varDecl;
                if (decl.getInitializer() != null) {
                    return isStringContant(decl.getInitializer(), unit, resource);
                }
            }
        } else if (arg instanceof MethodInvocation) {
            MethodInvocation inv = (MethodInvocation) arg;
            if (inv.getName().getIdentifier().equals("toString")) {
                // TODO: StringBuffer.toString() return result
                Expression target = inv.getExpression();
                // System.err.println("TODO -> methodInv: " + inv);
            }
        }
        // TODO: add final/const
        return false;       // this is a conservative return value
    }

    /*private Type findLocallyDeclaredType(String argName, CompilationUnit compilationUnit) {
        final Map<String, Type> var2type = new HashMap<String, Type>();
        ASTVisitor visitor = new ASTVisitor() {
            public boolean visit(VariableDeclarationStatement node) {
                Type type = node.getType();
                // node.getType()
                for (Iterator iter = node.fragments().iterator(); iter.hasNext();) {
                    VariableDeclarationFragment frag = (VariableDeclarationFragment) iter.next();
                    SimpleName var = frag.getName();
                    // System.out.println("Storing " +
                    // var.getFullyQualifiedName() + " of type " + type);
                    var2type.put(var.getFullyQualifiedName(), type);
                }
                return false;
            }
        };
        compilationUnit.accept(visitor);
        // System.out.println("There are " + var2type.size() + " elements in the
        // map");
        return (Type) var2type.get(argName);
    }*/

//    private Type findLocallyDeclaredType(SimpleName arg, CompilationUnit compilationUnit) {
//        return findLocallyDeclaredType(arg.getFullyQualifiedName(), compilationUnit);
//    }

    private void makeActions() {
        runAction = new Action() {
            public void run() {
                computeSinks();
            }
        };
       
        runAction.setText("Find sinks");
        runAction.setToolTipText("Find sinks");
        runAction.setImageDescriptor(JavaPluginImages.DESC_OBJS_JSEARCH);
        setSafeAction = new Action() {
            public void run() {
                Object[] matches = ((IStructuredSelection) viewer.getSelection()).toArray();
                for (int i = 0; i < matches.length; i++) {
                    ViewMatch match = (ViewMatch) matches[i];
                    if (match != null) {
                        // toggle the safe status
                        match.setSafe(!match.getSafe());
                        viewer.refresh(match);
                    }
                }
            }
        };
       
        setSafeAction.setText("Toggle safe status");
        setSafeAction.setToolTipText("Toggle safe status");
        // setSafeAction.setImageDescriptor(JavaPluginImages.DESC_DLCL_FILTER);
        JavaPluginImages.setLocalImageDescriptors(setSafeAction, "clear_co.gif");
        doBackwardPropagationAction = new Action() {
            public void run() {
                LapseView lapseView = LapsePlugin.getDefault().getLapseView();
                if (lapseView != null) {
                    ViewMatch match = ((ViewMatch) ((IStructuredSelection) viewer.getSelection()).getFirstElement());
                    ASTNode astNode = match.getAST();
                    SlicingFromSinkJob job = lapseView.getSinkSlicingJob();
                    if(job != null) {
                        ASTNode arg = null;
                        if (astNode instanceof MethodInvocation) {
                            arg = (ASTNode) ((MethodInvocation) astNode).arguments().get(0);
                        } else if(astNode instanceof ClassInstanceCreation)
                        {
                          arg=(ASTNode)((ClassInstanceCreation) astNode).arguments().get(0);
                        }
                        else
                        {
                            logError("Unrecognized " + astNode);
                            return;
                        }
                        job.setSink(arg);
                        job.setUnit(match.getUnit());
                        job.setResource(match.getResource());
                       
                        // switch to the provenance tracker view
                        lapseView.refresh();
                        lapseView.setFocus();
                       
                        // run the job         
                        job.schedule();
                    } else {
                        MessageDialog.openError(
                            viewer.getControl().getShell(),
                            "Error occurred",
                            "The provenance view is closed. Please open it and try again.");
                    }
                } else {
                    MessageDialog.openError(
                        viewer.getControl().getShell(),
                        "Error occurred",
                        "The provenance view is closed. Please open it and try again.");
                }
            }
        };
       
        doBackwardPropagationAction.setText("Perform backward propagation from this sink");
        doBackwardPropagationAction.setToolTipText("Perform backward propagation from this sink");
        doBackwardPropagationAction.setImageDescriptor(JavaPluginImages.DESC_ELCL_VIEW_MENU); // TODO
       
        copyToClipboardAction = new CopyMatchViewAction(this, fClipboard);
        copyToClipboardAction.setText("Copy selection to clipboard");
        copyToClipboardAction.setToolTipText("Copy selection to clipboard");
        copyToClipboardAction.setImageDescriptor(JavaPluginImages.DESC_DLCL_COPY_QUALIFIED_NAME);
        doubleClickAction = new Action() {
            public void run() {
                IStructuredSelection sel = (IStructuredSelection) viewer.getSelection();
                ViewMatch match = (ViewMatch) sel.getFirstElement();
                try {
                    // System.out.println("Double-clicked on " +
                    // match.getMember().getClass());
                    EditorUtility.openInEditor(match.getMember(), true);
                    if (match.getLineNumber() != -1) {
                        ITextEditor editor = (ITextEditor) EditorUtility.openInEditor(match.getMember());
                        editor.selectAndReveal(match.getAST().getStartPosition(), match.getAST().getLength());
                    }
                } catch (PartInitException e) {
                    log(e.getMessage(), e);
                } catch (Exception e) {
                    log(e.getMessage(), e);
                }
            }
        };
       
        {
            hideSafeAction = new Action("Hide safe vulnerability sinks (const params)", IAction.AS_CHECK_BOX) {
                boolean hasFilter = false;
                ViewerFilter filter = new ViewerFilter() {
                    public boolean select(Viewer viewer, Object parentElement, Object element) {
                        ViewMatch match = (ViewMatch) element;
                        return match.isError();
                    }
                };

                public void run() {
                    if (!hasFilter) {
                        viewer.addFilter(filter);
                        hasFilter = true;
                    } else {
                        viewer.removeFilter(filter);
                        hasFilter = false;
                    }
                }
            };
            hideSafeAction.setImageDescriptor(JavaPluginImages.DESC_ELCL_FILTER);
            // //////////
            hideNoSourceAction = new Action("Hide vulnerability sinks without source", IAction.AS_CHECK_BOX) {
                boolean hasFilter = false;
                ViewerFilter filter = new ViewerFilter() {
                    public boolean select(Viewer viewer, Object parentElement, Object element) {
                        ViewMatch match = (ViewMatch) element;
                        return match.isSource();
                    }
                };

                public void run() {
                    if (!hasFilter) {
                        viewer.addFilter(filter);
                        hasFilter = true;
                    } else {
                        viewer.removeFilter(filter);
                        hasFilter = false;
                    }
                }
            };
            hideSafeAction.setImageDescriptor(JavaPluginImages.DESC_ELCL_FILTER);
        }
        {
            showSQLAction = new Action("Show SQL Injection vulnerabilities only", IAction.AS_CHECK_BOX) {
                boolean hasFilter = false;
                ViewerFilter filter = new ViewerFilter() {
                    public boolean select(Viewer viewer, Object parentElement, Object element) {
                        ViewMatch match = (ViewMatch) element;
                        return match.getCategory().equalsIgnoreCase("SQL Injection");
                    }
                };

                public void run() {
                    if (!hasFilter) {
                        viewer.addFilter(filter);
                        hasFilter = true;
                    } else {
                        viewer.removeFilter(filter);
                        hasFilter = false;
                    }
                }
            };
            showSQLAction.setImageDescriptor(JavaPluginImages.DESC_ELCL_FILTER);
        }
        {
            showXSSAction = new Action("Show Cross-site Scripting vulnerabilities only", IAction.AS_CHECK_BOX) {
                boolean hasFilter = false;
                ViewerFilter filter = new ViewerFilter() {
                    public boolean select(Viewer viewer, Object parentElement, Object element) {
                        ViewMatch match = (ViewMatch) element;
                        return match.getCategory().equalsIgnoreCase("Cross-site Scripting");
                    }
                };

                public void run() {
                    if (!hasFilter) {
                        viewer.addFilter(filter);
                        hasFilter = true;
                    } else {
                        viewer.removeFilter(filter);
                        hasFilter = false;
                    }
                }
            };
            showXSSAction.setImageDescriptor(JavaPluginImages.DESC_ELCL_FILTER);
        }
        {
            showPTAction = new Action("Show Path Traversal vulnerabilities only", IAction.AS_CHECK_BOX) {
                boolean hasFilter = false;
                ViewerFilter filter = new ViewerFilter() {
                    public boolean select(Viewer viewer, Object parentElement, Object element) {
                        ViewMatch match = (ViewMatch) element;
                        return match.getCategory().equalsIgnoreCase("Path Traversal");
                    }
                };

                public void run() {
                    if (!hasFilter) {
                        viewer.addFilter(filter);
                        hasFilter = true;
                    } else {
                        viewer.removeFilter(filter);
                        hasFilter = false;
                    }
                }
            };
            showPTAction.setImageDescriptor(JavaPluginImages.DESC_ELCL_FILTER);
        }
       
        {
            showHttpResponseAction = new Action("Show Http Response Splitting vulnerabilities only", IAction.AS_CHECK_BOX) {
                boolean hasFilter = false;
                ViewerFilter filter = new ViewerFilter() {
                    public boolean select(Viewer viewer, Object parentElement, Object element) {
                        ViewMatch match = (ViewMatch) element;
                        return match.getCategory().equalsIgnoreCase("HTTP Response Splitting");
                    }
                };

                public void run() {
                    if (!hasFilter) {
                        viewer.addFilter(filter);
                        hasFilter = true;
                    } else {
                        viewer.removeFilter(filter);
                        hasFilter = false;
                    }
                }
            };
            showHttpResponseAction.setImageDescriptor(JavaPluginImages.DESC_ELCL_FILTER);
        }
       
        {
            showCommandInjectionAction = new Action("Show Command Injection vulnerabilities only", IAction.AS_CHECK_BOX) {
                boolean hasFilter = false;
                ViewerFilter filter = new ViewerFilter() {
                    public boolean select(Viewer viewer, Object parentElement, Object element) {
                        ViewMatch match = (ViewMatch) element;
                        return match.getCategory().equalsIgnoreCase("Command Injection");
                    }
                };

                public void run() {
                    if (!hasFilter) {
                        viewer.addFilter(filter);
                        hasFilter = true;
                    } else {
                        viewer.removeFilter(filter);
                        hasFilter = false;
                    }
                }
            };
            showCommandInjectionAction.setImageDescriptor(JavaPluginImages.DESC_ELCL_FILTER);
        }
       
        {
            showLDAPAction = new Action("Show LDAP Injection vulnerabilities only", IAction.AS_CHECK_BOX) {
                boolean hasFilter = false;
                ViewerFilter filter = new ViewerFilter() {
                    public boolean select(Viewer viewer, Object parentElement, Object element) {
                        ViewMatch match = (ViewMatch) element;
                        return match.getCategory().equalsIgnoreCase("LDAP Injection");
                    }
                };

                public void run() {
                    if (!hasFilter) {
                        viewer.addFilter(filter);
                        hasFilter = true;
                    } else {
                        viewer.removeFilter(filter);
                        hasFilter = false;
                    }
                }
            };
            showLDAPAction.setImageDescriptor(JavaPluginImages.DESC_ELCL_FILTER);
        }
       
        {
            showXPathAction = new Action("Show XPath Injection vulnerabilities only", IAction.AS_CHECK_BOX) {
                boolean hasFilter = false;
                ViewerFilter filter = new ViewerFilter() {
                    public boolean select(Viewer viewer, Object parentElement, Object element) {
                        ViewMatch match = (ViewMatch) element;
                        return match.getCategory().equalsIgnoreCase("XPath Injection");
                    }
                };

                public void run() {
                    if (!hasFilter) {
                        viewer.addFilter(filter);
                        hasFilter = true;
                    } else {
                        viewer.removeFilter(filter);
                        hasFilter = false;
                    }
                }
            };
            showXPathAction.setImageDescriptor(JavaPluginImages.DESC_ELCL_FILTER);
        }
       
       
        {
            hideNoSourceAction = new Action("Hide vulnerability sinks without source code", IAction.AS_CHECK_BOX) {
                boolean hasFilter = false;
                ViewerFilter filter = new ViewerFilter() {
                    public boolean select(Viewer viewer, Object parentElement, Object element) {
                        ViewMatch match = (ViewMatch) element;
                        return match.isSource();
                    }
                };

                public void run() {
                    if (!hasFilter) {
                        viewer.addFilter(filter);
                        hasFilter = true;
                    } else {
                        viewer.removeFilter(filter);
                        hasFilter = false;
                    }
                }
            };
            hideNoSourceAction.setImageDescriptor(JavaPluginImages.DESC_ELCL_FILTER);
        }
        {
            final SinkView sinkView = this;
            statAction = new Action() {
                public void run() {
                    SinkStatsDialog dialog = new SinkStatsDialog(viewer.getControl().getShell(),
                        sinkView);
                    // dialog.create();
                    dialog.open();
                    dialog.getReturnCode();
                }
            };
            statAction.setText("Get sink statistics");
            statAction.setToolTipText("Get sink statistics");
            //JavaPluginImages.setLocalImageDescriptors(statAction, "statistics.gif");
            ImageDescriptor desc = JavaPluginImages.DESC_OBJS_LIBRARY;
            statAction.setImageDescriptor(desc);
        }
    }

//    private void showMessage(String message) {
//        MessageDialog.openInformation(viewer.getControl().getShell(), "List of matches", message);
//    }

    /**
     * Passing the focus request to the viewer's control.
     */
    public void setFocus() {
        viewer.getControl().setFocus();
    }
    class LocationViewer extends TableViewer {
        private final String columnHeaders[] =
            {
                "Suspicious call", "Method", "Category",
                "Project", "File", "Line"
            };
        private ColumnLayoutData columnLayouts[] = {
                new ColumnPixelData(500),
                new ColumnWeightData(50), new ColumnWeightData(50), new ColumnWeightData(50),
                new ColumnWeightData(80), new ColumnWeightData(15)
            };
        //private CheckboxTableViewer checkable;

        LocationViewer(Composite parent) {
            super(parent, SWT.H_SCROLL | SWT.V_SCROLL | SWT.MULTI | SWT.FULL_SELECTION);
           
                   
            getTable().setLinesVisible(true);
            createColumns();
            // is there a way to remove this?..
//            checkable = CheckboxTableViewer.newCheckList(parent,
//                SWT.H_SCROLL | SWT.V_SCROLL | SWT.MULTI | SWT.FULL_SELECTION);
//            checkable.addCheckStateListener(new ICheckStateListener() {
//                public void checkStateChanged(CheckStateChangedEvent event) {
//                    ViewMatch match = ((ViewMatch) event.getElement());
//                    match.setDone(!match.isDone());
//                    // System.err.println("Refreshing");
//                    refresh(match);
//                }
//            });
        }

        private void createColumns() {
            TableLayout layout = new TableLayout();
            getTable().setLayout(layout);
            getTable().setHeaderVisible(true);
            for (int i = 0; i < columnHeaders.length; i++) {
                layout.addColumnData(columnLayouts[i]);
                TableColumn tc = new TableColumn(getTable(), SWT.BORDER, i);
                tc.setResizable(columnLayouts[i].resizable);
                tc.setText(columnHeaders[i]);
                tc.pack();
                final int j = i;
                tc.addSelectionListener(new SelectionAdapter() {
                    public void widgetSelected(SelectionEvent e) {
                        ViewerSorter oldSorter = viewer.getSorter();
                        if (oldSorter instanceof ColumnBasedSorter) {
                            ColumnBasedSorter sorter = (ColumnBasedSorter) oldSorter;
                            if (sorter.getColumn() == j) {
                                sorter.toggle();
                                viewer.refresh();
                                // System.err.println("Resorting column " + j +
                                // " in order "
                                // + sorter.getOrientation());
                                return;
                            }
                        }
                        viewer.setSorter(new ColumnBasedSorter(j));
                        logError("Sorting column " + j + " in order " + 1);
                        viewer.refresh();
                    }
                });
            }
        }

        /**
         * Attaches a contextmenu listener to the tree
         */
        void initContextMenu(IMenuListener menuListener, String popupId, IWorkbenchPartSite viewSite) {
            MenuManager menuMgr = new MenuManager();
            menuMgr.setRemoveAllWhenShown(true);
            menuMgr.addMenuListener(menuListener);
            Menu menu = menuMgr.createContextMenu(getControl());
            getControl().setMenu(menu);
            viewSite.registerContextMenu(popupId, menuMgr, this);
        }

        void clearViewer() {
            setInput(""); //$NON-NLS-1$
        }
    }

    private static String cutto(String str, int to) {
        if (str.length() < to - 3) {
            return str + repeat(" ", to - str.length());
        } else {
            return str.substring(0, to - 3) + "...";
        }
    }

    private static String repeat(String str, int times) {
        StringBuffer buf = new StringBuffer();
        for (int i = 0; i < times; i++) {
            buf.append(str);
        }
        return buf.toString();
    }
    class CopyMatchViewAction extends Action {
        // private static final char INDENTATION = '\t'; //$NON-NLS-1$
        private SinkView fView;
        private final Clipboard fClipboard;

        public CopyMatchViewAction(SinkView view, Clipboard clipboard) {
            super("Copy matches to clipboard");
            Assert.isNotNull(clipboard);
            fView = view;
            fClipboard = clipboard;
        }

        public void run() {
            StringBuffer buf = new StringBuffer();
            addCalls(viewer.getTable().getSelection(), buf);
            TextTransfer plainTextTransfer = TextTransfer.getInstance();
            try {
                fClipboard.setContents(new String[]{convertLineTerminators(buf.toString())},
                    new Transfer[]{plainTextTransfer});
            } catch (SWTError e) {
                if (e.code != DND.ERROR_CANNOT_SET_CLIPBOARD) throw e;
                if (MessageDialog
                    .openQuestion(fView.getViewSite().getShell(),
                        ("CopyCallHierarchyAction.problem"),
                        ("CopyCallHierarchyAction.clipboard_busy"))) {
                    run();
                }
            }
        }

        private void addCalls(TableItem[] items, StringBuffer buf) {
            for (int i = 0; i < items.length; i++) {
                TableItem item = items[i];
                SinkView.ViewMatch match = (SinkView.ViewMatch) item.getData();
                buf.append(match.toLongString());
                buf.append('\n');
            }
        }

        private String convertLineTerminators(String in) {
            StringWriter stringWriter = new StringWriter();
            PrintWriter printWriter = new PrintWriter(stringWriter);
            StringReader stringReader = new StringReader(in);
            BufferedReader bufferedReader = new BufferedReader(stringReader);
            String line;
            try {
                while ((line = bufferedReader.readLine()) != null) {
                    printWriter.println(line);
                }
            } catch (IOException e) {
                return in; // return the call hierarchy unfiltered
            }
            return stringWriter.toString();
        }
    }
    class ColumnBasedSorter extends ViewerSorter {
        private int columnNum;
        private int orientation = 1;

        ColumnBasedSorter(int columnNum, int orientation) {
            super(Collator.getInstance(Locale.getDefault()));
            this.columnNum = columnNum;
            this.orientation = orientation;
        }

        ColumnBasedSorter(int columnNum) {
            this(columnNum, 1);
        }

        public int category(Object element) {
            SinkView.ViewMatch match = (SinkView.ViewMatch) element;
            if (match.isSource()) {
                return 1;
            } else {
                return 0;
            }
        }

        public int compare(Viewer viewer, Object e1, Object e2) {
            SinkView.ViewMatch match1 = (SinkView.ViewMatch) e1;
            SinkView.ViewMatch match2 = (SinkView.ViewMatch) e2;
            int result = Integer.MAX_VALUE;
            String s1, s2;
            if (columnNum == MESSAGE_FIELD) {
                s1 = match1.getMessage();
                s2 = match2.getMessage();
            } else if (columnNum == TYPE_FIELD) {
                s1 = match1.getType().toString();
                s2 = match2.getType().toString();
            } else if (columnNum == CATEGORY_FIELD) {
                s1 = match1.getCategory();
                s2 = match2.getCategory();
            } else if (columnNum == PROJECT_FIELD) {
                s1 = match1.getProject().getProject().getName();
                s2 = match2.getProject().getProject().getName();
            } else if (columnNum == FILE_FIELD) {
                s1 = match1.getFileName().toString();
                s2 = match2.getFileName().toString();
            } else if (columnNum == LINE_FIELD) {
                s1 = "" + match1.getLineNumber();
                s2 = "" + match2.getLineNumber();
            } else {
                logError("Unknown column: " + columnNum);
                return 0;
            }
            result = orientation * s1.compareToIgnoreCase(s2);
        
            return result;
        }

        public void toggle() {
            orientation = orientation * -1;
        }

        public int getColumn() {
            return this.columnNum;
        }

        public int getOrientation() {
            return orientation;
        }
    }

    public StatisticsManager getStatisticsManager() {
        return statisticsManager;
    }
   
    private static void log(String message, Throwable e) {
        LapsePlugin.trace(LapsePlugin.SINK_DEBUG, "Sink view: " + message, e);
    }
   
    private static void log(String message) {
        log(message, null);
    }
   
    private static void logError(String message) {
        log(message, new Throwable());
    }
   
    public static boolean isDerivationName(String identifier) {
     
    Collection derivators = XMLConfig.readDerivators("derived.xml");
   
    for(Iterator iter = derivators.iterator(); iter.hasNext(); ){
      XMLConfig.DerivationDescription derivationDesc = (XMLConfig.DerivationDescription) iter.next();
      int i=derivationDesc.getMethodName().lastIndexOf('.');
      String sub=derivationDesc.getMethodName().substring(i+1);
      if(sub.equals(identifier)){
        return true;
      }
    }
 
    // none matched
    return false;
  }
}
TOP

Related Classes of lapsePlus.views.SinkView$StatisticsManager

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.