cxf-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From dk...@apache.org
Subject svn commit: r724942 - in /cxf/trunk: api/src/main/java/org/apache/cxf/ws/policy/ common/common/src/main/java/org/apache/cxf/helpers/ rt/core/src/main/java/org/apache/cxf/wsdl11/ rt/ws/security/src/main/java/org/apache/cxf/ws/security/policy/builders/ r...
Date Wed, 10 Dec 2008 00:52:04 GMT
Author: dkulp
Date: Tue Dec  9 16:52:04 2008
New Revision: 724942

URL: http://svn.apache.org/viewvc?rev=724942&view=rev
Log:
Start toward getting a STSClient 

Added:
    cxf/trunk/rt/ws/security/src/main/java/org/apache/cxf/ws/security/trust/
    cxf/trunk/rt/ws/security/src/main/java/org/apache/cxf/ws/security/trust/STSClient.java
  (with props)
Modified:
    cxf/trunk/api/src/main/java/org/apache/cxf/ws/policy/PolicyBuilder.java
    cxf/trunk/common/common/src/main/java/org/apache/cxf/helpers/DOMUtils.java
    cxf/trunk/rt/core/src/main/java/org/apache/cxf/wsdl11/WSDLServiceFactory.java
    cxf/trunk/rt/ws/security/src/main/java/org/apache/cxf/ws/security/policy/builders/TransportBindingBuilder.java
    cxf/trunk/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/policyhandlers/TransportBindingHandler.java

Modified: cxf/trunk/api/src/main/java/org/apache/cxf/ws/policy/PolicyBuilder.java
URL: http://svn.apache.org/viewvc/cxf/trunk/api/src/main/java/org/apache/cxf/ws/policy/PolicyBuilder.java?rev=724942&r1=724941&r2=724942&view=diff
==============================================================================
--- cxf/trunk/api/src/main/java/org/apache/cxf/ws/policy/PolicyBuilder.java (original)
+++ cxf/trunk/api/src/main/java/org/apache/cxf/ws/policy/PolicyBuilder.java Tue Dec  9 16:52:04
2008
@@ -19,8 +19,15 @@
 
 package org.apache.cxf.ws.policy;
 
+import java.io.IOException;
+import java.io.InputStream;
+
+import javax.xml.parsers.ParserConfigurationException;
+
 import org.w3c.dom.Element;
 
+import org.xml.sax.SAXException;
+
 import org.apache.neethi.Policy;
 import org.apache.neethi.PolicyReference;
 
@@ -45,4 +52,14 @@
      * @return the Policy object constructed from the element
      */
     Policy getPolicy(Element element);
+    
+    
+    /**
+     * Creates a Policy object from an InputStream.
+     * 
+     * @param stream the inputstream
+     * @return the Policy object constructed from the element
+     */
+    Policy getPolicy(InputStream stream)
+        throws IOException, ParserConfigurationException, SAXException;
 }

Modified: cxf/trunk/common/common/src/main/java/org/apache/cxf/helpers/DOMUtils.java
URL: http://svn.apache.org/viewvc/cxf/trunk/common/common/src/main/java/org/apache/cxf/helpers/DOMUtils.java?rev=724942&r1=724941&r2=724942&view=diff
==============================================================================
--- cxf/trunk/common/common/src/main/java/org/apache/cxf/helpers/DOMUtils.java (original)
+++ cxf/trunk/common/common/src/main/java/org/apache/cxf/helpers/DOMUtils.java Tue Dec  9
16:52:04 2008
@@ -22,6 +22,7 @@
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
+import java.io.Reader;
 import java.io.StringReader;
 import java.util.LinkedList;
 import java.util.List;
@@ -341,6 +342,25 @@
 
         return db.parse(is);
     }
