• Курсы Академии Кодебай, стартующие в мае - июне, от команды The Codeby

    1. Цифровая криминалистика и реагирование на инциденты
    2. ОС Linux (DFIR) Старт: 16 мая
    3. Анализ фишинговых атак Старт: 16 мая Устройства для тестирования на проникновение Старт: 16 мая

    Скидки до 10%

    Полный список ближайших курсов ...

Вызов xpage

lmike

нет, пердело совершенство
Lotus Team
27.08.2008
7 963
611
BIT
317
очевидной целью является "плавный" переход от классики или вызов java для ф-ций, которые по той или иной причине засунуть в агент будет проблематичным/рискованным/неудобным
Для версий нотусни, в которых нет класов обработки http запросов (ниже 10.0) или нет желания постигать дзен новых классов из LS, подход будет заключаться в вызове java агента, с единственной целью - вызвать и обработать результат от xpage
Основны "хитрости":
- авторизация (создание передача сессии)
- обработка ситуации с прокси сервером
- обработка результата и формирование ответа

первое и второе (в коде ниже) я здесь уже описывал, последнее предполагается задействовать через документ. Вполне возможно передавать и бинарные объекты, но обработка их в ЛС не очень удобна, да и часто конечным "потребителем" будет документ.

Коротко схема такова:
Код на ЛС -> вызов java агента с документом контекста (поля которого заполняются соответственно потребностям) -> кода java обрабатывающий вызов и возврат параметров xpage
Ниже код агента и библиотеки с обработкой:
Java:
//***************************************************
//агент
import lotus.domino.*;

public class JavaAgent extends AgentBase {

    public void NotesMain() {

      try {
          Session ses = getSession();
          AgentContext agentContext = ses.getAgentContext();

          // (Your code goes here)
          Document doc=agentContext.getDocumentContext();
          if (doc!=null){
                  //agentContext could contains document with parameters
                  doc.replaceItemValue("result", org.mypackage.XAgent.run(ses, agentContext));
              doc.recycle();
          }

      } catch(Exception e) {
          e.printStackTrace();
      }
   }
}
//***************************************************
//библиотека
package org.mypackage;
import lotus.domino.Session;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.InetSocketAddress;
import java.net.ProxySelector;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.Iterator;
import java.util.List;

import lotus.domino.AgentContext;
import lotus.domino.Database;
import lotus.domino.Document;
import lotus.domino.Name;
import lotus.domino.NotesException;

//import org.apache.commons.lang.*;
public class XAgent {
  
    private static boolean isError=true;
    public static String run(Session ses, AgentContext agentContext) throws NotesException {
      String url = null;
      StringBuffer buf=new StringBuffer();
      int status=-1;
      Document doc=agentContext.getDocumentContext();
      if (doc!=null){
        String xpageName=doc.getItemValueString("xpage");
        String domain=doc.getItemValueString("domain");
        String params=doc.getItemValueString("params");
        Database db=agentContext.getCurrentDatabase();
        String dbPath = agentContext.getCurrentDatabase().getFilePath();
        String server=db.getServer();
        if (!xpageName.isEmpty()){
            try {
                System.out.println("Trusting...");
                TrustAllCertificates.install();
                System.out.println("Generating token...");
                LtpaToken ltpaToken=new LtpaToken();
                ltpaToken.initByConfiguration(ses);
                String token=ltpaToken.generateLtpaToken(ses.getEffectiveUserName());
                System.out.println("Context processing...");
                //dbPath=db.getHttpURL();
                //System.out.println("path->"+dbPath);
                if (domain.isEmpty())domain=ltpaToken.getDomain();
                Name name=ses.createName(server);
                server=name.getCommon();
                //doc.recycle();
                url = "https://"+server+domain+"/" + dbPath + "/" + xpageName + ".xsp" + ((params.length())>0?"?"+params:"");
                url = "https://"+server+domain+"/" + dbPath.replace("\\", "/") + "/" + xpageName + ".xsp";
                System.out.println("Starting " + xpageName + " in database " + dbPath);
                System.out.println("URL to connect->"+url);
                assignSystemProxy(url);
                String cookies="LtpaToken=" + token;// + "; domain=" + domain.substring(1) + "; path=/";
                System.out.println("Cookies->"+cookies);
                doc.recycle();
                db.recycle();
  
                URL xPageURL = new URL(url);
                HttpURLConnection conn = (HttpURLConnection) xPageURL.openConnection();
                conn.setRequestProperty("Cookie", cookies);
                //conn.connect();
  
                status=conn.getResponseCode();
                switch (status) {
                case HttpURLConnection.HTTP_OK:
                    // read from the urlconnection via the bufferedreader
                    BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(conn.getInputStream()));
                    String line;
                    while ((line = bufferedReader.readLine()) != null) {
                        buf.append(line);
                        //System.out.println("Response: " + line);
                    }
                    bufferedReader.close();
                    isError=false;
                    break;
                case HttpURLConnection.HTTP_INTERNAL_ERROR:
                    buf.append("Interal server error while running");
                    System.out.println(buf.toString());
                    break;
                default:
                    buf.append(conn.getResponseMessage());
                    System.out.println("An error occurred: " + status);
                    System.out.println("Error message: " + buf.toString());
                    break;
                }

                conn.disconnect();

                System.out.println("Finished " + xpageName + " in database " + dbPath);

            } catch (Exception e) {
                System.out.println("!URL->"+url);
                e.printStackTrace();
                buf.append(e.getMessage());
            }
            String res="";
            if (isError)res="{,\n\"error\":true}";
            return "{\"status\":"+status+", \"msg\":\""
                    +org.apache.commons.lang.StringEscapeUtils.escapeHtml(buf.toString())+"\""+
                    res+"}";
        }
    }
    
