Changeset 14328 in josm for trunk


Ignore:
Timestamp:
2018-10-14T15:15:50+02:00 (8 months ago)
Author:
Don-vip
Message:

see #14319, see #16838 - update to svgSalamander 1.1.2

Location:
trunk/src
Files:
19 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/com/kitfox/svg/ClipPath.java

    r11525 r14328  
    132132     * all attributes with track information.
    133133     *
    134      * @param curTime
     134     * @param curTime Time at which to evaluate node
    135135     * @return - true if this node has changed state as a result of the time
    136136     * update
  • trunk/src/com/kitfox/svg/FillElement.java

    r8084 r14328  
    5959     * @param xform - The current transformation that the shape is being
    6060     * rendered under.
     61     * @return paint object
    6162     */
    6263    abstract public Paint getPaint(Rectangle2D bounds, AffineTransform xform);
  • trunk/src/com/kitfox/svg/Gradient.java

    r11525 r14328  
    160160    }
    161161
     162    private void buildStops()
     163    {
     164        ArrayList<Stop> stopList = new ArrayList<>(stops);
     165        stopList.sort((o1, o2) -> Float.compare(o1.offset, o2.offset));
     166
     167        //Remove doubles
     168        for (int i = stopList.size() - 2; i > 0; --i)
     169        {
     170            if (stopList.get(i + 1).offset == stopList.get(i).offset)
     171            {
     172                stopList.remove(i + 1);
     173            }
     174        }
     175       
     176        stopFractions = new float[stopList.size()];
     177        stopColors = new Color[stopList.size()];
     178        int idx = 0;
     179        for (Stop stop : stopList)
     180        {
     181            int stopColorVal = stop.color.getRGB();
     182            Color stopColor = new Color((stopColorVal >> 16) & 0xff, (stopColorVal >> 8) & 0xff, stopColorVal & 0xff, clamp((int) (stop.opacity * 255), 0, 255));
     183
     184            stopColors[idx] = stopColor;
     185            stopFractions[idx] = stop.offset;
     186            idx++;
     187        }
     188    }
     189
    162190    public float[] getStopFractions()
    163191    {
     
    173201        }
    174202
    175         stopFractions = new float[stops.size()];
    176         int idx = 0;
    177         for (Stop stop : stops) {
    178             float val = stop.offset;
    179             if (idx != 0 && val < stopFractions[idx - 1])
    180             {
    181                 val = stopFractions[idx - 1];
    182             }
    183             stopFractions[idx++] = val;
    184         }
     203        buildStops();
    185204
    186205        return stopFractions;
     
    200219        }
    201220
    202         stopColors = new Color[stops.size()];
    203         int idx = 0;
    204         for (Stop stop : stops) {
    205             int stopColorVal = stop.color.getRGB();
    206             Color stopColor = new Color((stopColorVal >> 16) & 0xff, (stopColorVal >> 8) & 0xff, stopColorVal & 0xff, clamp((int) (stop.opacity * 255), 0, 255));
    207             stopColors[idx++] = stopColor;
    208         }
     221        buildStops();
    209222
    210223        return stopColors;
    211     }
    212 
    213     public void setStops(Color[] colors, float[] fractions)
    214     {
    215         if (colors.length != fractions.length)
    216         {
    217             throw new IllegalArgumentException();
    218         }
    219 
    220         this.stopColors = colors;
    221         this.stopFractions = fractions;
    222         stopRef = null;
    223224    }
    224225
  • trunk/src/com/kitfox/svg/Group.java

    r11525 r14328  
    259259     * Recalculates the bounding box by taking the union of the bounding boxes
    260260     * of all children. Caches the result.
     261     * @throws com.kitfox.svg.SVGException
    261262     */
    262263    public void calcBoundingBox() throws SVGException
  • trunk/src/com/kitfox/svg/ImageSVG.java

    r11526 r14328  
    115115            {
    116116                URI src = sty.getURIValue(getXMLBase());
    117                 // CVE-2017-5617: Allow only data scheme
    118117                if ("data".equals(src.getScheme()))
    119118                {
    120119                    imageSrc = new URL(null, src.toASCIIString(), new Handler());
    121120                }
     121                else
     122                {
     123                    if (!diagram.getUniverse().isImageDataInlineOnly())
     124                    {
     125                        try
     126                        {
     127                            imageSrc = src.toURL();
     128                        } catch (Exception e)
     129                        {
     130                            Logger.getLogger(SVGConst.SVG_LOGGER).log(Level.WARNING,
     131                                "Could not parse xlink:href " + src, e);
     132                            imageSrc = null;
     133                        }
     134                    }
     135                }
    122136            }
    123137        } catch (Exception e)
     
    126140        }
    127141
    128         if (imageSrc != null)
    129         {
    130             diagram.getUniverse().registerImage(imageSrc);
    131 
    132             //Set widths if not set
    133             BufferedImage img = diagram.getUniverse().getImage(imageSrc);
    134             if (img == null)
    135             {
    136                 xform = new AffineTransform();
    137                 bounds = new Rectangle2D.Float();
    138                 return;
    139             }
    140 
    141             if (width == 0)
    142             {
    143                 width = img.getWidth();
    144             }
    145             if (height == 0)
    146             {
    147                 height = img.getHeight();
    148             }
    149 
    150             //Determine image xform
     142        diagram.getUniverse().registerImage(imageSrc);
     143
     144        //Set widths if not set
     145        BufferedImage img = diagram.getUniverse().getImage(imageSrc);
     146        if (img == null)
     147        {
    151148            xform = new AffineTransform();
    152             xform.translate(this.x, this.y);
    153             xform.scale(this.width / img.getWidth(), this.height / img.getHeight());
    154         }
     149            bounds = new Rectangle2D.Float();
     150            return;
     151        }
     152
     153        if (width == 0)
     154        {
     155            width = img.getWidth();
     156        }
     157        if (height == 0)
     158        {
     159            height = img.getHeight();
     160        }
     161
     162        //Determine image xform
     163        xform = new AffineTransform();
     164        xform.translate(this.x, this.y);
     165        xform.scale(this.width / img.getWidth(), this.height / img.getHeight());
    155166
    156167        bounds = new Rectangle2D.Float(this.x, this.y, this.width, this.height);
     
    326337                URI src = sty.getURIValue(getXMLBase());
    327338
    328                 URL newVal = null;
    329                 // CVE-2017-5617: Allow only data scheme
     339                URL newVal;
    330340                if ("data".equals(src.getScheme()))
    331341                {
    332342                    newVal = new URL(null, src.toASCIIString(), new Handler());
     343                } else
     344                {
     345                    newVal = src.toURL();
    333346                }
    334347
    335                 if (newVal != null && !newVal.equals(imageSrc))
     348                if (!newVal.equals(imageSrc))
    336349                {
    337350                    imageSrc = newVal;
  • trunk/src/com/kitfox/svg/MissingGlyph.java

    r11525 r14328  
    6161    private Shape path = null;
    6262    //Alternately, we may have child graphical elements
    63     private int horizAdvX = -1;  //Inherits font's value if not set
    64     private int vertOriginX = -1;  //Inherits font's value if not set
    65     private int vertOriginY = -1;  //Inherits font's value if not set
    66     private int vertAdvY = -1;  //Inherits font's value if not set
     63    private float horizAdvX = -1;  //Inherits font's value if not set
     64    private float vertOriginX = -1;  //Inherits font's value if not set
     65    private float vertOriginY = -1;  //Inherits font's value if not set
     66    private float vertAdvY = -1;  //Inherits font's value if not set
    6767
    6868    /**
     
    132132        if (getPres(sty.setName("horiz-adv-x")))
    133133        {
    134             horizAdvX = sty.getIntValue();
     134            horizAdvX = sty.getFloatValue();
    135135        }
    136136
    137137        if (getPres(sty.setName("vert-origin-x")))
    138138        {
    139             vertOriginX = sty.getIntValue();
     139            vertOriginX = sty.getFloatValue();
    140140        }
    141141
    142142        if (getPres(sty.setName("vert-origin-y")))
    143143        {
    144             vertOriginY = sty.getIntValue();
     144            vertOriginY = sty.getFloatValue();
    145145        }
    146146
    147147        if (getPres(sty.setName("vert-adv-y")))
    148148        {
    149             vertAdvY = sty.getIntValue();
     149            vertAdvY = sty.getFloatValue();
    150150        }
    151151    }
     
    179179    }
    180180
    181     public int getHorizAdvX()
     181    public float getHorizAdvX()
    182182    {
    183183        if (horizAdvX == -1)
     
    188188    }
    189189
    190     public int getVertOriginX()
     190    public float getVertOriginX()
    191191    {
    192192        if (vertOriginX == -1)
     
    197197    }
    198198
    199     public int getVertOriginY()
     199    public float getVertOriginY()
    200200    {
    201201        if (vertOriginY == -1)
     
    206206    }
    207207
    208     public int getVertAdvY()
     208    public float getVertAdvY()
    209209    {
    210210        if (vertAdvY == -1)
     
    261261     * @param horizAdvX the horizAdvX to set
    262262     */
    263     public void setHorizAdvX(int horizAdvX)
     263    public void setHorizAdvX(float horizAdvX)
    264264    {
    265265        this.horizAdvX = horizAdvX;
     
    269269     * @param vertOriginX the vertOriginX to set
    270270     */
    271     public void setVertOriginX(int vertOriginX)
     271    public void setVertOriginX(float vertOriginX)
    272272    {
    273273        this.vertOriginX = vertOriginX;
     
    277277     * @param vertOriginY the vertOriginY to set
    278278     */
    279     public void setVertOriginY(int vertOriginY)
     279    public void setVertOriginY(float vertOriginY)
    280280    {
    281281        this.vertOriginY = vertOriginY;
     
    285285     * @param vertAdvY the vertAdvY to set
    286286     */
    287     public void setVertAdvY(int vertAdvY)
     287    public void setVertAdvY(float vertAdvY)
    288288    {
    289289        this.vertAdvY = vertAdvY;
  • trunk/src/com/kitfox/svg/RadialGradient.java

    r11525 r14328  
    3737
    3838import com.kitfox.svg.xml.StyleAttribute;
     39import java.awt.Color;
    3940import java.awt.MultipleGradientPaint;
    4041import java.awt.Paint;
     
    129130        Point2D.Float pt1 = new Point2D.Float(cx, cy);
    130131        Point2D.Float pt2 = hasFocus ? new Point2D.Float(fx, fy) : pt1;
     132        float[] stopFractions = getStopFractions();
     133        Color[] stopColors = getStopColors();
    131134        if (gradientUnits == GU_USER_SPACE_ON_USE)
    132135        {
     
    135138                r,
    136139                pt2,
    137                 getStopFractions(),
    138                 getStopColors(),
     140                stopFractions,
     141                stopColors,
    139142                method,
    140143                MultipleGradientPaint.ColorSpaceType.SRGB,
     
    152155                r,
    153156                pt2,
    154                 getStopFractions(),
    155                 getStopColors(),
     157                stopFractions,
     158                stopColors,
    156159                method,
    157160                MultipleGradientPaint.ColorSpaceType.SRGB,
  • trunk/src/com/kitfox/svg/RenderableElement.java

    r11525 r14328  
    112112     * Pushes transform stack, transforms to local coordinates and sets up
    113113     * clipping mask.
     114     *
     115     * @param g Graphics context
     116     * @throws com.kitfox.svg.SVGException
    114117     */
    115118    protected void beginLayer(Graphics2D g) throws SVGException
     
    166169     * Restores transform and clipping values to the way they were before this
    167170     * layer was drawn.
     171     * @param g
    168172     */
    169173    protected void finishLayer(Graphics2D g)
  • trunk/src/com/kitfox/svg/SVGDiagram.java

    r11525 r14328  
    9090    final URI xmlBase;
    9191
    92     /** Creates a new instance of SVGDiagram */
     92    /**
     93     * Creates a new instance of SVGDiagram
     94     * @param xmlBase
     95     * @param universe
     96     */
    9397    public SVGDiagram(URI xmlBase, SVGUniverse universe)
    9498    {
     
    100104    /**
    101105     * Draws this diagram to the passed graphics context
     106     * @param g
     107     * @throws com.kitfox.svg.SVGException
    102108     */
    103109    public void render(Graphics2D g) throws SVGException
     
    114120     * SVGElement.getPath() is added for each entry.
    115121     *
     122     * @param point
     123     * @param retVec
    116124     * @return the passed in list
     125     * @throws com.kitfox.svg.SVGException
    117126     */
    118127    public List<List<SVGElement>> pick(Point2D point, List<List<SVGElement>> retVec) throws SVGException
     
    179188    /**
    180189     * Returns the viewing rectangle of this diagram in device coordinates.
     190     * @param rect
     191     * @return
    181192     */
    182193    public Rectangle2D getViewRect(Rectangle2D rect)
     
    224235     * Updates all attributes in this diagram associated with a time event.
    225236     * Ie, all attributes with track information.
     237     * @param curTime
     238     * @throws com.kitfox.svg.SVGException
    226239     */
    227240    public void updateTime(double curTime) throws SVGException
     
    240253     * SVGRoot when its x, y, width or height parameters are specified as
    241254     * percentages.
     255     * @param deviceViewport
    242256     */
    243257    public void setDeviceViewport(Rectangle deviceViewport)
  • trunk/src/com/kitfox/svg/SVGElement.java

    r11525 r14328  
    156156
    157157    /**
     158     * @param retVec
    158159     * @return an ordered list of nodes from the root of the tree to this node
    159160     */
     
    212213     * Searches children for given element. If found, returns index of child.
    213214     * Otherwise returns -1.
     215     * @param child
     216     * @return index of child
    214217     */
    215218    public int indexOfChild(SVGElement child)
     
    221224     * Swaps 2 elements in children.
    222225     *
    223      * @i index of first
    224      * @j index of second
    225      *
    226      * @return true if successful, false otherwise
     226     * @param i index of first child
     227     * @param j index of second child
     228     * @throws com.kitfox.svg.SVGException
    227229     */
    228230    public void swapChildren(int i, int j) throws SVGException
     
    246248     * @param helper - An object passed to all SVG elements involved in this
    247249     * build process to aid in sharing information.
     250     * @param parent
     251     * @throws org.xml.sax.SAXException
    248252     */
    249253    public void loaderStartElement(SVGLoaderHelper helper, Attributes attrs, SVGElement parent) throws SAXException
     
    317321     * Called after the start element but before the end element to indicate
    318322     * each child tag that has been processed
     323     * @param helper
     324     * @param child
     325     * @throws com.kitfox.svg.SVGElementException
    319326     */
    320327    public void loaderAddChild(SVGLoaderHelper helper, SVGElement child) throws SVGElementException
     
    346353    /**
    347354     * Called during load process to add text scanned within a tag
     355     * @param helper
     356     * @param text
    348357     */
    349358    public void loaderAddText(SVGLoaderHelper helper, String text)
     
    354363     * Called to indicate that this tag and the tags it contains have been
    355364     * completely processed, and that it should finish any load processes.
     365     * @param helper
     366     * @throws com.kitfox.svg.SVGParseException
    356367     */
    357368    public void loaderEndElement(SVGLoaderHelper helper) throws SVGParseException
     
    370381     * Called by internal processes to rebuild the geometry of this node from
    371382     * it's presentation attributes, style attributes and animated tracks.
     383     * @throws com.kitfox.svg.SVGException
    372384     */
    373385    protected void build() throws SVGException
     
    420432     * Hack to allow nodes to temporarily change their parents. The Use tag will
    421433     * need this so it can alter the attributes that a particular node uses.
     434     * @param context
    422435     */
    423436    protected void pushParentContext(SVGElement context)
     
    465478     * style attribute, checks attributes of parents back to root until one
    466479     * found.
     480     * @return
    467481     */
    468482    public boolean getStyle(StyleAttribute attrib, boolean recursive) throws SVGException
     
    523537
    524538    /**
     539     * @param styName
    525540     * @return the raw style value of this attribute. Does not take the
    526541     * presentation value or animation into consideration. Used by animations to
     
    536551     * Copies the presentation attribute into the passed one.
    537552     *
     553     * @param attrib
    538554     * @return - True if attribute was read successfully
     555     * @throws com.kitfox.svg.SVGException
    539556     */
    540557    public boolean getPres(StyleAttribute attrib) throws SVGException
     
    558575
    559576    /**
     577     * @param styName
    560578     * @return the raw presentation value of this attribute. Ignores any
    561579     * modifications applied by style attributes or animation. Used by
     
    810828     * all attributes with track information.
    811829     *
     830     * @param curTime
    812831     * @return - true if this node has changed state as a result of the time
    813832     * update
     833     * @throws com.kitfox.svg.SVGException
    814834     */
    815835    abstract public boolean updateTime(double curTime) throws SVGException;
  • trunk/src/com/kitfox/svg/SVGElementException.java

    r8084 r14328  
    4949    /**
    5050     * Creates a new instance of <code>SVGException</code> without detail message.
     51     * @param element
    5152     */
    5253    public SVGElementException(SVGElement element)
     
    5859    /**
    5960     * Constructs an instance of <code>SVGException</code> with the specified detail message.
     61     * @param element
    6062     * @param msg the detail message.
    6163     */
  • trunk/src/com/kitfox/svg/SVGLoader.java

    r11525 r14328  
    7676
    7777    final boolean verbose;
    78 
    79     /** Creates a new instance of SVGLoader */
     78   
     79    /**
     80     * Creates a new instance of SVGLoader
     81     * @param xmlBase
     82     * @param universe
     83     */
    8084    public SVGLoader(URI xmlBase, SVGUniverse universe)
    8185    {
  • trunk/src/com/kitfox/svg/SVGLoaderHelper.java

    r11525 r14328  
    5757    public final URI xmlBase;
    5858
    59     /** Creates a new instance of SVGLoaderHelper */
     59    /**
     60     * Creates a new instance of SVGLoaderHelper
     61     * @param xmlBase
     62     * @param universe
     63     * @param diagram
     64     */
    6065    public SVGLoaderHelper(URI xmlBase, SVGUniverse universe, SVGDiagram diagram)
    6166    {
  • trunk/src/com/kitfox/svg/SVGUniverse.java

    r11525 r14328  
    105105    XMLReader cachedReader;
    106106
     107    //If true, <imageSVG> elements will only load image data that is included using inline data: uris
     108    private boolean imageDataInlineOnly = false;
     109
    107110    /**
    108111     * Creates a new instance of SVGUniverse
     
    130133        loadedFonts.clear();
    131134        loadedImages.clear();
     135    }
     136
     137    /**
     138     * Returns the current animation time in milliseconds.
     139     */
     140    public double getCurTime()
     141    {
     142        return curTime;
     143    }
     144
     145    public void setCurTime(double curTime)
     146    {
     147        double oldTime = this.curTime;
     148        this.curTime = curTime;
     149        changes.firePropertyChange("curTime", new Double(oldTime), new Double(curTime));
     150    }
     151
     152    /**
     153     * Updates all time influenced style and presentation attributes in all SVG
     154     * documents in this universe.
     155     */
     156    public void updateTime() throws SVGException
     157    {
     158        for (SVGDiagram dia : loadedDocs.values()) {
     159            dia.updateTime(curTime);
     160        }
    132161    }
    133162
     
    648677        return universe;
    649678    }
     679
     680    /**
     681     * @return the imageDataInlineOnly
     682     */
     683    public boolean isImageDataInlineOnly()
     684    {
     685        return imageDataInlineOnly;
     686    }
     687
     688    /**
     689     * @param imageDataInlineOnly the imageDataInlineOnly to set
     690     */
     691    public void setImageDataInlineOnly(boolean imageDataInlineOnly)
     692    {
     693        this.imageDataInlineOnly = imageDataInlineOnly;
     694    }
    650695}
  • trunk/src/com/kitfox/svg/Text.java

    r11525 r14328  
    272272        for (int i = 0; i < families.length; ++i)
    273273        {
    274             font = diagram.getUniverse().getFont(fontFamily);
     274            font = diagram.getUniverse().getFont(families[i]);
    275275            if (font != null)
    276276            {
     
    278278            }
    279279        }
    280        
     280
    281281        if (font == null)
    282282        {
    283             font = new FontSystem(fontFamily, fontStyle, fontWeight, (int)fontSize);
     283            //Check system fonts
     284            font = FontSystem.createFont(fontFamily, fontStyle, fontWeight, (int)fontSize);
     285        }
     286
     287        if (font == null)
     288        {
     289            font = FontSystem.createFont("Serif", fontStyle, fontWeight, fontStyle);
    284290        }
    285291
  • trunk/src/com/kitfox/svg/Tspan.java

    r11525 r14328  
    231231        if (font == null)
    232232        {
    233             font = new FontSystem(fontFamily, fontStyle, fontWeight, (int)fontSize);
     233            font = FontSystem.createFont(fontFamily, fontStyle, fontWeight, (int)fontSize);
    234234        }
    235235
  • trunk/src/com/kitfox/svg/pathcmd/Arc.java

    r11525 r14328  
    104104     * point of the arc.
    105105     *
     106     * @param path The path that the arc will be appended to.
     107     *
    106108     * @param rx the x radius of the ellipse
    107109     * @param ry the y radius of the ellipse
     
    160162     * AffineTransform.getRotateInstance
    161163     *     (angle, arc.getX()+arc.getWidth()/2, arc.getY()+arc.getHeight()/2);
     164     *
     165     * @param x0 origin of arc in x
     166     * @param y0 origin of arc in y
     167     * @param rx radius of arc in x
     168     * @param ry radius of arc in y
     169     * @param angle number of radians in arc
     170     * @param largeArcFlag
     171     * @param sweepFlag
     172     * @param x ending coordinate of arc in x
     173     * @param y ending coordinate of arc in y
     174     * @return arc shape
     175     *
    162176     */
    163177    public static Arc2D computeArc(double x0, double y0,
  • trunk/src/com/kitfox/svg/util/FontSystem.java

    r11525 r14328  
    4242import java.awt.Canvas;
    4343import java.awt.FontMetrics;
     44import java.awt.GraphicsEnvironment;
    4445import java.awt.font.FontRenderContext;
    4546import java.awt.font.GlyphMetrics;
    4647import java.awt.font.GlyphVector;
    4748import java.util.HashMap;
     49import java.util.HashSet;
    4850
    4951/**
     
    5860    HashMap<String, Glyph> glyphCache = new HashMap<String, Glyph>();
    5961   
    60     public FontSystem(String fontFamily, int fontStyle, int fontWeight, int fontSize)
     62    static HashSet<String> sysFontNames = new HashSet<String>();
     63
     64    public static boolean checkIfSystemFontExists(String fontName)
     65    {
     66        if (sysFontNames.isEmpty())
     67        {
     68            for (String name: GraphicsEnvironment.getLocalGraphicsEnvironment().getAvailableFontFamilyNames())
     69            {
     70                sysFontNames.add(name);
     71            }
     72        }
     73
     74        return sysFontNames.contains(fontName);
     75    }
     76
     77    public static FontSystem createFont(String fontFamily, int fontStyle, int fontWeight, int fontSize)
     78    {
     79        String[] families = fontFamily.split(",");
     80        for (String fontName: families)
     81        {
     82            if (checkIfSystemFontExists(fontName))
     83            {
     84                return new FontSystem(fontName, fontStyle, fontWeight, fontSize);
     85            }
     86        }
     87
     88        return null;
     89    }
     90
     91    private FontSystem(String fontFamily, int fontStyle, int fontWeight, int fontSize)
    6192    {
    6293        int style;
     
    82113                break;
    83114        }
    84         sysFont = new java.awt.Font(fontFamily, style | weight, (int) fontSize);
     115
     116        sysFont = new java.awt.Font(fontFamily, style | weight, fontSize);
    85117       
    86118        Canvas c = new Canvas();
     
    100132        GlyphVector vec = sysFont.createGlyphVector(frc, unicode);
    101133       
    102         Glyph glyph = (Glyph)glyphCache.get(unicode);
     134        Glyph glyph = glyphCache.get(unicode);
    103135        if (glyph == null)
    104136        {
     
    107139
    108140            GlyphMetrics gm = vec.getGlyphMetrics(0);
    109             glyph.setHorizAdvX((int)gm.getAdvanceX());
    110             glyph.setVertAdvY((int)gm.getAdvanceY());
     141            glyph.setHorizAdvX(gm.getAdvanceX());
     142            glyph.setVertAdvY(gm.getAdvanceY());
    111143            glyph.setVertOriginX(0);
    112144            glyph.setVertOriginY(0);
  • trunk/src/org/openstreetmap/josm/tools/ImageProvider.java

    r14290 r14328  
    16561656        if (svgUniverse == null) {
    16571657            svgUniverse = new SVGUniverse();
     1658            // CVE-2017-5617: Allow only data scheme (see #14319)
     1659            svgUniverse.setImageDataInlineOnly(true);
    16581660        }
    16591661        return svgUniverse;
Note: See TracChangeset for help on using the changeset viewer.