+    public static Document readXml(Reader is) throws SAXException, IOException,
+        ParserConfigurationException {
+        DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
+    
+        dbf.setValidating(false);
+        dbf.setIgnoringComments(false);
+        dbf.setIgnoringElementContentWhitespace(true);
+        dbf.setNamespaceAware(true);
+        // dbf.setCoalescing(true);
+        // dbf.setExpandEntityReferences(true);
+    
+        DocumentBuilder db = null;
+        db = dbf.newDocumentBuilder();
+        db.setEntityResolver(new NullResolver());
+    
+        // db.setErrorHandler( new MyErrorHandler());
+        InputSource ips = new InputSource(is);
+        return db.parse(ips);
+    }
     public static Document readXml(StreamSource is) throws SAXException, IOException,
         ParserConfigurationException {
         

Modified: cxf/trunk/rt/core/src/main/java/org/apache/cxf/wsdl11/WSDLServiceFactory.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/core/src/main/java/org/apache/cxf/wsdl11/WSDLServiceFactory.java?rev=724942&r1=724941&r2=724942&view=diff
==============================================================================
--- cxf/trunk/rt/core/src/main/java/org/apache/cxf/wsdl11/WSDLServiceFactory.java (original)
+++ cxf/trunk/rt/core/src/main/java/org/apache/cxf/wsdl11/WSDLServiceFactory.java Tue Dec
 9 16:52:04 2008
@@ -69,6 +69,15 @@
         }
 
     }
+    public WSDLServiceFactory(Bus b, String url) {
+        setBus(b);
+        try {
+            // use wsdl manager to parse wsdl or get cached definition
+            definition = getBus().getExtension(WSDLManager.class).getDefinition(url);
+        } catch (WSDLException ex) {
+            throw new ServiceConstructionException(new Message("SERVICE_CREATION_MSG", LOG),
ex);
+        }
+    }
 
     public WSDLServiceFactory(Bus b, URL url, QName sn) {
         this(b, url);

Modified: cxf/trunk/rt/ws/security/src/main/java/org/apache/cxf/ws/security/policy/builders/TransportBindingBuilder.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/ws/security/src/main/java/org/apache/cxf/ws/security/policy/builders/TransportBindingBuilder.java?rev=724942&r1=724941&r2=724942&view=diff
==============================================================================
--- cxf/trunk/rt/ws/security/src/main/java/org/apache/cxf/ws/security/policy/builders/TransportBindingBuilder.java
(original)
+++ cxf/trunk/rt/ws/security/src/main/java/org/apache/cxf/ws/security/policy/builders/TransportBindingBuilder.java
Tue Dec  9 16:52:04 2008
@@ -29,6 +29,7 @@
 import org.apache.cxf.ws.policy.AssertionBuilder;
 import org.apache.cxf.ws.policy.PolicyAssertion;
 import org.apache.cxf.ws.policy.PolicyBuilder;
+import org.apache.cxf.ws.policy.PolicyConstants;
 import org.apache.cxf.ws.security.policy.SP11Constants;
 import org.apache.cxf.ws.security.policy.SP12Constants;
 import org.apache.cxf.ws.security.policy.SPConstants;
@@ -67,35 +68,41 @@
     private void processAlternative(Element element, 
                                     TransportBinding parent,
                                     SPConstants consts) {
-        Element polEl = DOMUtils.getFirstChildWithName(element, SPConstants.POLICY);
-        if (polEl != null) {
-            Element child = DOMUtils.getFirstElement(polEl);
-            while (child != null) {
-                String name = child.getLocalName();
-                if (name.equals(SPConstants.ALGO_SUITE)) {
-                    parent.setAlgorithmSuite((AlgorithmSuite)new AlgorithmSuiteBuilder().build(child));
-                } else if (name.equals(SPConstants.TRANSPORT_TOKEN)) {
-                    parent.setTransportToken((TransportToken)new TransportTokenBuilder(builder)
-                                                    .build(child));
-                } else if (name.equals(SPConstants.INCLUDE_TIMESTAMP)) {
-                    parent.setIncludeTimestamp(true);
-                } else if (name.equals(SPConstants.LAYOUT)) {
-                    parent.setLayout((Layout)new LayoutBuilder().build(child));
-                } else if (name.equals(SPConstants.SIGNED_SUPPORTING_TOKENS)
-                    || name.equals(SPConstants.SIGNED_ENDORSING_SUPPORTING_TOKENS)) {
-                    
-                    if (consts.getVersion() == SPConstants.Version.SP_V11) {
-                        parent.setSignedSupportingToken((SupportingToken)new SupportingTokensBuilder(builder)
+        Element polEl = DOMUtils.getFirstElement(element);
+        while (polEl != null) {
+            if (PolicyConstants.isPolicyElem(new QName(polEl.getNamespaceURI(),
+                                                       polEl.getLocalName()))) {
+                Element child = DOMUtils.getFirstElement(polEl);
+                while (child != null) {
+                    String name = child.getLocalName();
+                    if (name.equals(SPConstants.ALGO_SUITE)) {
+                        parent.setAlgorithmSuite((AlgorithmSuite)new AlgorithmSuiteBuilder().build(child));
+                    } else if (name.equals(SPConstants.TRANSPORT_TOKEN)) {
+                        parent.setTransportToken((TransportToken)new TransportTokenBuilder(builder)
                                                         .build(child));
-                    } else {
-                        parent.setSignedSupportingToken((SupportingToken)
-                                                        new SupportingTokens12Builder(builder)
-                                                            .build(child));             
          
+                    } else if (name.equals(SPConstants.INCLUDE_TIMESTAMP)) {
+                        parent.setIncludeTimestamp(true);
+                    } else if (name.equals(SPConstants.LAYOUT)) {
+                        parent.setLayout((Layout)new LayoutBuilder().build(child));
+                    } else if (name.equals(SPConstants.SIGNED_SUPPORTING_TOKENS)
+                        || name.equals(SPConstants.SIGNED_ENDORSING_SUPPORTING_TOKENS)) {
+                        
+                        if (consts.getVersion() == SPConstants.Version.SP_V11) {
+                            parent.setSignedSupportingToken((SupportingToken)
+                                                            new SupportingTokensBuilder(builder)
+                                                            .build(child));
+                        } else {
+                            parent.setSignedSupportingToken((SupportingToken)
+                                                            new SupportingTokens12Builder(builder)
+                                                                .build(child));         
              
+                        }
                     }
+                    child = DOMUtils.getNextElement(child);
                 }
-                child = DOMUtils.getNextElement(child);
             }
+            polEl = DOMUtils.getNextElement(polEl);
         }
+        
     }
 
     public PolicyAssertion buildCompatible(PolicyAssertion a, PolicyAssertion b) {

Added: cxf/trunk/rt/ws/security/src/main/java/org/apache/cxf/ws/security/trust/STSClient.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/ws/security/src/main/java/org/apache/cxf/ws/security/trust/STSClient.java?rev=724942&view=auto
==============================================================================
--- cxf/trunk/rt/ws/security/src/main/java/org/apache/cxf/ws/security/trust/STSClient.java
(added)
+++ cxf/trunk/rt/ws/security/src/main/java/org/apache/cxf/ws/security/trust/STSClient.java
Tue Dec  9 16:52:04 2008
@@ -0,0 +1,185 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.cxf.ws.security.trust;
+
+import java.io.StringReader;
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.xml.namespace.QName;
+import javax.xml.transform.dom.DOMSource;
+
+import org.apache.cxf.Bus;
+import org.apache.cxf.BusException;
+import org.apache.cxf.binding.BindingFactory;
+import org.apache.cxf.binding.BindingFactoryManager;
+import org.apache.cxf.binding.soap.SoapBindingConstants;
+import org.apache.cxf.binding.soap.model.SoapOperationInfo;
+import org.apache.cxf.databinding.source.SourceDataBinding;
+import org.apache.cxf.endpoint.Client;
+import org.apache.cxf.endpoint.ClientImpl;
+import org.apache.cxf.endpoint.Endpoint;
+import org.apache.cxf.endpoint.EndpointException;
+import org.apache.cxf.endpoint.EndpointImpl;
+import org.apache.cxf.helpers.DOMUtils;
+import org.apache.cxf.service.Service;
+import org.apache.cxf.service.ServiceImpl;
+import org.apache.cxf.service.model.BindingInfo;
+import org.apache.cxf.service.model.BindingOperationInfo;
+import org.apache.cxf.service.model.EndpointInfo;
+import org.apache.cxf.service.model.InterfaceInfo;
+import org.apache.cxf.service.model.MessageInfo;
+import org.apache.cxf.service.model.MessagePartInfo;
+import org.apache.cxf.service.model.OperationInfo;
+import org.apache.cxf.service.model.ServiceInfo;
+import org.apache.cxf.transport.ConduitInitiator;
+import org.apache.cxf.transport.ConduitInitiatorManager;
+import org.apache.cxf.ws.security.policy.model.Trust10;
+import org.apache.cxf.ws.security.policy.model.Trust13;
+import org.apache.cxf.ws.security.tokenstore.SecurityToken;
+import org.apache.neethi.Policy;
+
+/**
+ * 
+ */
+public class STSClient {
+    Bus bus;
+    Client client;
+    String location;
+    Policy policy;
+    String soapVersion = SoapBindingConstants.SOAP11_BINDING_ID;
+    
+    Map<String, Object> ctx = new HashMap<String, Object>();
+    
+    public STSClient(Bus b) {
+        bus = b;
+    }
+
+    public void setLocation(String location) {
+        this.location = location;
+    }
+    public void setPolicy(Policy policy) {
+        this.policy = policy;
+    }
+    public void setSoap12() {
+        soapVersion = SoapBindingConstants.SOAP12_BINDING_ID;
+    }
+    public void setSoap11() {
+        soapVersion = SoapBindingConstants.SOAP11_BINDING_ID;
+    }
+    public void setTrust(Trust10 trust) {
+        
+    }
+    public void setTrust(Trust13 trust) {
+        
+    }
+    private void createClient() throws BusException, EndpointException {
+        if (client != null) {
+            return;
+        }
+        Service service = null;
+        String ns = "http://schemas.xmlsoap.org/ws/2005/02/trust/wsdl";
+        String typeNs = "http://schemas.xmlsoap.org/ws/2005/02/trust";
+        ServiceInfo si = new ServiceInfo();
+        
+        QName iName = new QName(ns, "SecurityTokenService");
+        si.setName(iName);
+        InterfaceInfo ii = new InterfaceInfo(si, iName);
+        OperationInfo oi = ii.addOperation(new QName(ns, "RequestSecurityToken"));
+        MessageInfo mii = oi.createMessage(new QName(ns, "RequestSecurityTokenMsg"), 
+                                           MessageInfo.Type.INPUT);
+        oi.setInput("RequestSecurityTokenMsg", mii);
+        MessagePartInfo mpi = mii.addMessagePart("request");
+        mpi.setElementQName(new QName(typeNs, "RequestSecurityToken"));
+        
+        MessageInfo mio = oi.createMessage(new QName(ns, "RequestSecurityTokenResponseMsg"),

+                                           MessageInfo.Type.OUTPUT);
+        oi.setOutput("RequestSecurityTokenResponseMsg", mio);
+        mpi = mio.addMessagePart("response");
+        mpi.setElementQName(new QName(typeNs, "RequestSecurityTokenResponse"));
+        
+        si.setInterface(ii);
+        service = new ServiceImpl(si);
+        
+        BindingFactoryManager bfm = bus.getExtension(BindingFactoryManager.class);
+        BindingFactory bindingFactory = bfm.getBindingFactory(soapVersion);
+        BindingInfo bi = bindingFactory.createBindingInfo(service, 
+                                                          soapVersion, null);
+        si.addBinding(bi);
+        ConduitInitiatorManager cim = bus.getExtension(ConduitInitiatorManager.class);
+        ConduitInitiator ci = cim.getConduitInitiatorForUri(location);
+        EndpointInfo ei = new EndpointInfo(si, ci.getTransportIds().get(0));
+        ei.setBinding(bi);
+        ei.setName(iName);
+        ei.setAddress(location);
+        si.addEndpoint(ei);
+        ei.addExtensor(policy);
+        
+        BindingOperationInfo boi = bi.getOperation(oi);
+        SoapOperationInfo soi = boi.getExtensor(SoapOperationInfo.class);
+        if (soi == null) {
+            soi = new SoapOperationInfo();
+            boi.addExtensor(soi);
+        }
+        soi.setAction("http://schemas.xmlsoap.org/ws/2005/02/trust/RST/Issue");
+        
+
+        service.setDataBinding(new SourceDataBinding());
+        Endpoint endpoint = new EndpointImpl(bus, service, ei);
+        
+        client = new ClientImpl(bus, endpoint);
+        
+    }
+
+    public Map<String, Object> getRequestContext() throws Exception {
+        return ctx;
+    }
+    public SecurityToken requestSecurityToken() throws Exception {
+        createClient();
+        client.getRequestContext().putAll(ctx);
+        
+        //TODO: create the DOM based on the Trust10/Trust13 tokens
+        String rqst = "<t:RequestSecurityToken " 
+            + "xmlns:u='http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd'
"
+            + "xmlns:t='http://schemas.xmlsoap.org/ws/2005/02/trust'>\n"
+            + "<t:RequestType>"
+            + "http://schemas.xmlsoap.org/ws/2005/02/trust/Issue"
+            + "</t:RequestType>\n"
+            + "<t:Entropy>\n"
+            + "<t:BinarySecret u:Id='uuid-4acf589c-0076-4a83-8b66-5f29341514b7-3'"
+            + " Type='http://schemas.xmlsoap.org/ws/2005/02/trust/Nonce'>"
+            + "Uv38QLxDQM9gLoDZ6OwYDiFk094nmwu3Wmay7EdKmhw=</t:BinarySecret>\n"
+            + "</t:Entropy>\n"
+            + "<t:KeyType>http://schemas.xmlsoap.org/ws/2005/02/trust/SymmetricKey</t:KeyType>\n"
+            + "<t:KeySize>256</t:KeySize>\n"
+            + "<t:ComputedKeyAlgorithm>\n"
+            + "http://schemas.xmlsoap.org/ws/2005/02/trust/CK/PSHA1"
+            + "</t:ComputedKeyAlgorithm>\n"
+            + "</t:RequestSecurityToken>\n";
+
+        
+        client.invoke("RequestSecurityToken",
+                      new DOMSource(DOMUtils.readXml(new StringReader(rqst)).getDocumentElement()));
+        return null;
+    }
+
+   
+
+}

Propchange: cxf/trunk/rt/ws/security/src/main/java/org/apache/cxf/ws/security/trust/STSClient.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cxf/trunk/rt/ws/security/src/main/java/org/apache/cxf/ws/security/trust/STSClient.java
------------------------------------------------------------------------------
    svn:keywords = Rev Date

Modified: cxf/trunk/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/policyhandlers/TransportBindingHandler.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/policyhandlers/TransportBindingHandler.java?rev=724942&r1=724941&r2=724942&view=diff
==============================================================================
--- cxf/trunk/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/policyhandlers/TransportBindingHandler.java
(original)
+++ cxf/trunk/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/policyhandlers/TransportBindingHandler.java
Tue Dec  9 16:52:04 2008
@@ -20,15 +20,19 @@
 package org.apache.cxf.ws.security.wss4j.policyhandlers;
 
 import java.util.Collection;
+import java.util.Vector;
 
+import javax.xml.soap.SOAPException;
 import javax.xml.soap.SOAPMessage;
 
 import org.apache.cxf.binding.soap.SoapMessage;
+import org.apache.cxf.interceptor.Fault;
 import org.apache.cxf.ws.policy.AssertionInfo;
 import org.apache.cxf.ws.policy.AssertionInfoMap;
 import org.apache.cxf.ws.security.policy.SP12Constants;
 import org.apache.cxf.ws.security.policy.model.SupportingToken;
 import org.apache.cxf.ws.security.policy.model.TransportBinding;
+import org.apache.ws.security.WSEncryptionPart;
 import org.apache.ws.security.message.WSSecHeader;
 import org.apache.ws.security.message.WSSecTimestamp;
 
@@ -51,18 +55,67 @@
         Collection<AssertionInfo> ais;
         WSSecTimestamp timestamp = createTimestamp();
         handleLayout(timestamp);
-        
-        ais = aim.get(SP12Constants.SIGNED_SUPPORTING_TOKENS);
-        if (ais != null) {
-            SupportingToken sgndSuppTokens = null;
-            for (AssertionInfo ai : ais) {
-                sgndSuppTokens = (SupportingToken)ai.getAssertion();
-                ai.setAsserted(true);
-            }
-            if (sgndSuppTokens != null && sgndSuppTokens.getTokens() != null 
-                && sgndSuppTokens.getTokens().size() > 0) {
-                handleSupportingTokens(sgndSuppTokens);
+        try {
+            Vector<WSEncryptionPart> sigParts = getSignedParts();
+            if (this.isRequestor()) {
+                ais = aim.get(SP12Constants.SIGNED_SUPPORTING_TOKENS);
+                if (ais != null) {
+                    SupportingToken sgndSuppTokens = null;
+                    for (AssertionInfo ai : ais) {
+                        sgndSuppTokens = (SupportingToken)ai.getAssertion();
+                        ai.setAsserted(true);
+                    }
+                    if (sgndSuppTokens != null && sgndSuppTokens.getTokens() != null

+                        && sgndSuppTokens.getTokens().size() > 0) {
+                        addSignatureParts(handleSupportingTokens(sgndSuppTokens), sigParts);
+                    }
+                }
+                ais = aim.get(SP12Constants.SIGNED_ENDORSING_SUPPORTING_TOKENS);
+                if (ais != null) {
+                    SupportingToken sgndSuppTokens = null;
+                    for (AssertionInfo ai : ais) {
+                        sgndSuppTokens = (SupportingToken)ai.getAssertion();
+                        ai.setAsserted(true);
+                    }
+                    if (sgndSuppTokens != null && sgndSuppTokens.getTokens() != null

+                        && sgndSuppTokens.getTokens().size() > 0) {
+                        doEndorsedSignatures(handleSupportingTokens(sgndSuppTokens), false);
+                    }
+                }
+                ais = aim.get(SP12Constants.ENDORSING_SUPPORTING_TOKENS);
+                if (ais != null) {
+                    SupportingToken sgndSuppTokens = null;
+                    for (AssertionInfo ai : ais) {
+                        sgndSuppTokens = (SupportingToken)ai.getAssertion();
+                        ai.setAsserted(true);
+                    }
+                    if (sgndSuppTokens != null && sgndSuppTokens.getTokens() != null

+                        && sgndSuppTokens.getTokens().size() > 0) {
+                        
+                        
+                        doEndorsedSignatures(handleSupportingTokens(sgndSuppTokens), false);
+                    }
+                }
+                
+                ais = aim.get(SP12Constants.SUPPORTING_TOKENS);
+                if (ais != null) {
+                    SupportingToken suppTokens = null;
+                    for (AssertionInfo ai : ais) {
+                        suppTokens = (SupportingToken)ai.getAssertion();
+                        ai.setAsserted(true);
+                    }
+                    if (suppTokens != null && suppTokens.getTokens() != null 
+                        && suppTokens.getTokens().size() > 0) {
+                        handleSupportingTokens(suppTokens);
+                    }
+                }
+
+            } else {
+                addSignatureConfirmation(null);
             }
+
+        } catch (SOAPException e) {
+            throw new Fault(e);
         }
     }
 



Mime
View raw message