moved to helma.scripting.fesi.extensions package
This commit is contained in:
parent
b00f663f47
commit
6cdad2233f
5 changed files with 0 additions and 2079 deletions
File diff suppressed because it is too large
Load diff
|
@ -1,196 +0,0 @@
|
||||||
// ESMail.java
|
|
||||||
// Copyright (c) Hannes Wallnöfer 1998-2000
|
|
||||||
|
|
||||||
|
|
||||||
package helma.framework.extensions;
|
|
||||||
|
|
||||||
import javax.mail.*;
|
|
||||||
import javax.mail.internet.*;
|
|
||||||
import javax.activation.*;
|
|
||||||
import java.io.*;
|
|
||||||
import java.util.*;
|
|
||||||
import helma.main.Server;
|
|
||||||
import helma.framework.core.*;
|
|
||||||
import helma.util.*;
|
|
||||||
import FESI.Data.*;
|
|
||||||
import FESI.Interpreter.*;
|
|
||||||
import FESI.Exceptions.*;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A JavaScript wrapper around a JavaMail message class to send
|
|
||||||
* mail via SMTP from HOP
|
|
||||||
*/
|
|
||||||
|
|
||||||
public class ESMail extends ESObject implements Serializable {
|
|
||||||
|
|
||||||
MailExtension mailx;
|
|
||||||
Properties mprops;
|
|
||||||
MimeMessage message;
|
|
||||||
Multipart multipart;
|
|
||||||
StringBuffer buffer;
|
|
||||||
|
|
||||||
int status;
|
|
||||||
public static final int OK=0;
|
|
||||||
public static final int SUBJECT=10;
|
|
||||||
public static final int TEXT=11;
|
|
||||||
public static final int MIMEPART=12;
|
|
||||||
public static final int TO=20;
|
|
||||||
public static final int CC=21;
|
|
||||||
public static final int BCC=22;
|
|
||||||
public static final int FROM=23;
|
|
||||||
public static final int REPLYTO=24;
|
|
||||||
public static final int SEND=30;
|
|
||||||
|
|
||||||
|
|
||||||
public ESMail (MailExtension mailx) {
|
|
||||||
|
|
||||||
super (mailx.esMailPrototype, mailx.evaluator);
|
|
||||||
this.status = OK;
|
|
||||||
this.mailx = mailx;
|
|
||||||
this.mprops = mailx.mprops;
|
|
||||||
|
|
||||||
// create some properties and get the default Session
|
|
||||||
try {
|
|
||||||
Properties props = new Properties();
|
|
||||||
props.put ("mail.smtp.host", mprops.getProperty ("smtp", "mail"));
|
|
||||||
|
|
||||||
Session session = Session.getDefaultInstance(props, null);
|
|
||||||
message = new MimeMessage (session);
|
|
||||||
} catch (Throwable t) {
|
|
||||||
Server.getLogger().log ("caught in mail constructor: "+t);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setStatus (int status) {
|
|
||||||
// Only register the first error that occurrs
|
|
||||||
if (this.status == 0)
|
|
||||||
this.status = status;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getStatus () {
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ESValue getProperty(String propertyName, int hash) throws EcmaScriptException {
|
|
||||||
if ("status".equalsIgnoreCase (propertyName))
|
|
||||||
return new ESNumber (status);
|
|
||||||
return super.getProperty (propertyName, hash);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
public void setText (ESValue val) throws Exception {
|
|
||||||
if (buffer == null)
|
|
||||||
buffer = new StringBuffer ();
|
|
||||||
if (val != null)
|
|
||||||
buffer.append (val.toString ());
|
|
||||||
}
|
|
||||||
|
|
||||||
public void addPart (ESValue val[]) throws Exception {
|
|
||||||
if (val == null || val.length == 0) return;
|
|
||||||
if (multipart == null) {
|
|
||||||
multipart = new MimeMultipart ();
|
|
||||||
}
|
|
||||||
for (int i=0; i<val.length; i++) {
|
|
||||||
// FIXME: addPart is broken.
|
|
||||||
MimeBodyPart part = new MimeBodyPart ();
|
|
||||||
Object obj = val[i].toJavaObject ();
|
|
||||||
if (obj instanceof String) {
|
|
||||||
part.setContent (obj.toString (), "text/plain");
|
|
||||||
} else if (obj instanceof File) {
|
|
||||||
FileDataSource source = new FileDataSource ((File) obj);
|
|
||||||
part.setDataHandler (new DataHandler (source));
|
|
||||||
}
|
|
||||||
multipart.addBodyPart (part);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setSubject (ESValue val) throws Exception {
|
|
||||||
if (val == null)
|
|
||||||
return;
|
|
||||||
message.setSubject (MimeUtility.encodeWord (val.toString (), "iso-8859-1", null));
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setReplyTo (ESValue add) throws Exception {
|
|
||||||
String addstring = add.toString ();
|
|
||||||
if (addstring.indexOf ("@") < 0)
|
|
||||||
throw new AddressException ();
|
|
||||||
Address replyTo[] = new Address[1];
|
|
||||||
replyTo[0] = new InternetAddress (addstring);
|
|
||||||
message.setReplyTo (replyTo);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setFrom (ESValue add[]) throws Exception {
|
|
||||||
String addstring = add[0].toString ();
|
|
||||||
if (addstring.indexOf ("@") < 0)
|
|
||||||
throw new AddressException ();
|
|
||||||
Address address = null;
|
|
||||||
if (add.length > 1)
|
|
||||||
address = new InternetAddress (addstring, MimeUtility.encodeWord (add[1].toString (), "iso-8859-1", null));
|
|
||||||
else
|
|
||||||
address = new InternetAddress (addstring);
|
|
||||||
message.setFrom (address);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void addTo (ESValue add[]) throws Exception {
|
|
||||||
String addstring = add[0].toString ();
|
|
||||||
if (addstring.indexOf ("@") < 0)
|
|
||||||
throw new AddressException ();
|
|
||||||
Address address = null;
|
|
||||||
if (add.length > 1)
|
|
||||||
address = new InternetAddress (addstring, MimeUtility.encodeWord (add[1].toString (), "iso-8859-1", null));
|
|
||||||
else
|
|
||||||
address = new InternetAddress (addstring);
|
|
||||||
message.addRecipient (Message.RecipientType.TO, address);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void addCC (ESValue add[]) throws Exception {
|
|
||||||
String addstring = add[0].toString ();
|
|
||||||
if (addstring.indexOf ("@") < 0)
|
|
||||||
throw new AddressException ();
|
|
||||||
Address address = null;
|
|
||||||
if (add.length > 1)
|
|
||||||
address = new InternetAddress (addstring, MimeUtility.encodeWord (add[1].toString (), "iso-8859-1", null));
|
|
||||||
else
|
|
||||||
address = new InternetAddress (addstring);
|
|
||||||
message.addRecipient (Message.RecipientType.CC, address);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void addBCC (ESValue add[]) throws Exception {
|
|
||||||
String addstring = add[0].toString ();
|
|
||||||
if (addstring.indexOf ("@") < 0)
|
|
||||||
throw new AddressException ();
|
|
||||||
Address address = null;
|
|
||||||
if (add.length > 1)
|
|
||||||
address = new InternetAddress (addstring, MimeUtility.encodeWord (add[1].toString (), "iso-8859-1", null));
|
|
||||||
else
|
|
||||||
address = new InternetAddress (addstring);
|
|
||||||
message.addRecipient (Message.RecipientType.BCC, address);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void send () throws Exception {
|
|
||||||
if (buffer != null)
|
|
||||||
message.setText (buffer.toString ());
|
|
||||||
else if (multipart != null)
|
|
||||||
message.setContent (multipart);
|
|
||||||
else
|
|
||||||
message.setText ("");
|
|
||||||
Transport.send (message);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,419 +0,0 @@
|
||||||
// FtpExtension.java
|
|
||||||
// Copyright (c) Hannes Wallnöfer 1998-2000
|
|
||||||
|
|
||||||
package helma.framework.extensions;
|
|
||||||
|
|
||||||
import helma.objectmodel.*;
|
|
||||||
import FESI.Parser.*;
|
|
||||||
import FESI.AST.*;
|
|
||||||
import FESI.Interpreter.*;
|
|
||||||
import FESI.Exceptions.*;
|
|
||||||
import FESI.Extensions.*;
|
|
||||||
import FESI.Data.*;
|
|
||||||
import java.io.*;
|
|
||||||
|
|
||||||
import com.oroinc.net.ftp.*;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A FTP-client object that allows to do some FTP from HOP applications.
|
|
||||||
* FTP support is far from complete but can easily be extended if more
|
|
||||||
* functionality is needed.
|
|
||||||
* This uses the NetComponent classes from savarese.org (ex oroinc.com).
|
|
||||||
*/
|
|
||||||
|
|
||||||
class ESFtpClient extends ESObject {
|
|
||||||
|
|
||||||
private FTPClient ftpclient;
|
|
||||||
private String server;
|
|
||||||
private Exception lastError = null;
|
|
||||||
private File localDir = null;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a new FTP Client
|
|
||||||
*
|
|
||||||
* @param prototype The prototype object for the FTP object
|
|
||||||
* @param evaluator The current evaluator
|
|
||||||
*/
|
|
||||||
ESFtpClient(ESObject prototype, Evaluator evaluator, ESValue srvstr) {
|
|
||||||
super(prototype, evaluator);
|
|
||||||
this.server = srvstr.toString ();
|
|
||||||
}
|
|
||||||
|
|
||||||
ESFtpClient(ESObject prototype, Evaluator evaluator) {
|
|
||||||
super(prototype, evaluator);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public String getESClassName() {
|
|
||||||
return "FtpClient";
|
|
||||||
}
|
|
||||||
|
|
||||||
public String toString() {
|
|
||||||
return "[FtpClient]";
|
|
||||||
}
|
|
||||||
|
|
||||||
public String toDetailString() {
|
|
||||||
return "ES:[Object: builtin " + this.getClass().getName() + ":" +
|
|
||||||
this.toString() + "]";
|
|
||||||
}
|
|
||||||
|
|
||||||
ESValue getLastError() throws EcmaScriptException {
|
|
||||||
if (lastError == null) {
|
|
||||||
return ESNull.theNull;
|
|
||||||
} else {
|
|
||||||
return ESLoader.normalizeValue(lastError, evaluator);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Login to the FTP server
|
|
||||||
*
|
|
||||||
* @param arguments The argument list
|
|
||||||
* @return true if successful, false otherwise
|
|
||||||
*/
|
|
||||||
ESValue login(ESValue arguments[]) throws EcmaScriptException {
|
|
||||||
if (server == null)
|
|
||||||
return ESBoolean.makeBoolean(false);
|
|
||||||
try {
|
|
||||||
ftpclient = new FTPClient ();
|
|
||||||
ftpclient.connect (server);
|
|
||||||
ftpclient.login (arguments[0].toString(), arguments[1].toString());
|
|
||||||
return ESBoolean.makeBoolean (true);
|
|
||||||
} catch (Exception x) {
|
|
||||||
return ESBoolean.makeBoolean (false);
|
|
||||||
} catch (NoClassDefFoundError x) {
|
|
||||||
return ESBoolean.makeBoolean (false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ESValue cd (ESValue arguments[]) throws EcmaScriptException {
|
|
||||||
if (ftpclient == null)
|
|
||||||
return ESBoolean.makeBoolean(false);
|
|
||||||
try {
|
|
||||||
ftpclient.changeWorkingDirectory (arguments[0].toString ());
|
|
||||||
return ESBoolean.makeBoolean(true);
|
|
||||||
} catch (Exception wrong) {}
|
|
||||||
return ESBoolean.makeBoolean(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
ESValue mkdir (ESValue arguments[]) throws EcmaScriptException {
|
|
||||||
if (ftpclient == null)
|
|
||||||
return ESBoolean.makeBoolean(false);
|
|
||||||
try {
|
|
||||||
return ESBoolean.makeBoolean(ftpclient.makeDirectory (arguments[0].toString ()));
|
|
||||||
} catch (Exception wrong) {}
|
|
||||||
return ESBoolean.makeBoolean(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
ESValue lcd (ESValue arguments[]) throws EcmaScriptException {
|
|
||||||
try {
|
|
||||||
localDir = new File (arguments[0].toString());
|
|
||||||
if (!localDir.exists())
|
|
||||||
localDir.mkdirs();
|
|
||||||
return ESBoolean.makeBoolean(true);
|
|
||||||
} catch (Exception wrong) {}
|
|
||||||
return ESBoolean.makeBoolean(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
ESValue putFile(ESValue arguments[]) throws EcmaScriptException {
|
|
||||||
if (ftpclient == null)
|
|
||||||
return ESBoolean.makeBoolean(false);
|
|
||||||
try {
|
|
||||||
String fn = arguments[0].toString();
|
|
||||||
File f = localDir == null ? new File (fn) : new File (localDir, fn);
|
|
||||||
InputStream fin = new BufferedInputStream (new FileInputStream (f));
|
|
||||||
ftpclient.storeFile (arguments[1].toString (), fin);
|
|
||||||
fin.close ();
|
|
||||||
return ESBoolean.makeBoolean(true);
|
|
||||||
} catch (Exception wrong) {}
|
|
||||||
return ESBoolean.makeBoolean(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
ESValue putString(ESValue arguments[]) throws EcmaScriptException {
|
|
||||||
if (ftpclient == null)
|
|
||||||
return ESBoolean.makeBoolean(false);
|
|
||||||
try {
|
|
||||||
byte[] bytes = null;
|
|
||||||
// check if this already is a byte array
|
|
||||||
if (arguments[0] instanceof ESArrayWrapper) {
|
|
||||||
Object o = ((ESArrayWrapper) arguments[0]).toJavaObject ();
|
|
||||||
if (o instanceof byte[])
|
|
||||||
bytes = (byte[]) o;
|
|
||||||
}
|
|
||||||
if (bytes == null)
|
|
||||||
bytes = arguments[0].toString().getBytes();
|
|
||||||
ByteArrayInputStream bin = new ByteArrayInputStream (bytes);
|
|
||||||
ftpclient.storeFile (arguments[1].toString (), bin);
|
|
||||||
return ESBoolean.makeBoolean(true);
|
|
||||||
} catch (Exception wrong) {}
|
|
||||||
return ESBoolean.makeBoolean(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
ESValue getFile(ESValue arguments[]) throws EcmaScriptException {
|
|
||||||
if (ftpclient == null )
|
|
||||||
return ESBoolean.makeBoolean(false);
|
|
||||||
try {
|
|
||||||
String fn = arguments[0].toString();
|
|
||||||
File f = localDir == null ? new File (fn) : new File (localDir, fn);
|
|
||||||
OutputStream out = new BufferedOutputStream (new FileOutputStream(f));
|
|
||||||
ftpclient.retrieveFile (arguments[0].toString (), out);
|
|
||||||
out.close ();
|
|
||||||
return ESBoolean.makeBoolean(true);
|
|
||||||
} catch (Exception wrong) {}
|
|
||||||
return ESBoolean.makeBoolean(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
ESValue getString(ESValue arguments[]) throws EcmaScriptException {
|
|
||||||
if (ftpclient == null )
|
|
||||||
return ESNull.theNull;
|
|
||||||
try {
|
|
||||||
ByteArrayOutputStream bout = new ByteArrayOutputStream ();
|
|
||||||
ftpclient.retrieveFile (arguments[0].toString (), bout);
|
|
||||||
return new ESString (bout.toString ());
|
|
||||||
} catch (Exception wrong) {}
|
|
||||||
return ESNull.theNull;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Disconnect from FTP server
|
|
||||||
*
|
|
||||||
* @param arguments The argument list
|
|
||||||
* @return true if successful, false otherwise
|
|
||||||
*/
|
|
||||||
ESValue logout (ESValue arguments[]) throws EcmaScriptException {
|
|
||||||
if (ftpclient != null) {
|
|
||||||
try {
|
|
||||||
ftpclient.logout ();
|
|
||||||
} catch (IOException ignore) {}
|
|
||||||
try {
|
|
||||||
ftpclient.disconnect ();
|
|
||||||
} catch (IOException ignore) {}
|
|
||||||
}
|
|
||||||
return ESBoolean.makeBoolean (true);
|
|
||||||
}
|
|
||||||
|
|
||||||
ESValue binary (ESValue arguments[]) throws EcmaScriptException {
|
|
||||||
if (ftpclient != null) {
|
|
||||||
try {
|
|
||||||
ftpclient.setFileType (FTP.BINARY_FILE_TYPE);
|
|
||||||
return ESBoolean.makeBoolean (true);
|
|
||||||
} catch (IOException ignore) {}
|
|
||||||
}
|
|
||||||
return ESBoolean.makeBoolean (false);
|
|
||||||
}
|
|
||||||
|
|
||||||
ESValue ascii (ESValue arguments[]) throws EcmaScriptException {
|
|
||||||
if (ftpclient != null) {
|
|
||||||
try {
|
|
||||||
ftpclient.setFileType (FTP.ASCII_FILE_TYPE);
|
|
||||||
return ESBoolean.makeBoolean (true);
|
|
||||||
} catch (IOException ignore) {}
|
|
||||||
}
|
|
||||||
return ESBoolean.makeBoolean (false);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public class FtpExtension extends Extension {
|
|
||||||
|
|
||||||
private transient Evaluator evaluator = null;
|
|
||||||
private ESObject esFtpPrototype = null;
|
|
||||||
|
|
||||||
public FtpExtension () {
|
|
||||||
super();
|
|
||||||
}
|
|
||||||
|
|
||||||
class GlobalObjectFtpClient extends BuiltinFunctionObject {
|
|
||||||
GlobalObjectFtpClient(String name, Evaluator evaluator, FunctionPrototype fp) {
|
|
||||||
super(fp, evaluator, name, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
public ESValue callFunction(ESObject thisObject, ESValue[] arguments)
|
|
||||||
throws EcmaScriptException {
|
|
||||||
return doConstruct(thisObject, arguments);
|
|
||||||
}
|
|
||||||
|
|
||||||
public ESObject doConstruct(ESObject thisObject, ESValue[] arguments)
|
|
||||||
throws EcmaScriptException {
|
|
||||||
ESFtpClient ftp = null;
|
|
||||||
if (arguments.length != 1)
|
|
||||||
throw new EcmaScriptException("FtpClient requires 1 argument");
|
|
||||||
ftp = new ESFtpClient (esFtpPrototype,
|
|
||||||
this.evaluator,
|
|
||||||
arguments[0]);
|
|
||||||
return ftp;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
class FtpClientLogin extends BuiltinFunctionObject {
|
|
||||||
FtpClientLogin(String name, Evaluator evaluator, FunctionPrototype fp) {
|
|
||||||
super(fp, evaluator, name, 1);
|
|
||||||
}
|
|
||||||
public ESValue callFunction(ESObject thisObject,
|
|
||||||
ESValue[] arguments)
|
|
||||||
throws EcmaScriptException {
|
|
||||||
ESFtpClient ftp = (ESFtpClient) thisObject;
|
|
||||||
return ftp.login (arguments);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class FtpClientCD extends BuiltinFunctionObject {
|
|
||||||
FtpClientCD(String name, Evaluator evaluator, FunctionPrototype fp) {
|
|
||||||
super(fp, evaluator, name, 1);
|
|
||||||
}
|
|
||||||
public ESValue callFunction(ESObject thisObject,
|
|
||||||
ESValue[] arguments)
|
|
||||||
throws EcmaScriptException {
|
|
||||||
ESFtpClient ftp = (ESFtpClient) thisObject;
|
|
||||||
return ftp.cd (arguments);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class FtpClientMKDIR extends BuiltinFunctionObject {
|
|
||||||
FtpClientMKDIR(String name, Evaluator evaluator, FunctionPrototype fp) {
|
|
||||||
super(fp, evaluator, name, 1);
|
|
||||||
}
|
|
||||||
public ESValue callFunction(ESObject thisObject,
|
|
||||||
ESValue[] arguments)
|
|
||||||
throws EcmaScriptException {
|
|
||||||
ESFtpClient ftp = (ESFtpClient) thisObject;
|
|
||||||
return ftp.mkdir (arguments);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class FtpClientLCD extends BuiltinFunctionObject {
|
|
||||||
FtpClientLCD(String name, Evaluator evaluator, FunctionPrototype fp) {
|
|
||||||
super(fp, evaluator, name, 1);
|
|
||||||
}
|
|
||||||
public ESValue callFunction(ESObject thisObject,
|
|
||||||
ESValue[] arguments)
|
|
||||||
throws EcmaScriptException {
|
|
||||||
ESFtpClient ftp = (ESFtpClient) thisObject;
|
|
||||||
return ftp.lcd (arguments);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class FtpClientPutFile extends BuiltinFunctionObject {
|
|
||||||
FtpClientPutFile (String name, Evaluator evaluator, FunctionPrototype fp) {
|
|
||||||
super(fp, evaluator, name, 1);
|
|
||||||
}
|
|
||||||
public ESValue callFunction(ESObject thisObject,
|
|
||||||
ESValue[] arguments)
|
|
||||||
throws EcmaScriptException {
|
|
||||||
ESFtpClient ftp = (ESFtpClient) thisObject;
|
|
||||||
return ftp.putFile (arguments);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class FtpClientPutString extends BuiltinFunctionObject {
|
|
||||||
FtpClientPutString (String name, Evaluator evaluator, FunctionPrototype fp) {
|
|
||||||
super(fp, evaluator, name, 1);
|
|
||||||
}
|
|
||||||
public ESValue callFunction(ESObject thisObject,
|
|
||||||
ESValue[] arguments)
|
|
||||||
throws EcmaScriptException {
|
|
||||||
ESFtpClient ftp = (ESFtpClient) thisObject;
|
|
||||||
return ftp.putString (arguments);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class FtpClientGetFile extends BuiltinFunctionObject {
|
|
||||||
FtpClientGetFile (String name, Evaluator evaluator, FunctionPrototype fp) {
|
|
||||||
super(fp, evaluator, name, 1);
|
|
||||||
}
|
|
||||||
public ESValue callFunction(ESObject thisObject,
|
|
||||||
ESValue[] arguments)
|
|
||||||
throws EcmaScriptException {
|
|
||||||
ESFtpClient ftp = (ESFtpClient) thisObject;
|
|
||||||
return ftp.getFile (arguments);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class FtpClientGetString extends BuiltinFunctionObject {
|
|
||||||
FtpClientGetString (String name, Evaluator evaluator, FunctionPrototype fp) {
|
|
||||||
super(fp, evaluator, name, 1);
|
|
||||||
}
|
|
||||||
public ESValue callFunction(ESObject thisObject,
|
|
||||||
ESValue[] arguments)
|
|
||||||
throws EcmaScriptException {
|
|
||||||
ESFtpClient ftp = (ESFtpClient) thisObject;
|
|
||||||
return ftp.getString (arguments);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class FtpClientLogout extends BuiltinFunctionObject {
|
|
||||||
FtpClientLogout(String name, Evaluator evaluator, FunctionPrototype fp) {
|
|
||||||
super(fp, evaluator, name, 1);
|
|
||||||
}
|
|
||||||
public ESValue callFunction(ESObject thisObject,
|
|
||||||
ESValue[] arguments)
|
|
||||||
throws EcmaScriptException {
|
|
||||||
ESFtpClient ftp = (ESFtpClient) thisObject;
|
|
||||||
return ftp.logout (arguments);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class FtpClientBinary extends BuiltinFunctionObject {
|
|
||||||
FtpClientBinary(String name, Evaluator evaluator, FunctionPrototype fp) {
|
|
||||||
super(fp, evaluator, name, 1);
|
|
||||||
}
|
|
||||||
public ESValue callFunction(ESObject thisObject,
|
|
||||||
ESValue[] arguments)
|
|
||||||
throws EcmaScriptException {
|
|
||||||
ESFtpClient ftp = (ESFtpClient) thisObject;
|
|
||||||
return ftp.binary (arguments);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class FtpClientAscii extends BuiltinFunctionObject {
|
|
||||||
FtpClientAscii(String name, Evaluator evaluator, FunctionPrototype fp) {
|
|
||||||
super(fp, evaluator, name, 1);
|
|
||||||
}
|
|
||||||
public ESValue callFunction(ESObject thisObject,
|
|
||||||
ESValue[] arguments)
|
|
||||||
throws EcmaScriptException {
|
|
||||||
ESFtpClient ftp = (ESFtpClient) thisObject;
|
|
||||||
return ftp.ascii (arguments);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public void initializeExtension(Evaluator evaluator) throws EcmaScriptException {
|
|
||||||
|
|
||||||
this.evaluator = evaluator;
|
|
||||||
GlobalObject go = evaluator.getGlobalObject();
|
|
||||||
ObjectPrototype op = (ObjectPrototype) evaluator.getObjectPrototype();
|
|
||||||
FunctionPrototype fp = (FunctionPrototype) evaluator.getFunctionPrototype();
|
|
||||||
|
|
||||||
esFtpPrototype = new ESFtpClient (op, evaluator);
|
|
||||||
|
|
||||||
ESObject globalFtpObject = new GlobalObjectFtpClient("FtpClient", evaluator, fp);
|
|
||||||
globalFtpObject.putHiddenProperty("prototype",esFtpPrototype);
|
|
||||||
globalFtpObject.putHiddenProperty("length",new ESNumber(1));
|
|
||||||
|
|
||||||
|
|
||||||
esFtpPrototype.putHiddenProperty("login", new FtpClientLogin("login", evaluator, fp));
|
|
||||||
esFtpPrototype.putHiddenProperty("cd", new FtpClientCD("cd", evaluator, fp));
|
|
||||||
esFtpPrototype.putHiddenProperty("mkdir", new FtpClientMKDIR("mkdir", evaluator, fp));
|
|
||||||
esFtpPrototype.putHiddenProperty("lcd", new FtpClientLCD("lcd", evaluator, fp));
|
|
||||||
esFtpPrototype.putHiddenProperty("putFile", new FtpClientPutFile("putFile", evaluator, fp));
|
|
||||||
esFtpPrototype.putHiddenProperty("putString", new FtpClientPutString("putString", evaluator, fp));
|
|
||||||
esFtpPrototype.putHiddenProperty("getFile", new FtpClientGetFile("getFile", evaluator, fp));
|
|
||||||
esFtpPrototype.putHiddenProperty("getString", new FtpClientGetString("getString", evaluator, fp));
|
|
||||||
esFtpPrototype.putHiddenProperty("logout", new FtpClientLogout("logout", evaluator, fp));
|
|
||||||
esFtpPrototype.putHiddenProperty("binary", new FtpClientBinary("binary", evaluator, fp));
|
|
||||||
esFtpPrototype.putHiddenProperty("ascii", new FtpClientAscii("ascii", evaluator, fp));
|
|
||||||
|
|
||||||
go.putHiddenProperty("FtpClient", globalFtpObject);
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,133 +0,0 @@
|
||||||
// ImageExtension.java
|
|
||||||
// Copyright (c) Hannes Wallnöfer 1998-2000
|
|
||||||
|
|
||||||
package helma.framework.extensions;
|
|
||||||
|
|
||||||
import helma.objectmodel.*;
|
|
||||||
import helma.util.*;
|
|
||||||
import helma.image.*;
|
|
||||||
|
|
||||||
import FESI.Interpreter.*;
|
|
||||||
import FESI.Exceptions.*;
|
|
||||||
import FESI.Extensions.*;
|
|
||||||
import FESI.Data.*;
|
|
||||||
|
|
||||||
import java.io.*;
|
|
||||||
import java.awt.image.*;
|
|
||||||
import java.util.*;
|
|
||||||
import java.rmi.Naming;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Extension to do Image manipulation from HOP.
|
|
||||||
*/
|
|
||||||
|
|
||||||
public class ImageExtension extends Extension {
|
|
||||||
|
|
||||||
protected Evaluator evaluator = null;
|
|
||||||
|
|
||||||
static boolean remote = false;
|
|
||||||
|
|
||||||
|
|
||||||
public ImageExtension () {
|
|
||||||
super();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
class GlobalObjectImage extends BuiltinFunctionObject {
|
|
||||||
|
|
||||||
ImageExtension imagex;
|
|
||||||
ImageGenerator imggen;
|
|
||||||
|
|
||||||
GlobalObjectImage (String name, Evaluator evaluator, FunctionPrototype fp, ImageExtension imagex) {
|
|
||||||
super(fp, evaluator, name, 1);
|
|
||||||
this.imagex = imagex;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ESValue callFunction(ESObject thisObject, ESValue[] arguments) throws EcmaScriptException {
|
|
||||||
return doConstruct(thisObject, arguments);
|
|
||||||
}
|
|
||||||
|
|
||||||
public ESObject doConstruct(ESObject thisObject, ESValue[] arguments) throws EcmaScriptException {
|
|
||||||
Object img = null;
|
|
||||||
IRemoteGenerator rgen = null;
|
|
||||||
|
|
||||||
try {
|
|
||||||
if (imggen == null && !remote) {
|
|
||||||
try {
|
|
||||||
imggen = new ImageGenerator ();
|
|
||||||
} catch (UnsatisfiedLinkError noawt) {
|
|
||||||
remote = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (remote)
|
|
||||||
rgen = (IRemoteGenerator) Naming.lookup ("//localhost:3033/server");
|
|
||||||
|
|
||||||
if (arguments.length == 1) {
|
|
||||||
if (arguments[0] instanceof ESArrayWrapper) {
|
|
||||||
Object obj = ((ESArrayWrapper) arguments[0]).toJavaObject ();
|
|
||||||
if (obj instanceof byte[]) {
|
|
||||||
img = remote ?
|
|
||||||
(Object) rgen.createImage ((byte[]) obj) :
|
|
||||||
(Object) imggen.createImage ((byte[]) obj);
|
|
||||||
}
|
|
||||||
} else if (arguments[0] instanceof ESString) {
|
|
||||||
String imgurl = arguments[0].toString ();
|
|
||||||
img = remote ?
|
|
||||||
(Object) rgen.createPaintableImage (imgurl) :
|
|
||||||
(Object) imggen.createPaintableImage (imgurl);
|
|
||||||
}
|
|
||||||
} else if (arguments.length == 2) {
|
|
||||||
if (arguments[0] instanceof ESWrapper && arguments[1] instanceof ESWrapper) {
|
|
||||||
// create a new image from an existing one and an image filter
|
|
||||||
Object image = arguments[0].toJavaObject ();
|
|
||||||
Object filter = arguments[1].toJavaObject ();
|
|
||||||
img = imggen.createPaintableImage ((ImageWrapper) image, (ImageFilter) filter);
|
|
||||||
} else if (arguments[0].isNumberValue () && arguments[1].isNumberValue ()) {
|
|
||||||
img = remote ?
|
|
||||||
(Object) rgen.createPaintableImage (arguments[0].toInt32(), arguments[1].toInt32()) :
|
|
||||||
(Object) imggen.createPaintableImage (arguments[0].toInt32(), arguments[1].toInt32());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (Exception error) {
|
|
||||||
System.err.println ("Error creating Image: "+error);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (img == null)
|
|
||||||
throw new EcmaScriptException ("Error creating image: Bad parameters or setup problem.");
|
|
||||||
|
|
||||||
return new ESWrapper (img, this.evaluator);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Called by the evaluator after the extension is loaded.
|
|
||||||
*/
|
|
||||||
public void initializeExtension(Evaluator evaluator) throws EcmaScriptException {
|
|
||||||
|
|
||||||
this.evaluator = evaluator;
|
|
||||||
GlobalObject go = evaluator.getGlobalObject();
|
|
||||||
FunctionPrototype fp = (FunctionPrototype) evaluator.getFunctionPrototype();
|
|
||||||
|
|
||||||
ESObject image = new GlobalObjectImage ("Image", evaluator, fp, this); // the Image constructor
|
|
||||||
|
|
||||||
go.putHiddenProperty("Image", image); // register the constructor for a Image object.
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,255 +0,0 @@
|
||||||
// MailExtension.java
|
|
||||||
// Copyright (c) Hannes Wallnöfer 1998-2000
|
|
||||||
|
|
||||||
package helma.framework.extensions;
|
|
||||||
|
|
||||||
import helma.main.Server;
|
|
||||||
import helma.util.*;
|
|
||||||
|
|
||||||
import FESI.Interpreter.*;
|
|
||||||
import FESI.Exceptions.*;
|
|
||||||
import FESI.Extensions.*;
|
|
||||||
import FESI.Data.*;
|
|
||||||
|
|
||||||
import java.io.*;
|
|
||||||
import java.util.*;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Extension to create and send mail messages via SMTP from HOP applications
|
|
||||||
*/
|
|
||||||
|
|
||||||
public class MailExtension extends Extension {
|
|
||||||
|
|
||||||
|
|
||||||
protected Evaluator evaluator = null;
|
|
||||||
protected ObjectPrototype esMailPrototype = null;
|
|
||||||
protected Properties mprops;
|
|
||||||
|
|
||||||
|
|
||||||
public MailExtension () {
|
|
||||||
super();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setProperties (Properties props) {
|
|
||||||
this.mprops = props;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Called by the evaluator after the extension is loaded.
|
|
||||||
*/
|
|
||||||
public void initializeExtension(Evaluator evaluator) throws EcmaScriptException {
|
|
||||||
|
|
||||||
this.evaluator = evaluator;
|
|
||||||
GlobalObject go = evaluator.getGlobalObject();
|
|
||||||
FunctionPrototype fp = (FunctionPrototype) evaluator.getFunctionPrototype();
|
|
||||||
|
|
||||||
ESObject op = evaluator.getObjectPrototype();
|
|
||||||
esMailPrototype = new ObjectPrototype(op, evaluator); // the Node prototype
|
|
||||||
|
|
||||||
ESObject mail = new GlobalObjectMail ("Mail", evaluator, fp, this); // the Mail constructor
|
|
||||||
|
|
||||||
go.putHiddenProperty("Mail", mail); // register the constructor for a Mail object.
|
|
||||||
|
|
||||||
|
|
||||||
// methods for sending mail from JS...
|
|
||||||
ESObject p = new MailSetText ("setText", evaluator, fp);
|
|
||||||
esMailPrototype.putHiddenProperty("setText", p);
|
|
||||||
esMailPrototype.putHiddenProperty("addText", p);
|
|
||||||
|
|
||||||
esMailPrototype.putHiddenProperty("addPart", new MailAddPart ("addPart", evaluator, fp));
|
|
||||||
esMailPrototype.putHiddenProperty("setSubject", new MailSetSubject ("setSubject", evaluator, fp));
|
|
||||||
esMailPrototype.putHiddenProperty("setReplyTo", new MailSetReplyTo ("setReplyTo", evaluator, fp));
|
|
||||||
esMailPrototype.putHiddenProperty("setFrom", new MailSetFrom ("setFrom", evaluator, fp));
|
|
||||||
|
|
||||||
p = new MailAddTo ("addTo", evaluator, fp);
|
|
||||||
esMailPrototype.putHiddenProperty("addTo", p);
|
|
||||||
esMailPrototype.putHiddenProperty("setTo", p);
|
|
||||||
|
|
||||||
p = new MailAddCC ("addCC", evaluator, fp);
|
|
||||||
esMailPrototype.putHiddenProperty("addCC", p);
|
|
||||||
esMailPrototype.putHiddenProperty("setCC", p);
|
|
||||||
|
|
||||||
p = new MailAddBCC ("addBCC", evaluator, fp);
|
|
||||||
esMailPrototype.putHiddenProperty("addBCC", p);
|
|
||||||
esMailPrototype.putHiddenProperty("setBCC", p);
|
|
||||||
|
|
||||||
esMailPrototype.putHiddenProperty("send", new MailSend ("send", evaluator, fp));
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
class GlobalObjectMail extends BuiltinFunctionObject {
|
|
||||||
|
|
||||||
MailExtension mailx;
|
|
||||||
|
|
||||||
GlobalObjectMail (String name, Evaluator evaluator, FunctionPrototype fp, MailExtension mailx) {
|
|
||||||
super(fp, evaluator, name, 1);
|
|
||||||
this.mailx = mailx;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ESValue callFunction(ESObject thisObject, ESValue[] arguments) throws EcmaScriptException {
|
|
||||||
return doConstruct(thisObject, arguments);
|
|
||||||
}
|
|
||||||
|
|
||||||
public ESObject doConstruct(ESObject thisObject, ESValue[] arguments) throws EcmaScriptException {
|
|
||||||
ESMail mail = null;
|
|
||||||
|
|
||||||
if (arguments.length == 0) {
|
|
||||||
mail = new ESMail (mailx);
|
|
||||||
} else {
|
|
||||||
mail = new ESMail (mailx);
|
|
||||||
// should/could do something with extra arguments...
|
|
||||||
}
|
|
||||||
return mail;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
class MailSetText extends BuiltinFunctionObject {
|
|
||||||
MailSetText (String name, Evaluator evaluator, FunctionPrototype fp) {
|
|
||||||
super (fp, evaluator, name, 1);
|
|
||||||
}
|
|
||||||
public ESValue callFunction (ESObject thisObject, ESValue[] arguments) throws EcmaScriptException {
|
|
||||||
ESMail mail = (ESMail) thisObject;
|
|
||||||
if (arguments.length == 1) try {
|
|
||||||
mail.setText (arguments[0]);
|
|
||||||
} catch (Exception x) {
|
|
||||||
mail.setStatus (ESMail.TEXT);
|
|
||||||
return ESBoolean.makeBoolean(false);
|
|
||||||
}
|
|
||||||
return ESBoolean.makeBoolean(true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class MailAddPart extends BuiltinFunctionObject {
|
|
||||||
MailAddPart (String name, Evaluator evaluator, FunctionPrototype fp) {
|
|
||||||
super (fp, evaluator, name, 1);
|
|
||||||
}
|
|
||||||
public ESValue callFunction (ESObject thisObject, ESValue[] arguments) throws EcmaScriptException {
|
|
||||||
ESMail mail = (ESMail) thisObject;
|
|
||||||
try {
|
|
||||||
mail.addPart (arguments);
|
|
||||||
} catch (Exception x) {
|
|
||||||
mail.setStatus (ESMail.MIMEPART);
|
|
||||||
return ESBoolean.makeBoolean(false);
|
|
||||||
}
|
|
||||||
return ESBoolean.makeBoolean(true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class MailSetSubject extends BuiltinFunctionObject {
|
|
||||||
MailSetSubject (String name, Evaluator evaluator, FunctionPrototype fp) {
|
|
||||||
super (fp, evaluator, name, 1);
|
|
||||||
}
|
|
||||||
public ESValue callFunction (ESObject thisObject, ESValue[] arguments) throws EcmaScriptException {
|
|
||||||
ESMail mail = (ESMail) thisObject;
|
|
||||||
if (arguments.length == 1) try {
|
|
||||||
mail.setSubject (arguments[0]);
|
|
||||||
} catch (Exception x) {
|
|
||||||
mail.setStatus (ESMail.SUBJECT);
|
|
||||||
return ESBoolean.makeBoolean(false);
|
|
||||||
}
|
|
||||||
return ESBoolean.makeBoolean(true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class MailSetReplyTo extends BuiltinFunctionObject {
|
|
||||||
MailSetReplyTo (String name, Evaluator evaluator, FunctionPrototype fp) {
|
|
||||||
super (fp, evaluator, name, 1);
|
|
||||||
}
|
|
||||||
public ESValue callFunction (ESObject thisObject, ESValue[] arguments) throws EcmaScriptException {
|
|
||||||
ESMail mail = (ESMail) thisObject;
|
|
||||||
if (arguments.length == 1) try {
|
|
||||||
mail.setReplyTo (arguments[0]);
|
|
||||||
} catch (Exception x) {
|
|
||||||
mail.setStatus (ESMail.REPLYTO);
|
|
||||||
return ESBoolean.makeBoolean(false);
|
|
||||||
}
|
|
||||||
return ESBoolean.makeBoolean(true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class MailSetFrom extends BuiltinFunctionObject {
|
|
||||||
MailSetFrom (String name, Evaluator evaluator, FunctionPrototype fp) {
|
|
||||||
super (fp, evaluator, name, 1);
|
|
||||||
}
|
|
||||||
public ESValue callFunction (ESObject thisObject, ESValue[] arguments) throws EcmaScriptException {
|
|
||||||
ESMail mail = (ESMail) thisObject;
|
|
||||||
try {
|
|
||||||
mail.setFrom (arguments);
|
|
||||||
} catch (Exception x) {
|
|
||||||
mail.setStatus (ESMail.FROM);
|
|
||||||
return ESBoolean.makeBoolean(false);
|
|
||||||
}
|
|
||||||
return ESBoolean.makeBoolean(true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class MailAddTo extends BuiltinFunctionObject {
|
|
||||||
MailAddTo (String name, Evaluator evaluator, FunctionPrototype fp) {
|
|
||||||
super (fp, evaluator, name, 1);
|
|
||||||
}
|
|
||||||
public ESValue callFunction (ESObject thisObject, ESValue[] arguments) throws EcmaScriptException {
|
|
||||||
ESMail mail = (ESMail) thisObject;
|
|
||||||
try {
|
|
||||||
mail.addTo (arguments);
|
|
||||||
} catch (Exception x) {
|
|
||||||
mail.setStatus (ESMail.TO);
|
|
||||||
return ESBoolean.makeBoolean(false);
|
|
||||||
}
|
|
||||||
return ESBoolean.makeBoolean(true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class MailAddCC extends BuiltinFunctionObject {
|
|
||||||
MailAddCC (String name, Evaluator evaluator, FunctionPrototype fp) {
|
|
||||||
super (fp, evaluator, name, 1);
|
|
||||||
}
|
|
||||||
public ESValue callFunction (ESObject thisObject, ESValue[] arguments) throws EcmaScriptException {
|
|
||||||
ESMail mail = (ESMail) thisObject;
|
|
||||||
try {
|
|
||||||
mail.addCC (arguments);
|
|
||||||
} catch (Exception x) {
|
|
||||||
mail.setStatus (ESMail.CC);
|
|
||||||
return ESBoolean.makeBoolean(false);
|
|
||||||
}
|
|
||||||
return ESBoolean.makeBoolean(true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class MailAddBCC extends BuiltinFunctionObject {
|
|
||||||
MailAddBCC (String name, Evaluator evaluator, FunctionPrototype fp) {
|
|
||||||
super (fp, evaluator, name, 1);
|
|
||||||
}
|
|
||||||
public ESValue callFunction (ESObject thisObject, ESValue[] arguments) throws EcmaScriptException {
|
|
||||||
ESMail mail = (ESMail) thisObject;
|
|
||||||
try {
|
|
||||||
mail.addBCC (arguments);
|
|
||||||
} catch (Exception x) {
|
|
||||||
mail.setStatus (ESMail.BCC);
|
|
||||||
return ESBoolean.makeBoolean(false);
|
|
||||||
}
|
|
||||||
return ESBoolean.makeBoolean(true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class MailSend extends BuiltinFunctionObject {
|
|
||||||
MailSend (String name, Evaluator evaluator, FunctionPrototype fp) {
|
|
||||||
super (fp, evaluator, name, 1);
|
|
||||||
}
|
|
||||||
public ESValue callFunction (ESObject thisObject, ESValue[] arguments) throws EcmaScriptException {
|
|
||||||
ESMail mail = (ESMail) thisObject;
|
|
||||||
try {
|
|
||||||
mail.send ();
|
|
||||||
} catch (Exception x) {
|
|
||||||
Server.getLogger().log ("Error sending mail: "+x);
|
|
||||||
mail.setStatus (ESMail.SEND);
|
|
||||||
return ESBoolean.makeBoolean(false);
|
|
||||||
}
|
|
||||||
return ESBoolean.makeBoolean(true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue