• 15 апреля стартует «Курс «SQL-injection Master» ©» от команды The Codeby

    За 3 месяца вы пройдете путь от начальных навыков работы с SQL-запросами к базам данных до продвинутых техник. Научитесь находить уязвимости связанные с базами данных, и внедрять произвольный SQL-код в уязвимые приложения.

    На последнюю неделю приходится экзамен, где нужно будет показать свои навыки, взломав ряд уязвимых учебных сайтов, и добыть флаги. Успешно сдавшие экзамен получат сертификат.

    Запись на курс до 25 апреля. Получить промодоступ ...

ODA (OpenNTF Domino API)

lmike

нет, пердело совершенство
Lotus Team
27.08.2008
7 941
609
BIT
214
Здесь буду излагать свой опыт, ибо в тырнетах документация скудная, как говорил Вини-Пух "оно хорошее, но почему-то хромает"

Есть всякие слайды "древние", в основном 2013-2014 гг





(которую с трудом, но завел, отдельная тема) и в слайдах на неё ссылаются (OpenNTF/org.openntf.domino)
вебинар по ней
на гитхабе устаревший "местами" код и в современной ODA он даст ошибку компиляции - надо подправить получение сессии.

Логирование
В состав ODA уже включен OpenNTF logger, вызывается несколько иначе, чем изначально было без ODA
Java:
XspOpenLogUtil.logEvent(new Throwable(), classID, Level.INFO, null);
как пример, т.е. XspOpenLogUtil.log в это отмечено
по странному стечению - найти шаблон для БД оказалось трудной задачей, но на opnentf.org таки
без шаблона все не айс - доки будут а смотреть нечем ;)

ODA регулярно ообновляется и развивается, для домино 9.0.1 ФП7 (т.е. <ФП8) версия д.б. 3.2.1 (последняя, по докам, новее требуют новее ФП)
Тем более странно - подробной документации, свежей, и слайдов нет

Из моих ощущений...
- легче прогать с доминошными объектами (можно забыть про recycle)
- удобно обновлять значения в доках - из хэшмапа
Java:
package com.setralubs;

import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.logging.Level;

import org.openntf.domino.Database;
import org.openntf.domino.Document;
import org.openntf.domino.Item;
import org.openntf.domino.Session;
import org.openntf.domino.View;
import org.openntf.domino.utils.Factory;
import org.openntf.domino.utils.Factory.SessionType;
import org.openntf.domino.xsp.XspOpenLogUtil;

public abstract class ODAItems {
    static final String[] AUTHORS = {"[author]"};//role for all doc authors
    static final String[] READERS = {"[DbReader]","[DbManager]"};
    static final String AVAIL_FOR_FLD="avail_for";//authors field for current user (document creator)
    //users and roles could change doc
    static final String AUTHORS_FLD="authors";//includes AUTHORS by default
    //could contains DB readers users, includes READERS by default
    static final String EDITORS_FLD="editors";//contains roles for reading (doc visibility for users with access level >=editor)
    private final Map <String,Object> access;

  
    Session ses;
    Database db;
    View view;
    private final String classID="::" + this.getClass().getName() + "::";
    String form;

    ODAItems(String viewName) {
        XspOpenLogUtil.logEvent(new Throwable(), classID, Level.INFO, null);
        ses = Factory.getSession();//SessionType.NATIVE
        db = ses.getCurrentDatabase();
        view = db.getView(viewName);
        access=fillAcess();
        if (view != null)
            view.setAutoUpdate(false);
        else
            XspOpenLogUtil.logErrorEx(null, classID+"view is null:"+viewName, Level.INFO, null);
    }

    Map<String,Object> fillAcess(){
        Map<String,Object> map=new HashMap<String,Object>();
        map.put(AVAIL_FOR_FLD,ses.getEffectiveUserName());
        map.put(AUTHORS_FLD,AUTHORS);
        map.put(EDITORS_FLD, READERS);
        return map;
    }

    Document setDefAccess(Document doc, String userName){
        Item item = doc.replaceItemValue(AUTHORS_FLD, AUTHORS);
        item.setAuthors(true);
        item = doc.replaceItemValue(AVAIL_FOR_FLD, userName);
        item.setAuthors(true);
        item = doc.replaceItemValue(EDITORS_FLD, READERS);
        item.setReaders(true);
        return doc;
    }

    /*
     * (non-Javadoc)
     *
     * @see com.setralubs.ODAItems#updateItem(java.util.Map)
     */
    public void updateItems(Map<String, Map<String, Object>> map) {
        /*
         * ViewNavigator nav = view.createViewNav(); nav.skip(1000000);
         *
         * System.out.println("CacheSize: " + nav.getCacheSize());
         */
        if (view != null) {
            Document doc = null;
            for (Entry<String, Map<String, Object>> flds : map.entrySet()) {
                doc = view.getFirstDocumentByKey(flds.getKey(), true);
                if (doc != null)
                    doc.putAll(flds.getValue());
                else
                    doc = db.createDocument(flds.getValue());
                doc.replaceItemValue("form",form);
                doc.putAll(access);
                doc.save();
            }
            // view.setAutoUpdate(true);
        }
    }

    /*
     * (non-Javadoc)
     *
     * @see com.setralubs.ODAItems#updateItem(java.lang.String, java.util.Map)
     */
    public void updateItem(String key, Map<String, String> value) {
        if (view != null && key!=null && !key.isEmpty()) {
            Document doc = null;
            doc = view.getFirstDocumentByKey(key, true);
            if (doc != null)
                doc.putAll(value);
            else
                doc = db.createDocument(value);
            doc.replaceItemValue("form",form);
            setDefAccess(doc, ses.getEffectiveUserName()).save();
        }
    }
  
    public Document setAccess(Document doc) {
      
        return doc;
    }

}
- логи снимают гимор с выводом информации и отладкой
- в логах подробно дается стек-трейс из xsp
JavaScript:
}catch(e){
  //_dump(e);
  org.openntf.domino.xsp.XspOpenLogUtil.logError(e);
}
т.е. _dump становится ненужным (да и толку отнего, при большом трейсе, нет)
 
Последнее редактирование:

lmike

нет, пердело совершенство
Lotus Team
27.08.2008
7 941
609
BIT
214
в логе можно не указывать первый параметр (null) XspOpenLogUtil.logEvent(new Throwable(), classID, Level.INFO, null);
но тогда не получим имя метода
и сообщение попадет и в поле ошибки (хотя ошибко считаться не будет) вот так получится
1532614674015.png

еще смущает момент - имя класса, для метода, совершенно не относится к делу ;)
1532614539638.png
 
  • Нравится
Реакции: Иван Пахомов

lmike

нет, пердело совершенство
Lotus Team
27.08.2008
7 941
609
BIT
214
небольшая хитрость по анализу доков опираясь на фичу получения Map из доков и энтрисов
Java:
    public void updateItem(String key, Map<String, String> value) {
        if (view != null && key != null && !key.isEmpty()
                && !list.contains(key)) {
            Document doc = null;
            ViewEntry entry = view.getFirstEntryByKey(key, true);
            // doc = view.getFirstDocumentByKey(key, true);
            boolean bSave = false;
            if (entry != null) {
                bSave = !entry.getColumnValuesMap().entrySet().containsAll(
                        value.entrySet());
                // doc = entry.getDocument();
                // bSave = !doc.asDocMap().entrySet()
                // .containsAll(value.entrySet());
                if (bSave) {
                    doc = entry.getDocument();
                    logBody.appendText(entry.getColumnValuesMap().entrySet().toString());
                    // logBody.appendText(doc.asDocMap().entrySet().toString());
                    logBody.addNewLine();
                    logBody.appendText("update doc with:");
                    doc.putAll(value);
                }
            } else {
                bSave = true;
                logBody.appendText("new doc with:");
                doc = db.createDocument(value);
                doc.replaceItemValue("form", form);
                setDefAccess(doc, ses.getEffectiveUserName());
            }
            if (bSave && doc.save()) {
                logBody.appendText(value.toString());
                logBody.appendDocLink(doc);
                logBody.addNewLine();
                list.add(key);
            }
        }
    }
удобно делать entry.getColumnValuesMap().entrySet().containsAll(value.entrySet());
где value - Map на входе, не надо итераций и мучать вектор для колонок - одна строка и мы устанавливаем отличие заначений.
Dьюшка должна содержать программные имена колонок в соответствии с Map.
Из записи лога
[fusion=6/7/18, prodName=-, pack=Act>Evo 2T, basePrice=]
update doc with:{prodName=, fusion=6/7/18, pack=Act>Evo 2T}
первая строка - из колонок вьюшки, вторая значения в value
есть нюанс - doc.asDocMap().entrySet() - в случае пустого значения поля выдаст null соответ. значения:
{prodName=null, fusion=6/7/18, pack=Act>Evo 2T}
, что даст отрицательное сравнение с value, кот. имеет значение "" (пустая строка)!
А вот сотрудник Анатолий был послан entry.getColumnValuesMap().entrySet() но сумел - вернуться бодрым, отдохнувшим и всем магнитики привез отработает корректно
 
Последнее редактирование:
Мы в соцсетях:

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