    return "{\"status\":"+status+", \"msg\":\""
      +((status==HttpURLConnection.HTTP_OK)?
              buf.toString():
                  org.apache.commons.lang.StringEscapeUtils.escapeHtml(buf.toString()))+"\"}";
  }

    static void assignSystemProxy(String url){
        System.setProperty("java.net.useSystemProxies", "true");
        System.out.println("detecting proxies");
        List l = null;
        try {
            l = ProxySelector.getDefault().select(new URI(url));
        }
        catch (URISyntaxException e) {
            e.printStackTrace();
        }
        if (l != null) {
            for (Iterator iter = l.iterator(); iter.hasNext();) {
                java.net.Proxy proxy = (java.net.Proxy) iter.next();
                System.out.println("proxy type: " + proxy.type());

                InetSocketAddress addr = (InetSocketAddress) proxy.address();

                if (addr == null) {
                    System.out.println("No Proxy");
                } else {
                    System.out.println("proxy hostname: " + addr.getHostName());
                    System.setProperty("http.proxyHost", addr.getHostName());
                    System.out.println("proxy port: " + addr.getPort());
                    System.setProperty("http.proxyPort", Integer.toString(addr.getPort()));
                }
            }
        }
    }
}
пример вызова из ЛС
Код:
Option Public
Option Declare
Use "ErrorHandlingLS"
Sub Initialize
    On Error Goto ErrH
    Goto Continue
ErrH:
    Error Err, RaiseError
Continue:
    Dim doc As NotesDocument, ses As New NotesSession, db As NotesDatabase
    Set db=ses.Currentdatabase
    Set doc=db.Createdocument()
    doc.Replaceitemvalue {xpage}, {groupingreport}
    Call db.Getagent({JXAgent}).Runwithdocumentcontext(doc, doc.Noteid)
    Messagebox doc.Getitemvalue({result})(0)
End Sub
 
Последнее редактирование:
  • Нравится
Реакции: alexas1

lmike

нет, пердело совершенство
Lotus Team
27.08.2008
7 963
611
BIT
317
теперь про LS2J
агент имеет ряд особенностей:
- время запуска
- "отдельный" экземпляр jvm (для каждого агента будет некая копия среды jvm) т.е. память + время
LS2J имеет ряд ограничений (нельзя использовать LDN классы и ограничен в многопоточности) но и преимущества - по времени и памяти
модифицированный код java:
Java:
/*************************/
import java.io.InputStream;

public class HttpRet {
    StringBuffer buf=new StringBuffer();
    InputStream is=null;
    String contentType="";
    String contentDisposition="";
    int status=-1;
    public String toString(){
        return buf.toString();
    }
  
    public int getStatus(){
        return status;
    }
  
    public InputStream getInputStream(){
        return this.is;
    }

    public String getContentType() {
        return contentType;
    }

    public String getContentDisposition() {
        return contentDisposition;
    }

}

/*************************/
import lotus.domino.Session;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.InetSocketAddress;
import java.net.MalformedURLException;
import java.net.ProxySelector;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.nio.file.Files;
import java.util.Iterator;
import java.util.List;

import org.apache.commons.io.IOUtils;

import lotus.domino.AgentContext;
import lotus.domino.Database;
import lotus.domino.Document;
import lotus.domino.Name;
import lotus.domino.NotesException;

//import org.apache.commons.lang.*;
public class XAgent {
    String xpageName;
    String domain;
    String params;

    public static enum Proto {
        HTTP, HTTPS, NOTES
    };
    public static Proto defProto=Proto.HTTPS;
    private boolean isError = true;

    public void setXpage(String xpage){
        this.xpageName=xpage;
    }

    public String run(Session ses, AgentContext agentContext) throws NotesException {
        String url = null;
        StringBuffer buf = new StringBuffer();
        int status = -1;
        Document doc = agentContext.getDocumentContext();
        if (doc != null) {
            xpageName = doc.getItemValueString("xpage");
            domain = doc.getItemValueString("domain");
            params = doc.getItemValueString("params");
            Database db = agentContext.getCurrentDatabase();
            String dbPath = agentContext.getCurrentDatabase().getFilePath();
            String server = db.getServer();
            if (!xpageName.isEmpty()) {
                try {
                    // System.out.println("Trusting...");
                    // TrustAllCertificates.install();
                    System.out.println("Generating token...");
                    LtpaToken ltpaToken = new LtpaToken();
                    ltpaToken.initByConfiguration(ses);
                    String token = ltpaToken.generateLtpaToken(ses.getEffectiveUserName());
                    System.out.println("Context processing...");
                    // dbPath=db.getHttpURL();
                    // System.out.println("path->"+dbPath);
                    if (domain.isEmpty())
                        domain = ltpaToken.getDomain();
                    Name name = ses.createName(server);
                    server = name.getCommon();
                    // doc.recycle();
                    System.out.println("Starting " + xpageName + " in database " + dbPath);
                    doc.recycle();
                    db.recycle();
                    HttpRet ret=callXPage(Proto.HTTPS, server + domain , dbPath, xpageName, token);
                    buf=ret.buf;
                    System.out.println("Finished " + xpageName + " in database " + dbPath);

                } catch (Exception e) {
                    System.out.println("!URL->" + url);
                    e.printStackTrace();
                    buf.append(e.getMessage());
                }
                String res = "";
                if (isError)
                    res = "{,\n\"error\":true}";
                return "{\"status\":" + status + ", \"msg\":\""
                        + org.apache.commons.lang.StringEscapeUtils.escapeHtml(buf.toString()) + "\"" + res + "}";
            }
        }

        return "{\"status\":" + status + ", \"msg\":\"" + ((status == HttpURLConnection.HTTP_OK) ? buf.toString()
                : org.apache.commons.lang.StringEscapeUtils.escapeHtml(buf.toString())) + "\"}";
    }

    public boolean getIsError(){return isError;}

    public HttpRet callXPage(Proto proto, String server, String dbPath, String xpage, String token) throws IOException {
//        try{
        HttpRet ret = new HttpRet();
        isError=true;
        String url = String.valueOf(proto).toLowerCase() + "://" + server + "/" + dbPath.replace("\\", "/")
                + "/" + xpage + ".xsp" + (params!=null && (params.length() > 0) ? "?" + params : "");
        String cookies = "LtpaToken=" + token;// + "; domain=" +
                                                // domain.substring(1) + ";
                                                // path=/";
        assignSystemProxy(url);
        URL xPageURL = new URL(url);
        HttpURLConnection conn = (HttpURLConnection) xPageURL.openConnection();
        conn.setRequestProperty("Cookie", cookies);
        // conn.connect();

         ret.status = conn.getResponseCode();
        switch (ret.status) {
        case HttpURLConnection.HTTP_OK:
            // read from the urlconnection via the bufferedreader
            ret.is = conn.getInputStream();
            ret.contentDisposition=conn.getHeaderField("Content-Disposition");
            ret.contentType=conn.getContentType();
            if (ret.contentType.contains("json") || conn.getContentType().contains("text")) {
                System.out.println("text Content");
                BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(conn.getInputStream()));
                String line;
                while ((line = bufferedReader.readLine()) != null) {
                    ret.buf.append(line);
                    // System.out.println("Response: " + line);
                }
                bufferedReader.close();
            }
            isError = false;
            break;
        case HttpURLConnection.HTTP_INTERNAL_ERROR:
            ret.buf.append("Interal server error while running");
            System.out.println(ret.buf.toString());
            break;
        default:
            ret.buf.append(conn.getResponseMessage());
            System.out.println("An error occurred: " + ret.status);
            System.out.println("Error message: " + ret.buf.toString());
            break;
        }
        //conn.disconnect();
        return ret;
//        }catch(Exception e){
//            e.printStackTrace();
//        }
//        return null;
    }
    public String getTempFromRet(HttpRet ret) throws IOException{
        String sret="";
        if (ret.contentDisposition.contains("filename=")){
            String fName=ret.contentDisposition.split("=")[1];
            File tmp=File.createTempFile("tmp", fName.split("\\.")[1]);
            IOUtils.copy(ret.is, new FileOutputStream(tmp));
            sret=tmp.getAbsolutePath();
        }
        return sret;
    }

    static void assignSystemProxy(String url) {
        System.setProperty("java.net.useSystemProxies", "true");
        System.out.println("detecting proxies");
        List l = null;
        try {
            l = ProxySelector.getDefault().select(new URI(url));
        } catch (URISyntaxException e) {
            e.printStackTrace();
        }
        if (l != null) {
            for (Iterator iter = l.iterator(); iter.hasNext();) {
                java.net.Proxy proxy = (java.net.Proxy) iter.next();
                System.out.println("proxy type: " + proxy.type());

                InetSocketAddress addr = (InetSocketAddress) proxy.address();

                if (addr == null) {
                    System.out.println("No Proxy");
                } else {
                    System.out.println("proxy hostname: " + addr.getHostName());
                    System.setProperty("http.proxyHost", addr.getHostName());
                    System.out.println("proxy port: " + addr.getPort());
                    System.setProperty("http.proxyPort", Integer.toString(addr.getPort()));
                }
            }
        }
    }
}
класс LS:
Код:
%REM
    Library XAgent.LS
    Created Jul 29, 2019 by Mikhail Cholokov/CRUINTERNET
    Description: Comments for Library
%END REM
Option Public
Option Declare
Use "ErrorHandling"
Use "XAgent"
    Const NAMESDB="names.nsf"
    Const SSOVIEW="($WebSSOConfigs)"
    Const SSO_DOMINO_SECRETFIELD="LTPA_DominoSecret"
    Const SSO_DOMINO_DURATIONFIELD="LTPA_TokenExpiration"
    Const SSO_DOMINO_DOMAIN="LTPA_TokenDomain"
    Const WebSSOSite="MYORG:MYsite"

%REM
    Class XAgent
    Description: Comments for Class
%END REM
Class XAgent As ErrorHandlerWJ
    token As String
    ses As NotesSession
    LtpaClass As Javaclass
    LtpaObj As Javaobject
    XAgentClass As JavaClass
    XAgentObj As JavaObject
    IOUtils As Javaclass
    server As String
    dbPath As String
    proto As JavaObject

    %REM
        Sub New
        Description: Comments for Sub
    %END REM
    Sub New()
        On Error GoTo ErrH
        GoTo Continue
ErrH:
        Error Err, RaiseError
Continue:
        Set ses=New NotesSession
        Dim db As NotesDatabase, currentServer As String
        Set db=ses.CurrentDatabase
        currentServer=db.Server
        Dim n As New NotesName(currentServer)
        me.server=n.Common
        Set db=ses.getDatabase(currentServer, NAMESDB, False)
        Dim view As NotesView, ssoDoc As NotesDocument
        Set view=db.Getview(SSOVIEW)
        Set ssoDoc=view.getDocumentByKey(webSSOSite, True)
    
        Set me.XAgentClass=jSession.Getclass({com.setralubs.XAgent})
        Set me.XAgentObj=me.XAgentClass.Createobject()
        Set proto=me.XAgentClass.defProto
    

        Set me.LtpaClass=jSession.Getclass({com.setralubs.LtpaToken})
        Set me.Ltpaobj=me.LtpaClass.Createobject()
    
        Call me.LtpaObj.setLtpaSecret(ssoDoc.getItemValue(SSO_DOMINO_SECRETFIELD)(0))
        Call me.LtpaObj.setDuration(CInt(ssoDoc.getItemValue(SSO_DOMINO_DURATIONFIELD)(0)))
        Call me.LtpaObj.setDomain(ssoDoc.getItemValue(SSO_DOMINO_DOMAIN)(0))
        token=me.LtpaObj.generateLtpaToken(ses.Effectiveusername)
        server=server + ltpaObj.getDomain()
        Set IOUtils=jSession.Getclass({org.apache.commons.io.IOUtils})
        Print {token:} token
    End Sub

    %REM
        Sub test
        Description: Comments for Sub
    %END REM
    Sub test(sPath As String, xpage As String)
        On Error GoTo ErrH
        GoTo Continue
ErrH:
        Error Err, Me.RaiseError
Continue:
        Dim isClass As Javaclass, osClass As Javaclass
        Set isClass=jSession.Getclass({java.io.FileInputStream}):Set osClass=jSession.Getclass({java.io.FileOutputStream})
        Dim fis As JavaObject, fos As Javaobject
        'Set fis=isClass.Createobject({(Ljava/lang/String;)V}, sPath)
        'Set fos=osClass.Createobject({(Ljava/lang/String;)V}, sPath)
        Print {protocol:} me.proto.toString()
        Dim ret
        Set ret = me.XAgentObj.callXPage(me.proto, me.server, ses.Currentdatabase.FilePath(), xpage, me.token)
        Dim fName As String, status As Integer
        fName=ret.getContentDisposition()
        status=ret.getStatus()
        Print {Code|Content-Type/Disposition:}status {/} ret.getContentType() {/} fName
        If status<>200Then
            MsgBox ret.toString()
        Else
            If Len(fName)>0 And fName Like {*attach*filename=*}Then
'                fName=StrRight(fName,{=})
'                Dim tmp
'                Set tmp=tempFile({.} &StrRightBack(fName,{.}))
                Dim path As String
'                path=tmp.getAbsolutePath()
'                Print {temp file:} path
'                Set fos=osClass.Createobject({(Ljava/io/File;)V}, tmp)
'                Print {is size: }ret.getInputStream().available()
'                Call IOUtils.copy(ret.getInputStream(), fos)
                path=me.XAgentObj.getTempFromRet(ret)
                MsgBox path
                'Set fos=osClass.Createobject({(Ljava/io/File;)V}, tmp)
            End If
        End If
    End Sub

    %REM
        Function tempFile
        Description: Comments for Function
    %END REM
    Function tempFile(ext As String) As Variant
        On Error GoTo ErrH
        GoTo Continue
ErrH:
        Error Err, Me.RaiseError
Continue:
        Dim FileClass As JavaClass
        Set FileClass = jSession.GetClass({java.io.File})
        Set tempFile=FileClass.createTempFile({tmp},ext)
    End Function
    %REM
        Function fileFromPath
        Description: java File from path
    %END REM
    Function fileFromPath(sPAth As String)
        On Error GoTo ErrH
        GoTo Continue
ErrH:
        Error Err, RaiseError
Continue:
        Dim FileClass As JavaClass
        Set FileClass = jSession.GetClass({java.io.File})
        Set fileFromPath=FileClass.CreateObject({(Ljava/lang/String;)V}, sPath)
    End Function

End Class
в вызове XAgent.test параметр не используется, обращение идет к хэпаге дающей на выходе бинарный файл (конкретнее docx)
 
Последнее редактирование:
  • Нравится
Реакции: alexas1

lmike

нет, пердело совершенство
Lotus Team
27.08.2008
7 963
611
BIT
317
отступление про токены
выше-указанный подход использует создание токена "руками" для любого юзера..., НО код будет работать только под администратором, с правами чтения ключа в АК
т.е. запустить можно и из LS (через бридж), но это в любом случае будет агент (т.к. нужно иметь возможность задать выполнение кода с "нужными" правами). В самих хэпагах есть возможность эскалации прав в сессии, в классике только вызовом агента (с нужными правами)
Есть , НО и там нюанецы ;) - надо копировать документ SSO в "общий", с названием LtpaToken (по ссылке это описано)
Как упомянул - любой вариант подразумевает вызов агента (LS или java - дело вкуса фламастеров и осознания +-)
 
Последнее редактирование:

lmike

нет, пердело совершенство
Lotus Team
27.08.2008
7 963
611
BIT
317
Все это забавно, но скучно ;)
а вот что действительно интересует - детали передачи данных в хэпаги и обратно
способов несколько:
  1. файл туда, файл обратно
  2. файл туда, текст обратно (под тесктом м.б. как неструктурированный так и json)
  3. текст туда, файл обратно
  4. самое интересное - текст + файл туда (обратно уже неинтересно ;) )
первый и третий вариант я уже описывал (в т.ч. в теме про aspose, четвертый, "в ваших интернетах" надо гуглить и подбирать/допиливать
вот именно это я и сделал...
отправка мултиформы и получение результата на клиентской стороне (учитывая специфику авторизации)
Java:
/*****************/
import java.io.InputStream;

public class HttpRet {
    StringBuffer buf=new StringBuffer();
    InputStream is=null;
    String contentType="";
    String contentDisposition="";

    public long getContentLength() {
        return contentLength;
    }

    long contentLength=0;
    int status=-1;
    public String toString(){
        return buf.toString();
    }

    public int getStatus(){
        return status;
    }

    public InputStream getInputStream(){
        return this.is;
    }

    public String getContentType() {
        return contentType;
    }

    public String getContentDisposition() {
        return contentDisposition;
    }

}
/*****************/
import lotus.domino.*;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.StringUtils;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;

import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;

/**
* This utility class provides an abstraction layer for sending multipart HTTP
* POST requests to a web server.
* @author www.codejava.net
*
*/
public class MultipartUtility {
    private final String boundary;
    private static final String LINE_FEED = "\r\n";
    private HttpURLConnection httpConn;
    private String charset;
    private OutputStream outputStream;
    private PrintWriter writer;
    String sCookies=null;
    private boolean isError;
    final static String DATA_DIR="";
    /**
     * This constructor initializes a new HTTP POST request with content type
     * is set to multipart/form-data
     * @param requestURL
     * @param charset
     * @throws IOException
     */
    public MultipartUtility(String requestURL, String charset, String token)
            throws IOException {
        this.charset = charset;

        // creates a unique boundary based on time stamp
        boundary = "===" + System.currentTimeMillis() + "===";

        URL url = new URL(requestURL);
        httpConn = (HttpURLConnection) url.openConnection();
        httpConn.setRequestProperty("Cookie",token);
        httpConn.setUseCaches(false);
        httpConn.setDoOutput(true); // indicates POST method
        httpConn.setDoInput(true);
        httpConn.setRequestProperty("Content-Type",
                "multipart/form-data; boundary=" + boundary);
        outputStream = httpConn.getOutputStream();
        writer = new PrintWriter(new OutputStreamWriter(outputStream, charset),
                true);
    }

    /**
     * Adds a form field to the request
     * @param name field name
     * @param value field value
     */
    public void addFormField(String name, String value) {
        writer.append("--" + boundary).append(LINE_FEED);
        writer.append("Content-Disposition: form-data; name=\"" + name + "\"")
                .append(LINE_FEED);
        writer.append("Content-Type: text/plain; charset=" + charset).append(
                LINE_FEED);
        writer.append(LINE_FEED);
        writer.append(value).append(LINE_FEED);
        writer.flush();
    }

    /**
     * Adds a upload file section to the request
     * @param fieldName name attribute in <input type="file" name="..." />
     * @param uploadFile a File to be uploaded
     * @throws IOException
     */
    public void addFilePart(String fieldName, File uploadFile)
            throws IOException {
        String fileName = uploadFile.getName();
        writer.append("--" + boundary).append(LINE_FEED);
        writer.append(
                "Content-Disposition: form-data; name=\"" + fieldName
                        + "\"; filename=\"" + fileName + "\"")
                .append(LINE_FEED);
      
        String ext=StringUtils.substringAfterLast(fileName,".");
        String type=MIMEType.get(ext);
      
        writer.append(
                "Content-Type: "
                        + type)//URLConnection.guessContentTypeFromName(fileName))
                .append(LINE_FEED);

        System.out.println("extension/Content-type: "+ext+"/"+type);
        writer.append("Content-Transfer-Encoding: binary").append(LINE_FEED);
        writer.append(LINE_FEED);
        writer.flush();

        FileInputStream inputStream = new FileInputStream(uploadFile);
        byte[] buffer = new byte[4096];
        int bytesRead = -1;
        while ((bytesRead = inputStream.read(buffer)) != -1) {
            outputStream.write(buffer, 0, bytesRead);
        }
        outputStream.flush();
        inputStream.close();

        writer.append(LINE_FEED);
        writer.flush();
    }

    /**
     * Adds a header field to the request.
     * @param name - name of the header field
     * @param value - value of the header field
     */
    public void addHeaderField(String name, String value) {
        writer.append(name + ": " + value).append(LINE_FEED);
        writer.flush();
    }

    /**
     * Completes the request and receives response from the server.
     * @return a list of Strings as response in case the server returned
     * status OK, otherwise an exception is thrown.
     * @throws IOException
     */
    public HttpRet finish() throws IOException {
        List<String> response = new ArrayList<String>();

        writer.append(LINE_FEED).flush();
        writer.append("--" + boundary + "--").append(LINE_FEED);
        writer.close();

        // checks server's status code first
        HttpRet ret=new HttpRet();
        ret.status = httpConn.getResponseCode();
        switch (ret.status) {
            case HttpURLConnection.HTTP_OK:
                // read from the urlconnection via the bufferedreader
                ret.is = httpConn.getInputStream();
                ret.contentDisposition=httpConn.getHeaderField("Content-Disposition");
                ret.contentType=httpConn.getContentType();
                ret.contentLength=httpConn.getContentLength();
                if (ret.contentType.contains("json") || httpConn.getContentType().contains("text")) {
                    System.out.println("text Content");
                    BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(httpConn.getInputStream()));
                    String line;
                    while ((line = bufferedReader.readLine()) != null) {
                        ret.buf.append(line);
                        // System.out.println("Response: " + line);
                    }
                    bufferedReader.close();
                    isError = false;
                    Document doc = Jsoup.parseBodyFragment(ret.buf.toString());
                    Element body = doc.body();
                    List<Element> elements=body.getElementsByTag("input");
                    for(Element el:elements){
                        if (el.attributes().get("type").equalsIgnoreCase("password")){
                            isError=true;
                            //ret.buf.setLength(0);
                            //ret.buf.append(doc.outerHtml());
                            break;
                        }
                    }
                    if (isError){
                        Element el=body.getElementsByTag("h1").get(0);
                        ret.buf.setLength(0);
                        ret.buf.append(el.siblingElements().get(0).text());
                    }else{
                        System.out.println("response:\n"+ret.buf.toString());
                    }
                }else{
                    System.out.println("Content:\n"
                            +ret.contentDisposition
                            +"\nsize: "+ret.contentLength);
                }
                break;
            case HttpURLConnection.HTTP_INTERNAL_ERROR:
                ret.buf.append("Interal server error while running");
                System.out.println(ret.buf.toString());
                break;
            default:
                ret.buf.append(httpConn.getResponseMessage());
                System.out.println("An error occurred: " + ret.status);
                System.out.println("Error message: " + ret.buf.toString());
                break;
        }
        if(isError){
            System.out.println(ret.buf.toString());
        }

/*
        if (status == HttpURLConnection.HTTP_OK) {
            BufferedReader reader = new BufferedReader(new InputStreamReader(
                    httpConn.getInputStream()));
            String line = null;
            while ((line = reader.readLine()) != null) {
                response.add(line);
            }
            reader.close();
            httpConn.disconnect();
        } else {
            throw new IOException("Server returned non-OK status: " + status);
        }

*/
        return ret;
    }
  
    public void copyIs2File(InputStream is, File file) throws IOException{
        FileUtils.copyInputStreamToFile(is, file);
    }

public static void main(String[]args) throws IOException {
    Authorization authorization=new Authorization();
    String token=authorization.authorize();
    System.out.println(token);
    String findAndRepplace="https://server/pathToDB/xpage.xsp";
    MultipartUtility form=new MultipartUtility(findAndRepplace,"UTF-8", token);
    form.addFormField("<SPA_POSITION>","Генерал");
    form.addFormField("<SPA_WHOM>","Кузнецов");
    form.addFormField("<SPA_BASIS>","Устава");
    form.addFilePart("body", new File(DATA_DIR+"test.docx"));
    HttpRet ret=form.finish();
    if (ret.is!=null){
        String outName=DATA_DIR + "out.docx";
        FileUtils.copyInputStreamToFile(ret.is, new File(outName));
        Runtime.getRuntime().exec("gio open "+outName);
    }
}
}
код цельнотянутый с изменениями по получению результата
серверная часть, ссылки (откуда тянул) в каментах
Java:
import com.aspose.words.Document;
import com.aspose.words.FindReplaceOptions;
import com.aspose.words.NodeCollection;
import com.aspose.words.NodeType;
import com.aspose.words.Table;
import com.ibm.icu.impl.locale.XCldrStub.Joiner;
import com.ibm.xsp.context.FacesContextEx;
import com.ibm.xsp.webapp.XspHttpServletResponse;

import java.util.logging.Level;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.List;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.regex.Pattern;
import java.util.zip.ZipOutputStream;

import javax.faces.context.ExternalContext;
import javax.faces.context.FacesContext;
import javax.servlet.http.HttpServletRequest;

import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.fileupload.FileItem;
import com.ibm.xsp.http.UploadedFile;

import org.openntf.domino.xsp.XspOpenLogUtil;

public class FindAndReplace {
    private static final String BODY = "body";
    final com.aspose.words.License license;

    class PostFormMulti {
        Map<String, String> map = new HashMap<String, String>();
        InputStream is = null;
        public String fileName;
        public String contentType;
        public Map<String, UploadedFile> mapFiles;
    }

    public FindAndReplace() throws Exception {
        license = new com.aspose.words.License();
        InputStream is = // new FileInputStream("Aspose.Total.Java.lic");
                FacesContextEx.getCurrentInstance().getExternalContext().getResourceAsStream("Aspose.txt");
        license.setLicense(is);// "/tmp/Aspose.Total.Java.lic");
    }

    public String replace(String regex, Map<String, String> map, InputStream is) throws Exception {
        Document doc = new Document(is);// dataDir + "SpA_SupAgreement.docx");
        FindReplaceOptions options = new FindReplaceOptions();
        options.setReplacingCallback(new ReplaceEvaluator(map));

        doc.getRange().replace(Pattern.compile(regex), "", options);
        File tmp = File.createTempFile("out", ".docx");
        String outName = tmp.getAbsolutePath();
        doc.save(outName);
        return outName;
        // Runtime.getRuntime().exec("gio open "+outName);
    }

    public Map<String, String[]> getFields(String regex, InputStream is) throws Exception {
        Document doc = new Document(is);
        FindReplaceOptions options = new FindReplaceOptions();
        Map<String, String[]> map = new HashMap<String, String[]>();
        options.setReplacingCallback(new FindEvaluator(map));
        doc.getRange().replace(Pattern.compile(regex), "", options);
        return map;
    }

    public List<String> getTablesNames(Document doc) {
        List<String> lst = new ArrayList<String>();
        NodeCollection<Table> tables = doc.getChildNodes(NodeType.TABLE, true);
        for (Table tbl : tables) {
            if (!tbl.getTitle().isEmpty())
                lst.add(tbl.getTitle());
        }
        return lst;
    }

    public Map<String, Table> getTablesNamesMap(Document doc) {
        Map<String, Table> map = new HashMap<String, Table>();
        NodeCollection<Table> tables = doc.getChildNodes(NodeType.TABLE, true);
        int i = 0;
        for (Table tbl : tables) {
            String name = tbl.getTitle();
            if (!name.isEmpty()) {
                if (map.containsKey(name))
                    name += "+" + i;
                map.put(name, tbl);
            }
            i++;
        }
        return map;
    }

    public Table getTableByName(String name, Document doc) {
        Table ret = null;
        NodeCollection<Table> tables = doc.getChildNodes(NodeType.TABLE, true);
        for (Table tbl : tables) {
            String title = tbl.getTitle();
            if (!title.isEmpty() && title.equalsIgnoreCase(name)) {
                ret = tbl;
                break;
            }
        }
        return ret;
    }

    public void replaceRows(Table firstTable, Table secondTable) {
        firstTable.getRows().clear();
        while (secondTable.hasChildNodes())
            firstTable.getRows().add(secondTable.getFirstRow());
    }

    public int replaceAndOut() {
        Throwable throwable = new Throwable();
        int status = HttpURLConnection.HTTP_INTERNAL_ERROR;
        InputStream is = null;
        FacesContext fc = FacesContext.getCurrentInstance();
        ExternalContext ex = fc.getExternalContext();
        HttpServletRequest request = (HttpServletRequest) ex.getRequest();
        try {
            PostFormMulti pfm = this.processPost(request, MIMEType.get("docx"));
            is = pfm == null ? null : pfm.is;// request.getInputStream();
            status = HttpURLConnection.HTTP_NOT_FOUND;
            if (is != null
            /*
             * && request.getContentType()!=null &&
             * request.getContentType().contains( MIMEType.get("docx"))
             */ ) {
                XspHttpServletResponse xspResponse = (XspHttpServletResponse) ex.getResponse();
                javax.servlet.http.HttpServletResponse response = xspResponse.getDelegate();
                String type = MIMEType.get("docx");
                // response.setHeader("Content-Type",type);
                // https://www.slideshare.net/JohnFoldager/xpages-binary-output
                xspResponse.setContentType(type);
                xspResponse.setHeader("Cache-Control", "no-cache");
                xspResponse.setHeader("Pragma", "no-store");
                xspResponse.setHeader("Content-Disposition", "attachment; filename=replaced.docx");
                OutputStream os = xspResponse.getOutputStream();

                Map<String, String> map = pfm.map;// new
                                                    // HashMap<String,String>();
                /*
                 * map.put("<SPA_POSITION>","Генерал");
                 * map.put("<SPA_WHOM>","Кузнецов");
                 */

                String fName;
                try {
                    fName = replace("(<.+?>)", map// processParams(request)
                            , is);// FacesContext.getCurrentInstance().getExternalContext().getResourceAsStream(testName));
                    Path path = Paths.get(fName);
                    long bytes = Files.copy(path, os);
                    XspOpenLogUtil.logEvent(null, "path to result: " + fName, Level.INFO, null);
                    xspResponse.setHeader("Content-Length", String.valueOf(bytes));
                    os.close();
                    fc.responseComplete();
                    status = HttpURLConnection.HTTP_OK;
                    File tmp = new File(fName);
                    tmp.delete();
                } catch (Exception e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                    XspOpenLogUtil.logError(e);
                }
            } else {
                XspOpenLogUtil.logEvent(null, "InputStream is null", Level.INFO, null);
            }
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
            XspOpenLogUtil.logError(e);
        }
        return status;
    }

    // https://stackoverflow.com/questions/2422468/how-to-upload-files-to-server-using-jsp-servlet/2424824#2424824
    protected PostFormMulti processPost(HttpServletRequest request, String mimeFilter) throws IOException {
        PostFormMulti pfm = new PostFormMulti();
        try {
            List<FileItem> items = new ServletFileUpload(new DiskFileItemFactory()).parseRequest(request);
            for (FileItem item : items) {
                if (item.isFormField()) {
                    // Process regular form field (input
                    // type="text|radio|checkbox|etc", select, etc).
                    String fieldName = item.getFieldName();
                    String fieldValue = item.getString();
                    // ... (do your job here)
                    pfm.map.put(fieldName, fieldValue);
                } else {
                    // Process form file field (input type="file").
                    // String fieldName = item.getFieldName();

                    if (!item.getContentType().contains(mimeFilter))
                        return null;

                    pfm.fileName = FilenameUtils.getName(item.getName());
                    // InputStream fileContent = item.getInputStream();
                    // ... (do your job here)
                    pfm.is = item.getInputStream();

                }
            }
            if (items.size() == 0) {
                for (Map.Entry<String, Object> e : ((Map<String, Object>) request.getParameterMap()).entrySet()) {
                    if (e.getValue() instanceof com.ibm.xsp.http.UploadedFile) {
                        com.ibm.xsp.http.UploadedFile fileItem = (com.ibm.xsp.http.UploadedFile) e.getValue();
                        pfm.contentType = fileItem.getContentType();
                        if (e.getKey().equals(BODY)) {
                            if (fileItem.getContentType().contains(mimeFilter)) {
                                pfm.fileName = fileItem.getClientFileName();
                                pfm.is = new FileInputStream(fileItem.getServerFile());
                            } else {
                                pfm.fileName = Joiner.on("\n").join(fileItem.getClientFileNames());
                                // fileItem.getClientFileNames()
                            }
                        }else{
                            pfm.mapFiles.put(e.getKey(), fileItem);
                        }
                    } else {
                        pfm.map.put(e.getKey(), String.valueOf(e.getValue()));
                    }
                }
            }

            XspOpenLogUtil.logEvent(null,
                    "Content-type: " + request.getContentType() + "\nParams map:\n"
                            + Joiner.on("\n").join(pfm.map.entrySet())// +Joiner.on("\n").join(request.getParameterMap().entrySet())
                            + "\nFile name: " + pfm.fileName + "\nFile type: " + pfm.contentType + "\nFile size: "
                            + String.valueOf(pfm.is != null ? pfm.is.available() : 0)
                    // +"\nform items: "+ String.valueOf(items.size())
                    // +"\nField
                    // Map:\n"+Joiner.on("\n").join(pfm.map.entrySet())
                    , Level.INFO, null);
            return pfm;
        } catch (FileUploadException e) {
            e.printStackTrace();
            XspOpenLogUtil.logError(e);
        }

        return null;
    }

    private Map<String, String> processParams(HttpServletRequest req) {
        Enumeration<String> parameterNames = req.getParameterNames();
        Map<String, String> map = new HashMap<String, String>();
        while (parameterNames.hasMoreElements()) {

            String paramName = parameterNames.nextElement();
            // only first value
            map.put(paramName, req.getParameterValues(paramName)[0]);
            /*
             * for (int i = 0; i < paramValues.length; i++) { String paramValue
             * = paramValues[i]; out.write("t" + paramValue); out.write("n"); }
             */
        }
        return map;
    }

    public long replace2out(Map<String, String> map, InputStream docis, OutputStream os) throws Exception {
        String fName = replace("(<.+?>)", map, docis);
        Path path = Paths.get(fName);
        long bytes = Files.copy(path, os);
        return bytes;
    }

}
ф-ции по обработке запроса - processPost и replace, причем вариант по ссылке не получает поля, в if (items.size() == 0) я написал работающий
 
Последнее редактирование:
Мы в соцсетях:

Обучение наступательной кибербезопасности в игровой форме. Начать игру!