text:
#include "switch.hpp"
#include "const.hpp"

#ifdef WEBENGINEVIEW

#include "webengineview.hpp"

#include <QQuickWidget>

#include <QWebEngineView>
#include <QWebEnginePage>
#include <QWebEngineHistory>
#include <QWebEngineContextMenuData>
#include <QNetworkRequest>
#include <QDir>
#include <QDrag>
#include <QMimeData>
#include <QTextDocument>
#include <QClipboard>
#include <QTimer>
#include <QStyle>
#include <QKeySequence>

#if defined(Q_OS_WIN)
#  include <windows.h>
#endif

#include "treebank.hpp"
#include "treebar.hpp"
#include "notifier.hpp"
#include "receiver.hpp"
#include "networkcontroller.hpp"
#include "application.hpp"
#include "mainwindow.hpp"

#if QT_VERSION < 0x050B00
QMap<View*, QUrl> WebEngineView::m_InspectorTable = QMap<View*, QUrl>();
#endif

WebEngineView::WebEngineView(TreeBank *parent, QString id, QStringList set)
    : QWebEngineView(TreeBank::PurgeView() ? 0 : static_cast<QWidget*>(parent))
    , View(parent, id, set)
{
#if QT_VERSION >= 0x050900
    SetUpEventFilterInstaller();
#endif

    Initialize();
    NetworkAccessManager *nam = NetworkController::GetNetworkAccessManager(id, set);
    m_Page = new WebEnginePage(nam, this);
    ApplySpecificSettings(set);
    setPage(page());

    if(TreeBank::PurgeView()){
        setWindowFlags(Qt::FramelessWindowHint);
    } else {
        if(parent) setParent(parent);
    }
    setMouseTracking(true);
    setAcceptDrops(true);
    setAttribute(Qt::WA_AcceptTouchEvents);

    m_Inspector = 0;
    m_PreventScrollRestoration = false;
    m_ScrollSignalTimer = 0;
#ifdef PASSWORD_MANAGER
    m_PreventAuthRegistration = false;
#endif
    connect(this, SIGNAL(iconChanged(const QIcon&)),
            this, SLOT(OnIconChanged(const QIcon&)));
}

WebEngineView::~WebEngineView(){
    setPage(0);
#if QT_VERSION < 0x050B00
    m_InspectorTable.remove(this);
#endif
    if(m_Inspector) m_Inspector->deleteLater();
}

#if QT_VERSION >= 0x050900
void WebEngineView::SetUpEventFilterInstaller(){
    static bool checked = false;
    if(checked) return;
    checked = true;

    connect(Application::GetInstance(), &Application::focusChanged, [](QWidget*, QWidget* widget){

        if(widget && widget->parentWidget() &&
           0 == strcmp(widget->metaObject()->className(),
                       "QtWebEngineCore::RenderWidgetHostViewQtDelegateWidget")){

            if(WebEngineView *wev = qobject_cast<WebEngineView*>(widget->parentWidget())){

                bool haveEventEater = false;

                foreach(QObject *obj, widget->children()){
                    if(0 == strcmp(obj->metaObject()->className(), "EventEater")){
                        haveEventEater = true;
                        break;
                    }
                }
                if(!haveEventEater)
                    widget->installEventFilter(new EventEater(wev, widget));
            }
        }
    });
}
#endif

QWebEngineView *WebEngineView::base(){
    return static_cast<QWebEngineView*>(this);
}

WebEnginePage *WebEngineView::page(){
    return static_cast<WebEnginePage*>(View::page());
}

QUrl WebEngineView::url(){
    return base()->url();
}

QString WebEngineView::html(){
    return WholeHtml();
}

TreeBank *WebEngineView::parent(){
    return m_TreeBank;
}

void WebEngineView::setUrl(const QUrl &url){
    base()->setUrl(url);
    emit urlChanged(url);
}

void WebEngineView::setHtml(const QString &html, const QUrl &url){
    base()->setHtml(html, url);
    emit urlChanged(url);
}

void WebEngineView::setParent(TreeBank* tb){
    View::SetTreeBank(tb);
    if(!TreeBank::PurgeView()) base()->setParent(tb);
    if(page()) page()->AddJsObject();
    if(tb) resize(size());
}

void WebEngineView::Connect(TreeBank *tb){
    View::Connect(tb);

    if(!tb || !page()) return;

    connect(this, SIGNAL(titleChanged(const QString&)),
            tb->parent(), SLOT(SetWindowTitle(const QString&)));
    if(Notifier *notifier = tb->GetNotifier()){
        connect(this, SIGNAL(statusBarMessage(const QString&)),
                notifier, SLOT(SetStatus(const QString&)));
        connect(this, SIGNAL(statusBarMessage2(const QString&, const QString&)),
                notifier, SLOT(SetStatus(const QString&, const QString&)));
        connect(page(), SIGNAL(linkHovered(const QString&, const QString&, const QString&)),
                notifier, SLOT(SetLink(const QString&, const QString&, const QString&)));

        connect(this, SIGNAL(ScrollChanged(QPointF)),
                notifier, SLOT(SetScroll(QPointF)));
        connect(notifier, SIGNAL(ScrollRequest(QPointF)),
                this, SLOT(SetScroll(QPointF)));
    }
    if(Receiver *receiver = tb->GetReceiver()){
        connect(receiver, SIGNAL(OpenBookmarklet(const QString&)),
                this, SLOT(Load(const QString&)));
        connect(receiver, SIGNAL(SeekText(const QString&, View::FindFlags)),
                this, SLOT(SeekText(const QString&, View::FindFlags)));
        connect(receiver, SIGNAL(KeyEvent(QString)),
                this, SLOT(KeyEvent(QString)));

        connect(receiver, SIGNAL(SuggestRequest(const QUrl&)),
                page(), SLOT(DownloadSuggest(const QUrl&)));
        connect(page(), SIGNAL(SuggestResult(const QByteArray&)),
                receiver, SLOT(DisplaySuggest(const QByteArray&)));
    }
}

void WebEngineView::Disconnect(TreeBank *tb){
    View::Disconnect(tb);

    if(!tb || !page()) return;

    disconnect(this, SIGNAL(titleChanged(const QString&)),
               tb->parent(), SLOT(SetWindowTitle(const QString&)));
    if(Notifier *notifier = tb->GetNotifier()){
        disconnect(this, SIGNAL(statusBarMessage(const QString&)),
                   notifier, SLOT(SetStatus(const QString&)));
        disconnect(this, SIGNAL(statusBarMessage2(const QString&, const QString&)),
                   notifier, SLOT(SetStatus(const QString&, const QString&)));
        disconnect(page(), SIGNAL(linkHovered(const QString&, const QString&, const QString&)),
                   notifier, SLOT(SetLink(const QString&, const QString&, const QString&)));

        disconnect(this, SIGNAL(ScrollChanged(QPointF)),
                   notifier, SLOT(SetScroll(QPointF)));
        disconnect(notifier, SIGNAL(ScrollRequest(QPointF)),
                   this, SLOT(SetScroll(QPointF)));
    }
    if(Receiver *receiver = tb->GetReceiver()){
        disconnect(receiver, SIGNAL(OpenBookmarklet(const QString&)),
                   this, SLOT(Load(const QString&)));
        disconnect(receiver, SIGNAL(SeekText(const QString&, View::FindFlags)),
                   this, SLOT(SeekText(const QString&, View::FindFlags)));
        disconnect(receiver, SIGNAL(KeyEvent(QString)),
                   this, SLOT(KeyEvent(QString)));

        disconnect(receiver, SIGNAL(SuggestRequest(const QUrl&)),
                   page(), SLOT(DownloadSuggest(const QUrl&)));
        disconnect(page(), SIGNAL(SuggestResult(const QByteArray&)),
                   receiver, SLOT(DisplaySuggest(const QByteArray&)));
    }
}

void WebEngineView::OnSetViewNode(ViewNode*){}

void WebEngineView::OnSetHistNode(HistNode*){}

void WebEngineView::OnSetThis(WeakView){}

void WebEngineView::OnSetMaster(WeakView){}

void WebEngineView::OnSetSlave(WeakView){}

void WebEngineView::OnSetJsObject(_View*){}

void WebEngineView::OnSetJsObject(_Vanilla*){}

void WebEngineView::OnLoadStarted(){
    if(!GetHistNode()) return;

    View::OnLoadStarted();

    emit statusBarMessage(tr("Started loading."));
    m_PreventScrollRestoration = false;

#if QT_VERSION < 0x050B00
    AssignInspector();
#endif
}

void WebEngineView::OnLoadProgress(int progress){
    if(!GetHistNode()) return;
    View::OnLoadProgress(progress);
    // loadProgress: 100% signal is emitted after loadFinished.
    if(progress != 100)
        emit statusBarMessage(tr("Loading ... (%1 percent)").arg(progress));
}

void WebEngineView::OnLoadFinished(bool ok){
    if(!GetHistNode()) return;

    View::OnLoadFinished(ok);

    QUrl historyUrl;
    if(history()->count()){
        historyUrl = history()->currentItem().url();
    }
    if(!url().isEmpty() && url().toEncoded().startsWith("view-source:")){
        // why history's url doesn't start with "view-source:"....?
        emit urlChanged(url());
    } else if(!historyUrl.isEmpty()){
        emit urlChanged(historyUrl);
    } else if(!url().isEmpty()){
        emit urlChanged(url());
    }
    if(!ok){
        emit statusBarMessage(tr("Failed to load."));
        return;
    }

    RestoreScroll();
    emit ViewChanged();
    emit statusBarMessage(tr("Finished loading."));

#if QT_VERSION < 0x050B00
    AssignInspector();
#endif

#ifdef PASSWORD_MANAGER
    QString data = Application::GetAuthDataWithNoDialog
        (page()->profile()->storageName() +
         QStringLiteral(":") + url().host());

    if(!data.isEmpty())
        page()->runJavaScript(DecorateFormFieldJsCode(data));
#endif //ifdef PASSWORD_MANAGER

    if(visible() && m_TreeBank &&
       m_TreeBank->GetMainWindow()->GetTreeBar()->isVisible()){
        UpdateThumbnail();
    }
}

void WebEngineView::OnTitleChanged(const QString &title){
    if(!GetHistNode()) return;
    ChangeNodeTitle(title);
}

void WebEngineView::OnUrlChanged(const QUrl &uri){
    if(!GetHistNode()) return;
    SaveHistory();
    ChangeNodeUrl(uri);
}

void WebEngineView::OnViewChanged(){
    if(!GetHistNode()) return;
    TreeBank::AddToUpdateBox(GetThis().lock());
}

void WebEngineView::OnScrollChanged(){
    if(!GetHistNode()) return;
    SaveScroll();
}

void WebEngineView::EmitScrollChanged(){
    if(!page()) return;
    if(!m_ScrollSignalTimer)
        m_ScrollSignalTimer = startTimer(200);
}

void WebEngineView::CallWithScroll(PointFCallBack callBack){
    if(!page() || url().isEmpty() || url() == BLANK_URL){
        // sometime cause crash.
        //callBack(QPointF(0.5f, 0.5f));
        return;
    }
    page()->runJavaScript
        (GetScrollRatioPointJsCode(), [callBack](QVariant var){
            if(!var.isValid()) return callBack(QPointF(0.5f, 0.5f));
            QVariantList list = var.toList();
            callBack(QPointF(list[0].toFloat(),list[1].toFloat()));
        });
}

void WebEngineView::SetScrollBarState(){
    if(!page()) return;
    page()->runJavaScript
        (GetScrollBarStateJsCode(), [this](QVariant var){
            Q_UNUSED(this);
            if(!var.isValid()) return;
            QVariantList list = var.toList();
            int hmax = list[0].toInt();
            int vmax = list[1].toInt();
            if(hmax < 0) hmax = 0;
            if(vmax < 0) vmax = 0;
            if(hmax && vmax) m_ScrollBarState = BothScrollBarEnabled;
            else if(hmax)    m_ScrollBarState = HorizontalScrollBarEnabled;
            else if(vmax)    m_ScrollBarState = VerticalScrollBarEnabled;
            else             m_ScrollBarState = NoScrollBarEnabled;
        });
}

QPointF WebEngineView::GetScroll(){
    if(!page()) return QPointF(0.5f, 0.5f);
    // this function does not return actual value on WebEngineView.
    return QPointF(0.5f, 0.5f);
}

void WebEngineView::SetScroll(QPointF pos){
    if(!page()) return;
    page()->runJavaScript(SetScrollRatioPointJsCode(pos), [](QVariant){});
}

bool WebEngineView::SaveScroll(){
    if(!page()) return false;
    page()->runJavaScript
        (GetScrollValuePointJsCode(), [this](QVariant var){
            if(!var.isValid() || !GetHistNode()) return;
            QVariantList list = var.toList();
            GetHistNode()->SetScrollX(list[0].toInt());
            GetHistNode()->SetScrollY(list[1].toInt());
        });
    return true;
}

bool WebEngineView::RestoreScroll(){
    if(!page() || !GetHistNode()) return false;
    if(m_PreventScrollRestoration) return false;
    QPoint pos = QPoint(GetHistNode()->GetScrollX(),
                        GetHistNode()->GetScrollY());
    page()->runJavaScript(SetScrollValuePointJsCode(pos));
    return true;
}

bool WebEngineView::SaveZoom(){
    if(!GetHistNode()) return false;
    GetHistNode()->SetZoom(zoomFactor());
    return true;
}

bool WebEngineView::RestoreZoom(){
    if(!GetHistNode()) return false;
    setZoomFactor(static_cast<qreal>(GetHistNode()->GetZoom()));
    return true;
}

bool WebEngineView::SaveHistory(){
    if(!GetHistNode()) return false;
    QByteArray ba;
    QDataStream stream(&ba, QIODevice::WriteOnly);
    stream << (*history());
    if(!ba.isEmpty()){
        GetHistNode()->SetHistoryData(ba);
        return true;
    }
    return false;
}

bool WebEngineView::RestoreHistory(){
    if(!GetHistNode()) return false;

    QByteArray ba = GetHistNode()->GetHistoryData();
    if(!ba.isEmpty()){
        QDataStream stream(&ba, QIODevice::ReadOnly);
        stream >> (*history());
        return history()->count() > 0;
    }
    return false;
}

void WebEngineView::KeyEvent(QString key){
    TriggerKeyEvent(key);
}

bool WebEngineView::SeekText(const QString &str, View::FindFlags opt){
    QWebEnginePage::FindFlags flags = 0;
    if(opt & FindBackward)    flags |= QWebEnginePage::FindBackward;
    if(opt & CaseSensitively) flags |= QWebEnginePage::FindCaseSensitively;

    bool ret = true; // dummy value.
    QWebEngineView::findText(str, flags, [](bool){});
    return ret;
}

void WebEngineView::SetFocusToElement(QString xpath){
    page()->runJavaScript(SetFocusToElementJsCode(xpath));
}

void WebEngineView::FireClickEvent(QString xpath, QPoint pos){
    page()->runJavaScript(FireClickEventJsCode(xpath, pos/zoomFactor()));
}

void WebEngineView::SetTextValue(QString xpath, QString text){
    page()->runJavaScript(SetTextValueJsCode(xpath, text));
}

#if QT_VERSION < 0x050B00
void WebEngineView::AssignInspector(){
    if(m_InspectorTable.contains(this)) return;

    QString addr = QStringLiteral("http://localhost:%1").arg(Application::RemoteDebuggingPort());
    QNetworkRequest req(QUrl(addr + QStringLiteral("/json")));
    DownloadItem *item = NetworkController::Download
        (static_cast<NetworkAccessManager*>(page()->networkAccessManager()),
         req, NetworkController::ToVariable);

    if(!item) return;

    item->setParent(base());

    connect(item, &DownloadItem::DownloadResult, [this, addr](const QByteArray &result){

        foreach(QJsonValue value, QJsonDocument::fromJson(result).array()){

            QString debuggeeValue = value.toObject()["url"].toString();
            QString debuggerValue = value.toObject()["devtoolsFrontendUrl"].toString();

            if(debuggeeValue.isEmpty() || debuggerValue.isEmpty()) break;

            QUrl debuggee = QUrl(debuggeeValue);
            QUrl debugger = QUrl(addr + debuggerValue);

            if(url() == debuggee && !m_InspectorTable.values().contains(debugger)){
                m_InspectorTable[this] = debugger;
                break;
            }
        }
    });
}
#endif

void WebEngineView::OnIconChanged(const QIcon &icon){
    Application::RegisterIcon(url().host(), icon);
}

void WebEngineView::Copy(){
    if(page()) page()->triggerAction(QWebEnginePage::Copy);
}

void WebEngineView::Cut(){
    if(page()) page()->triggerAction(QWebEnginePage::Cut);
}

void WebEngineView::Paste(){
    if(page()) page()->triggerAction(QWebEnginePage::Paste);
}

void WebEngineView::Undo(){
    if(page()) page()->triggerAction(QWebEnginePage::Undo);
}

void WebEngineView::Redo(){
    if(page()) page()->triggerAction(QWebEnginePage::Redo);
}

void WebEngineView::SelectAll(){
    if(page()) page()->triggerAction(QWebEnginePage::SelectAll);
}

void WebEngineView::Unselect(){
    if(page()){
        page()->triggerAction(QWebEnginePage::Unselect);
        page()->runJavaScript(QStringLiteral(
            "(function(){\n"
            "    document.activeElement.blur();\n"
            "}());"));
    }
}

void WebEngineView::Reload(){
    if(page()) page()->triggerAction(QWebEnginePage::Reload);
}

void WebEngineView::ReloadAndBypassCache(){
    if(page()) page()->triggerAction(QWebEnginePage::ReloadAndBypassCache);
}

void WebEngineView::Stop(){
    if(page()) page()->triggerAction(QWebEnginePage::Stop);
}

void WebEngineView::StopAndUnselect(){
    Stop(); Unselect();
}

void WebEngineView::Print(){
    if(!page()) return;

    QString filename = ModalDialog::GetSaveFileName_
        (QString(), QString(),
         QStringLiteral("Pdf document (*.pdf);;Images (*.jpg *.jpeg *.gif *.png *.bmp *.xpm)"));

    if(filename.isEmpty()) return;

    if(filename.toLower().endsWith(QStringLiteral(".pdf"))){

        page()->printToPdf(filename);

    } else {

        QQuickWidget *widget = findChild<QQuickWidget*>();

        if(!widget) return;

        QSize origSize = size();
        QPointF origPos = page()->scrollPosition();
        resize(page()->contentsSize().toSize());

        QTimer::singleShot(700, this, [this, widget, filename, origSize, origPos](){

        widget->grabFramebuffer().save(filename);

        resize(origSize);
        page()->runJavaScript(SetScrollValuePointJsCode(origPos.toPoint()));

        });
    }
}

void WebEngineView::Save(){
    if(page()) page()->triggerAction(QWebEnginePage::SavePage);
}

void WebEngineView::ZoomIn(){
    float zoom = PrepareForZoomIn();
    setZoomFactor(static_cast<qreal>(zoom));
    emit statusBarMessage(tr("Zoom factor changed to %1 percent").arg(zoom*100.0));
}

void WebEngineView::ZoomOut(){
    float zoom = PrepareForZoomOut();
    setZoomFactor(static_cast<qreal>(zoom));
    emit statusBarMessage(tr("Zoom factor changed to %1 percent").arg(zoom*100.0));
}

void WebEngineView::ToggleMediaControls(){
    if(page() && page()->contextMenuData().isValid())
        page()->triggerAction(QWebEnginePage::ToggleMediaControls);
}

void WebEngineView::ToggleMediaLoop(){
    if(page() && page()->contextMenuData().isValid())
         page()->triggerAction(QWebEnginePage::ToggleMediaLoop);
}

void WebEngineView::ToggleMediaPlayPause(){
    if(page() && page()->contextMenuData().isValid())
        page()->triggerAction(QWebEnginePage::ToggleMediaPlayPause);
}

void WebEngineView::ToggleMediaMute(){
    if(page() && page()->contextMenuData().isValid())
        page()->triggerAction(QWebEnginePage::ToggleMediaMute);
}

void WebEngineView::ExitFullScreen(){
    if(page()) page()->triggerAction(QWebEnginePage::ExitFullScreen);
}

void WebEngineView::InspectElement(){
    if(!page()) return;
    if(!m_Inspector){
        m_Inspector = new QWebEngineView();
        m_Inspector->setAttribute(Qt::WA_DeleteOnClose, false);
#if QT_VERSION < 0x050B00
        m_Inspector->load(m_InspectorTable[this]);
#else
        page()->setDevToolsPage(m_Inspector->page());
#endif
    } else {
        m_Inspector->reload();
    }
    m_Inspector->show();
    m_Inspector->raise();
    //if(page()) page()->InspectElement();
}

void WebEngineView::AddSearchEngine(QPoint pos){
    if(page()) page()->AddSearchEngine(pos);
}

void WebEngineView::AddBookmarklet(QPoint pos){
    if(page()) page()->AddBookmarklet(pos);
}

void WebEngineView::timerEvent(QTimerEvent *ev){
    QWebEngineView::timerEvent(ev);
    if(ev->timerId() == m_ScrollSignalTimer){
        CallWithScroll([this](QPointF pos){ emit ScrollChanged(pos);});
        killTimer(m_ScrollSignalTimer);
        m_ScrollSignalTimer = 0;
    }
}

void WebEngineView::childEvent(QChildEvent *ev){
    QWebEngineView::childEvent(ev);
    if(ev->added() &&
       0 == strcmp(ev->child()->metaObject()->className(),
                   "QtWebEngineCore::RenderWidgetHostViewQtDelegateWidget")){
        ev->child()->installEventFilter(new EventEater(this, ev->child()));
    }
}

void WebEngineView::hideEvent(QHideEvent *ev){
    if(GetDisplayObscured()) ExitFullScreen();
    SaveViewState();
    QWebEngineView::hideEvent(ev);
}

void WebEngineView::showEvent(QShowEvent *ev){
    m_PreventScrollRestoration = false;
    QWebEngineView::showEvent(ev);
    RestoreViewState();
}

void WebEngineView::keyPressEvent(QKeyEvent *ev){
#if QT_VERSION >= 0x050900
    if(GetDisplayObscured()){
        if(ev->key() == Qt::Key_Escape || ev->key() == Qt::Key_F11){
            ExitFullScreen();
            ev->setAccepted(true);
            return;
        }
    }

#  ifdef PASSWORD_MANAGER
    if(Application::HasCtrlModifier(ev) && ev->key() == Qt::Key_Return){

        QString data = Application::GetAuthData
            (page()->profile()->storageName() +
             QStringLiteral(":") + url().host());

        if(!data.isEmpty()){
            m_PreventAuthRegistration = true;
            page()->runJavaScript
                (SubmitFormDataJsCode(data),
                 [this](QVariant){
                    m_PreventAuthRegistration = false;
                });
            ev->setAccepted(true);
            return;
        }
    }
#  endif //ifdef PASSWORD_MANAGER
#endif //if QT_VERSION >= 0x050900

    // all key events are ignored, if input method is activated.
    // so input method specific keys are accepted.

    // 'HasAnyModifier' ignores ShiftModifier.
    if(Application::HasAnyModifier(ev) ||
       Application::IsFunctionKey(ev)){
        ev->setAccepted(TriggerKeyEvent(ev));
        return;
    }

    if(!m_PreventScrollRestoration &&
       Application::IsMoveKey(ev)){
        m_PreventScrollRestoration = true;
    }

#if QT_VERSION < 0x050900
    QWebEngineView::keyPressEvent(ev);
#endif

    if(
#if QT_VERSION < 0x050900
       !ev->isAccepted() &&
#endif
       !Application::IsOnlyModifier(ev)){

        ev->setAccepted(TriggerKeyEvent(ev));
    }
}

void WebEngineView::keyReleaseEvent(QKeyEvent *ev){
    QWebEngineView::keyReleaseEvent(ev);
}

void WebEngineView::resizeEvent(QResizeEvent *ev){
    QWebEngineView::resizeEvent(ev);
}

void WebEngineView::contextMenuEvent(QContextMenuEvent *ev){
    SharedWebElement elem = m_ClickedElement;
    Page::MediaType type = Page::MediaTypeNone;
    QWebEngineContextMenuData data = page()->contextMenuData();
    if(data.isValid()){
        if(data.mediaType() == QWebEngineContextMenuData::MediaTypeVideo ||
           data.mediaType() == QWebEngineContextMenuData::MediaTypeAudio)
            type = Page::MediaTypePlayable;
        else if(data.mediaType() == QWebEngineContextMenuData::MediaTypeImage)
            type = Page::MediaTypeImage;
        if(!elem){
            std::shared_ptr<JsWebElement> e = std::make_shared<JsWebElement>();
            *e = JsWebElement(this, data.position(), data.linkUrl(), data.mediaUrl(), data.isContentEditable());
            elem = e;
        }
        m_SelectedText = data.selectedText();
    }
    page()->DisplayContextMenu(m_TreeBank, elem, ev->pos(), ev->globalPos(), type);
    GestureAborted();
    ev->setAccepted(true);
}

void WebEngineView::mouseMoveEvent(QMouseEvent *ev){
    if(!m_TreeBank) return;

    Application::SetCurrentWindow(m_TreeBank->GetMainWindow());

    if(m_DragStarted){
        QWebEngineView::mouseMoveEvent(ev);
        ev->setAccepted(true);
        return;
    }
    if(ev->buttons() & Qt::RightButton &&
       !m_GestureStartedPos.isNull()){

        GestureMoved(ev->pos());
        QString gesture = GestureToString(m_Gesture);
        QString action =
            !m_RightGestureMap.contains(gesture)
              ? tr("NoAction")
            : Page::IsValidAction(m_RightGestureMap[gesture])
              ? Action(Page::StringToAction(m_RightGestureMap[gesture]))->text()
            : m_RightGestureMap[gesture];
        emit statusBarMessage(gesture + QStringLiteral(" (") + action + QStringLiteral(")"));
        ev->setAccepted(false);
        return;
    }

    int scrollBarWidth = Application::style()->pixelMetric(QStyle::PM_ScrollBarExtent);
    bool horizontal = m_ScrollBarState == BothScrollBarEnabled
        ||            m_ScrollBarState == HorizontalScrollBarEnabled;
    bool vertical   = m_ScrollBarState == BothScrollBarEnabled
        ||            m_ScrollBarState == VerticalScrollBarEnabled;
    QRect touchableRect =
        QRect(QPoint(),
              size() - QSize(vertical   ? scrollBarWidth : 0,
                             horizontal ? scrollBarWidth : 0));

    if(ev->buttons() & Qt::LeftButton &&
       !m_GestureStartedPos.isNull() &&
       touchableRect.contains(m_GestureStartedPos) &&
       (m_ClickedElement &&
        !m_ClickedElement->IsNull() &&
        !m_ClickedElement->IsEditableElement())){

        if(QLineF(ev->pos(), m_GestureStartedPos).length() < 2){
            // gesture not aborted.
            QWebEngineView::mouseMoveEvent(ev);
            ev->setAccepted(false);
            return;
        }
        QDrag *drag = new QDrag(this);

        // clear or make directory if need.
        Application::ClearTemporaryDirectory();

        NetworkAccessManager *nam =
            static_cast<NetworkAccessManager*>(page()->networkAccessManager());

        QMimeData *mime = m_HadSelection
            ? CreateMimeDataFromSelection(nam)
            : CreateMimeDataFromElement(nam);

        if(!mime){
            drag->deleteLater();

            // call default behavior.
            GestureAborted();
            QWebEngineView::mouseMoveEvent(ev);
            ev->setAccepted(false);
            return;
        }

        QPixmap pixmap = m_HadSelection
            ? CreatePixmapFromSelection()
            : CreatePixmapFromElement();

        QRect rect = m_HadSelection
            ? m_SelectionRegion.boundingRect()
            : m_ClickedElement->Rectangle().intersected(QRect(QPoint(), size()));
        QPoint pos = ev->pos() - rect.topLeft();

        if(pixmap.width()  > MAX_DRAGGING_PIXMAP_WIDTH ||
           pixmap.height() > MAX_DRAGGING_PIXMAP_HEIGHT){

            pos /= qMax(static_cast<float>(pixmap.width()) /
                        static_cast<float>(MAX_DRAGGING_PIXMAP_WIDTH),
                        static_cast<float>(pixmap.height()) /
                        static_cast<float>(MAX_DRAGGING_PIXMAP_HEIGHT));
            pixmap = pixmap.scaled(MAX_DRAGGING_PIXMAP_WIDTH,
                                   MAX_DRAGGING_PIXMAP_HEIGHT,
                                   Qt::KeepAspectRatio,
                                   Qt::SmoothTransformation);
        }

        if(m_HadSelection){
            mime->setImageData(pixmap.toImage());
        } else {
            QPixmap element = m_ClickedElement->Pixmap();
            if(element.isNull())
                mime->setImageData(pixmap.toImage());
            else
                mime->setImageData(element.toImage());
        }
        if(m_EnableDragHackLocal){
            GestureMoved(ev->pos());
        } else {
            GestureAborted();
        }
        m_DragStarted = true;
        drag->setMimeData(mime);
        drag->setPixmap(pixmap);
        drag->setHotSpot(pos);
        drag->exec(Qt::CopyAction | Qt::MoveAction);
        drag->deleteLater();
        ev->setAccepted(true);
    } else {
        // call default behavior.
        GestureAborted();
        QWebEngineView::mouseMoveEvent(ev);
        ev->setAccepted(false);
    }
}

void WebEngineView::mousePressEvent(QMouseEvent *ev){
    QString mouse;

    Application::AddModifiersToString(mouse, ev->modifiers());
    Application::AddMouseButtonsToString(mouse, ev->buttons() & ~ev->button());
    Application::AddMouseButtonToString(mouse, ev->button());

    if(m_MouseMap.contains(mouse)){

        QString str = m_MouseMap[mouse];
        if(!str.isEmpty()){
            if(!View::TriggerAction(str, ev->pos())){
                ev->setAccepted(false);
                return;
            }
            GestureAborted();
            ev->setAccepted(true);
            return;
        }
    }

    GestureStarted(ev->pos());
    QWebEngineView::mousePressEvent(ev);
    ev->setAccepted(false);
}

void WebEngineView::mouseReleaseEvent(QMouseEvent *ev){
    emit statusBarMessage(QString());

    QUrl link = m_ClickedElement ? m_ClickedElement->LinkUrl() : QUrl();

    if(!link.isEmpty() &&
       m_Gesture.isEmpty() &&
       (ev->button() == Qt::LeftButton ||
        ev->button() == Qt::MidButton)){

        QNetworkRequest req(link);
        req.setRawHeader("Referer", url().toEncoded());

        if(Application::HasShiftModifier(ev) ||
           Application::HasCtrlModifier(ev) ||
           ev->button() == Qt::MidButton){

            GestureAborted();
            m_TreeBank->OpenInNewViewNode(req, Page::Activate(), GetViewNode());
            ev->setAccepted(true);
            return;

        } else if(
            // it's requirements of starting loadhack.
            // loadhack uses new hist node instead of same view's `load()'.
            m_EnableLoadHackLocal
            // url is not empty.
            && !url().isEmpty()
            // link doesn't hold jump command.
            && !link.toEncoded().contains("#")
            // m_ClickedElement doesn't hold javascript function.
            && !m_ClickedElement->IsJsCommandElement()){

            GestureAborted();
            m_TreeBank->OpenInNewHistNode(req, true, GetHistNode());
            ev->setAccepted(true);
            return;
        }
    }

    if(ev->button() == Qt::RightButton){

        if(!m_Gesture.isEmpty()){
            GestureFinished(ev->pos(), ev->button());
        } else if(!m_GestureStartedPos.isNull()){
            // transfer event to contextMenuEvent.
            ev->setAccepted(false);
            return;
        }
        ev->setAccepted(true);
        return;
    }

#if QT_VERSION >= 0x050900
    // since Qt5.9, mouseReleaseEvent is called when dropping.
    if(ev->button() == Qt::LeftButton && !m_Gesture.isEmpty())
        ; // do nothing.
    else
#endif
        GestureAborted();

    QWebEngineView::mouseReleaseEvent(ev);
    ev->setAccepted(false);
}

void WebEngineView::mouseDoubleClickEvent(QMouseEvent *ev){
    QWebEngineView::mouseDoubleClickEvent(ev);
    ev->setAccepted(false);
}

void WebEngineView::dragEnterEvent(QDragEnterEvent *ev){
    m_DragStarted = true;
    ev->setDropAction(Qt::MoveAction);
    ev->acceptProposedAction();
    QWebEngineView::dragEnterEvent(ev);
    ev->setAccepted(true);
}

void WebEngineView::dragMoveEvent(QDragMoveEvent *ev){
    if(m_EnableDragHackLocal && !m_GestureStartedPos.isNull()){

        GestureMoved(ev->pos());
        QString gesture = GestureToString(m_Gesture);
        QString action =
            !m_LeftGestureMap.contains(gesture)
              ? tr("NoAction")
            : Page::IsValidAction(m_LeftGestureMap[gesture])
              ? Action(Page::StringToAction(m_LeftGestureMap[gesture]))->text()
            : m_LeftGestureMap[gesture];
        emit statusBarMessage(gesture + QStringLiteral(" (") + action + QStringLiteral(")"));
    }
    QWebEngineView::dragMoveEvent(ev);
    ev->setAccepted(true);
}

void WebEngineView::dropEvent(QDropEvent *ev){
    emit statusBarMessage(QString());
    bool isLocal = false;
    QPoint pos = ev->pos();
    QObject *source = ev->source();
    QString text = ev->mimeData()->text();
    QList<QUrl> urls = Page::MimeDataToUrls(ev->mimeData(), source);

    foreach(QUrl u, urls){ if(u.isLocalFile()) isLocal = true;}

    if(!text.isEmpty()){
        text.replace(QStringLiteral("\""), QStringLiteral("\\\""));
    } else if(!urls.isEmpty()){
        foreach(QUrl u, urls){
            if(text.isEmpty()) text = u.toString();
            else text += QStringLiteral("\n") + u.toString();
        }
    }

    CallWithHitElement(pos, [this, pos, source, text, urls](SharedWebElement elem){

    if(elem && !elem->IsNull() && (elem->IsEditableElement() || elem->IsTextInputElement())){

        GestureAborted();
        elem->SetText(text);
        return;
    }

    if(!m_Gesture.isEmpty() && source == this){
        GestureFinished(pos, Qt::LeftButton);
        return;
    }

    GestureAborted();

    if(!urls.isEmpty() && source != this){
        m_TreeBank->OpenInNewViewNode(urls, true, GetViewNode());
    }

    });

#if defined(Q_OS_MAC)
    // do nothing.
#else
    if(isLocal ||
       (DragToStartDownload() && !urls.isEmpty() && source == this))
        ; // do nothing.
    else
        QWebEngineView::dropEvent(ev);
#endif

    ev->setAccepted(true);
}

void WebEngineView::dragLeaveEvent(QDragLeaveEvent *ev){
    ev->setAccepted(false);
    m_DragStarted = false;
    QWebEngineView::dragLeaveEvent(ev);
}

void WebEngineView::wheelEvent(QWheelEvent *ev){
    // wheel event is called twice on Qt5.7 or newer.
    // senders are EventEater and QWebEngineView.
    m_PreventScrollRestoration = true;
    ev->setAccepted(false);
}

void WebEngineView::focusInEvent(QFocusEvent *ev){
    QWebEngineView::focusInEvent(ev);
    OnFocusIn();
}

void WebEngineView::focusOutEvent(QFocusEvent *ev){
    QWebEngineView::focusOutEvent(ev);
    OnFocusOut();
}

bool WebEngineView::focusNextPrevChild(bool next){
    if(!m_Switching && visible())
        return QWebEngineView::focusNextPrevChild(next);
    return false;
}

#if defined(Q_OS_WIN)
bool WebEngineView::nativeEvent(const QByteArray &eventType, void *message, long *result){
    bool ret = QWebEngineView::nativeEvent(eventType, message, result);
    if(TreeBank::PurgeView() && eventType == "windows_generic_MSG"){
        if(static_cast<MSG*>(message)->message == WM_WINDOWPOSCHANGED){
            MainWindow *win;
            if(m_TreeBank) win = m_TreeBank->GetMainWindow();
            if(!m_TreeBank) return ret;
            if(win) win->RaiseAllEdgeWidgets();
            if(m_TreeBank->GetNotifier()) m_TreeBank->GetNotifier()->raise();
            if(m_TreeBank->GetReceiver()) m_TreeBank->GetReceiver()->raise();
        }
    }
    return ret;
}
#endif

void WebEngineView::CallWithGotBaseUrl(UrlCallBack callBack){
    if(!page() || url().isEmpty() || url() == BLANK_URL)
        return callBack(QUrl());

    page()->runJavaScript
        (GetBaseUrlJsCode(), [callBack](QVariant var){
            callBack(var.isValid() ? var.toUrl() : QUrl());
        });
}

void WebEngineView::CallWithGotCurrentBaseUrl(UrlCallBack callBack){
    if(!page() || url().isEmpty() || url() == BLANK_URL)
        return callBack(QUrl());

    page()->runJavaScript
        (GetCurrentBaseUrlJsCode(), [callBack](QVariant var){
            callBack(var.isValid() ? var.toUrl() : QUrl());
        });
}

void WebEngineView::CallWithFoundElements(Page::FindElementsOption option,
                                          WebElementListCallBack callBack){
    if(!page() || url().isEmpty() || url() == BLANK_URL)
        return callBack(SharedWebElementList());

    page()->runJavaScript
        (FindElementsJsCode(option), [this, callBack](QVariant var){
            if(!var.isValid()) return callBack(SharedWebElementList());
            QVariantList list = var.toMap().values();
            SharedWebElementList result;

            MainWindow *win = Application::GetCurrentWindow();
            QSize s =
                m_TreeBank ? m_TreeBank->size() :
                win ? win->GetTreeBank()->size() :
                !size().isEmpty() ? size() :
                DEFAULT_WINDOW_SIZE;
            QRect viewport = QRect(QPoint(), s);

            for(int i = 0; i < list.length(); i++){
                std::shared_ptr<JsWebElement> e = std::make_shared<JsWebElement>();
                *e = JsWebElement(this, list[i]);
                if(!viewport.intersects(e->Rectangle()))
                    e->SetRectangle(QRect());
                result << e;
            }
            callBack(result);
        });
}

void WebEngineView::CallWithHitElement(const QPoint &pos, WebElementCallBack callBack){
    if(!page() || url().isEmpty() || url() == BLANK_URL || pos.isNull())
        return callBack(SharedWebElement());

    page()->runJavaScript
        (HitElementJsCode(pos/zoomFactor()), [this, callBack](QVariant var){
            if(!var.isValid()) return callBack(SharedWebElement());
            std::shared_ptr<JsWebElement> e = std::make_shared<JsWebElement>();
            *e = JsWebElement(this, var);
            callBack(e);
        });
}

void WebEngineView::CallWithHitLinkUrl(const QPoint &pos, UrlCallBack callBack){
    if(!page() || url().isEmpty() || url() == BLANK_URL || pos.isNull())
        return callBack(QUrl());

    page()->runJavaScript
        (HitLinkUrlJsCode(pos/zoomFactor()), [callBack](QVariant var){
            callBack(var.isValid() ? var.toUrl() : QUrl());
        });
}

void WebEngineView::CallWithHitImageUrl(const QPoint &pos, UrlCallBack callBack){
    if(!page() || url().isEmpty() || url() == BLANK_URL || pos.isNull())
        return callBack(QUrl());

    page()->runJavaScript
        (HitImageUrlJsCode(pos/zoomFactor()), [callBack](QVariant var){
            callBack(var.isValid() ? var.toUrl() : QUrl());
        });
}

void WebEngineView::CallWithSelectedText(StringCallBack callBack){
    if(page()) callBack(page()->selectedText());
}

void WebEngineView::CallWithSelectedHtml(StringCallBack callBack){
    if(!page() || url().isEmpty() || url() == BLANK_URL)
        return callBack(QString());

    page()->runJavaScript
        (SelectedHtmlJsCode(), [callBack](QVariant var){
            callBack(var.isValid() ? var.toString() : QString());
        });
}

void WebEngineView::CallWithWholeText(StringCallBack callBack){
    if(page()) page()->toPlainText(callBack);
}

void WebEngineView::CallWithWholeHtml(StringCallBack callBack){
    if(page()) page()->toHtml(callBack);
}

void WebEngineView::CallWithSelectionRegion(RegionCallBack callBack){
    if(!page() || !hasSelection()) return callBack(QRegion());
    QRect viewport = QRect(QPoint(), size());
    page()->runJavaScript
        (SelectionRegionJsCode(), [viewport, callBack](QVariant var){
            if(!var.isValid() || !var.canConvert(QMetaType::QVariantMap))
                return callBack(QRegion());
            QRegion region;
            QVariantMap map = var.toMap();
            foreach(QString key, map.keys()){
                QVariantMap m = map[key].toMap();
                region |= QRect(m["x"].toInt(),
                                m["y"].toInt(),
                                m["width"].toInt(),
                                m["height"].toInt()).intersected(viewport);
            }
            callBack(region);
        });
}

void WebEngineView::CallWithEvaluatedJavaScriptResult(const QString &code,
                                                      VariantCallBack callBack){
    if(!page() || url().isEmpty() || url() == BLANK_URL)
        return callBack(QVariant());

    page()->runJavaScript(code, callBack);
}

#endif //ifdef WEBENGINEVIEW

repository: rallentando/vanilla

repo_name: rallentando/vanilla

extension: cpp


text:
package common

import (
	"bufio"
	"errors"
	"fmt"
	"os"
	"path/filepath"
	"regexp"
	"sort"
	"strconv"
	"strings"

	"github.com/manifoldco/promptui"
	"github.com/mitchellh/go-homedir"
)

// ListProfilesFromAWSConfig parses default aws config file (~/.aws/config) and returns
// all profiles found in that file.
func ListProfilesFromAWSConfig() []string {
	var profiles []string

	homeDir, err := homedir.Dir()
	if err != nil {
		panic(err.Error())
	}

	var awsConfigFilePath = filepath.Join(homeDir, ".aws", "config")

	file, err := os.Open(awsConfigFilePath)
	if err != nil {
		panic(err.Error())
	}

	defer file.Close()

	reg := regexp.MustCompile(`^\[profile `)

	scanner := bufio.NewScanner(file)
	for scanner.Scan() {
		if t := reg.MatchString(scanner.Text()); t == true {
			s := strings.TrimSuffix(reg.ReplaceAllString(scanner.Text(), "${1}"), "]")
			profiles = append(profiles, s)
		}
	}

	if err := scanner.Err(); err != nil {
		panic(err.Error())
	}

	sort.Strings(profiles)
	return profiles
}

// SelectProfile prompts to select one AWS Profile from given profile list.
func SelectProfile(profiles []string) string {
	templates := &promptui.SelectTemplates{
		Label:    "{{ . }}?",
		Active:   "{{ . | cyan }}",
		Inactive: "{{ . | faint }}",
		Details: `
--------- Current profile ----------
{{ "Name:" | faint }}	{{ . }}`,
	}

	searcher := func(input string, index int) bool {
		return strings.Contains(strings.ToLower(profiles[index]), strings.ToLower(input))
	}

	prompt := promptui.Select{
		Label:     "AWS Profiles",
		Items:     profiles,
		Templates: templates,
		Size:      4,
		Searcher:  searcher,
	}

	i, _, err := prompt.Run()

	if err != nil {
		fmt.Printf("Prompt failed %v\n", err)
		return ""
	}

	return profiles[i]

}

// SelectBucket prompts to select one bucket from given bucket list.
func SelectBucket(buckets []string) string {
	templates := &promptui.SelectTemplates{
		Active:   `{{ . | cyan | bold }}`,
		Inactive: `{{ . | faint }}`,
		Details: `
--------- Current Bucket ----------
{{ "Name:" | faint }}	{{ . }}`,
	}

	searcher := func(input string, index int) bool {
		return strings.Contains(strings.ToLower(buckets[index]), strings.ToLower(input))
	}

	prompt := promptui.Select{
		Label:        "Buckets: " + strconv.Itoa(len(buckets)),
		Items:        buckets,
		Templates:    templates,
		Size:         15,
		Searcher:     searcher,
		HideSelected: true,
	}

	i, _, err := prompt.Run()

	if err != nil {
		fmt.Printf("Prompt failed %v\n", err)
		return ""
	}

	return buckets[i]

}

// ExitWithError exits with an error status and print current error message
func ExitWithError(msg string, args ...interface{}) {
	fmt.Fprintf(os.Stderr, msg+"\n", args...)
	os.Exit(1)
}

// ConfirmDeletion prompts user to confirm or not deletion
func ConfirmDeletion() bool {
	validate := func(input string) error {
		if len(input) == 0 || !(strings.EqualFold(strings.ToLower(input), "y") || strings.EqualFold(strings.ToLower(input), "n")) {
			return errors.New("Valid values are Y or N")
		}

		return nil
	}
	prompt := promptui.Prompt{
		Validate: validate,
		Label:    "Do you want to continue? [y/N]",
		Default:  "N",
	}
	result, err := prompt.Run()
	if err != nil {
		fmt.Printf("Prompt failed %v\n", err)
		return false
	}

	return strings.EqualFold(strings.ToLower(result), "y")
}

license_type: permissive

branch_name: refs/heads/master

extension: go


text:
# generated from genmsg/cmake/pkg-genmsg.cmake.em

message(STATUS "robot_pose_ekf: 0 messages, 1 services")

set(MSG_I_FLAGS "-Istd_msgs:/opt/ros/indigo/share/std_msgs/cmake/../msg")

# Find all generators
find_package(gencpp REQUIRED)
find_package(genlisp REQUIRED)
find_package(genpy REQUIRED)

add_custom_target(robot_pose_ekf_generate_messages ALL)

# verify that message/service dependencies have not changed since configure

get_filename_component(_filename "/home/ubuntu/catkin_ws/src/navigation/robot_pose_ekf/srv/GetStatus.srv" NAME_WE)
add_custom_target(_robot_pose_ekf_generate_messages_check_deps_${_filename}
  COMMAND ${CATKIN_ENV} ${PYTHON_EXECUTABLE} ${GENMSG_CHECK_DEPS_SCRIPT} "robot_pose_ekf" "/home/ubuntu/catkin_ws/src/navigation/robot_pose_ekf/srv/GetStatus.srv" ""
)

#
#  langs = gencpp;genlisp;genpy
#

### Section generating for lang: gencpp
### Generating Messages

### Generating Services
_generate_srv_cpp(robot_pose_ekf
  "/home/ubuntu/catkin_ws/src/navigation/robot_pose_ekf/srv/GetStatus.srv"
  "${MSG_I_FLAGS}"
  ""
  ${CATKIN_DEVEL_PREFIX}/${gencpp_INSTALL_DIR}/robot_pose_ekf
)

### Generating Module File
_generate_module_cpp(robot_pose_ekf
  ${CATKIN_DEVEL_PREFIX}/${gencpp_INSTALL_DIR}/robot_pose_ekf
  "${ALL_GEN_OUTPUT_FILES_cpp}"
)

add_custom_target(robot_pose_ekf_generate_messages_cpp
  DEPENDS ${ALL_GEN_OUTPUT_FILES_cpp}
)
add_dependencies(robot_pose_ekf_generate_messages robot_pose_ekf_generate_messages_cpp)

# add dependencies to all check dependencies targets
get_filename_component(_filename "/home/ubuntu/catkin_ws/src/navigation/robot_pose_ekf/srv/GetStatus.srv" NAME_WE)
add_dependencies(robot_pose_ekf_generate_messages_cpp _robot_pose_ekf_generate_messages_check_deps_${_filename})

# target for backward compatibility
add_custom_target(robot_pose_ekf_gencpp)
add_dependencies(robot_pose_ekf_gencpp robot_pose_ekf_generate_messages_cpp)

# register target for catkin_package(EXPORTED_TARGETS)
list(APPEND ${PROJECT_NAME}_EXPORTED_TARGETS robot_pose_ekf_generate_messages_cpp)

### Section generating for lang: genlisp
### Generating Messages

### Generating Services
_generate_srv_lisp(robot_pose_ekf
  "/home/ubuntu/catkin_ws/src/navigation/robot_pose_ekf/srv/GetStatus.srv"
  "${MSG_I_FLAGS}"
  ""
  ${CATKIN_DEVEL_PREFIX}/${genlisp_INSTALL_DIR}/robot_pose_ekf
)

### Generating Module File
_generate_module_lisp(robot_pose_ekf
  ${CATKIN_DEVEL_PREFIX}/${genlisp_INSTALL_DIR}/robot_pose_ekf
  "${ALL_GEN_OUTPUT_FILES_lisp}"
)

add_custom_target(robot_pose_ekf_generate_messages_lisp
  DEPENDS ${ALL_GEN_OUTPUT_FILES_lisp}
)
add_dependencies(robot_pose_ekf_generate_messages robot_pose_ekf_generate_messages_lisp)

# add dependencies to all check dependencies targets
get_filename_component(_filename "/home/ubuntu/catkin_ws/src/navigation/robot_pose_ekf/srv/GetStatus.srv" NAME_WE)
add_dependencies(robot_pose_ekf_generate_messages_lisp _robot_pose_ekf_generate_messages_check_deps_${_filename})

# target for backward compatibility
add_custom_target(robot_pose_ekf_genlisp)
add_dependencies(robot_pose_ekf_genlisp robot_pose_ekf_generate_messages_lisp)

# register target for catkin_package(EXPORTED_TARGETS)
list(APPEND ${PROJECT_NAME}_EXPORTED_TARGETS robot_pose_ekf_generate_messages_lisp)

### Section generating for lang: genpy
### Generating Messages

### Generating Services
_generate_srv_py(robot_pose_ekf
  "/home/ubuntu/catkin_ws/src/navigation/robot_pose_ekf/srv/GetStatus.srv"
  "${MSG_I_FLAGS}"
  ""
  ${CATKIN_DEVEL_PREFIX}/${genpy_INSTALL_DIR}/robot_pose_ekf
)

### Generating Module File
_generate_module_py(robot_pose_ekf
  ${CATKIN_DEVEL_PREFIX}/${genpy_INSTALL_DIR}/robot_pose_ekf
  "${ALL_GEN_OUTPUT_FILES_py}"
)

add_custom_target(robot_pose_ekf_generate_messages_py
  DEPENDS ${ALL_GEN_OUTPUT_FILES_py}
)
add_dependencies(robot_pose_ekf_generate_messages robot_pose_ekf_generate_messages_py)

# add dependencies to all check dependencies targets
get_filename_component(_filename "/home/ubuntu/catkin_ws/src/navigation/robot_pose_ekf/srv/GetStatus.srv" NAME_WE)
add_dependencies(robot_pose_ekf_generate_messages_py _robot_pose_ekf_generate_messages_check_deps_${_filename})

# target for backward compatibility
add_custom_target(robot_pose_ekf_genpy)
add_dependencies(robot_pose_ekf_genpy robot_pose_ekf_generate_messages_py)

# register target for catkin_package(EXPORTED_TARGETS)
list(APPEND ${PROJECT_NAME}_EXPORTED_TARGETS robot_pose_ekf_generate_messages_py)

if(gencpp_INSTALL_DIR AND EXISTS ${CATKIN_DEVEL_PREFIX}/${gencpp_INSTALL_DIR}/robot_pose_ekf)
  # install generated code
  install(
    DIRECTORY ${CATKIN_DEVEL_PREFIX}/${gencpp_INSTALL_DIR}/robot_pose_ekf
    DESTINATION ${gencpp_INSTALL_DIR}
  )
endif()
add_dependencies(robot_pose_ekf_generate_messages_cpp std_msgs_generate_messages_cpp)

if(genlisp_INSTALL_DIR AND EXISTS ${CATKIN_DEVEL_PREFIX}/${genlisp_INSTALL_DIR}/robot_pose_ekf)
  # install generated code
  install(
    DIRECTORY ${CATKIN_DEVEL_PREFIX}/${genlisp_INSTALL_DIR}/robot_pose_ekf
    DESTINATION ${genlisp_INSTALL_DIR}
  )
endif()
add_dependencies(robot_pose_ekf_generate_messages_lisp std_msgs_generate_messages_lisp)

if(genpy_INSTALL_DIR AND EXISTS ${CATKIN_DEVEL_PREFIX}/${genpy_INSTALL_DIR}/robot_pose_ekf)
  install(CODE "execute_process(COMMAND \"/usr/bin/python\" -m compileall \"${CATKIN_DEVEL_PREFIX}/${genpy_INSTALL_DIR}/robot_pose_ekf\")")
  # install generated code
  install(
    DIRECTORY ${CATKIN_DEVEL_PREFIX}/${genpy_INSTALL_DIR}/robot_pose_ekf
    DESTINATION ${genpy_INSTALL_DIR}
  )
endif()
add_dependencies(robot_pose_ekf_generate_messages_py std_msgs_generate_messages_py)

license: MIT

extension: cmake


text:
SUMMARY = "Inventory config for openpower-vpd-parser"
PR = "r1"
LICENSE = "Apache-2.0"
LIC_FILES_CHKSUM = "file://${COREBASE}/meta/files/common-licenses/Apache-2.0;md5=89aea4e17d99a7cacdbeed46a0096b10"

inherit openpower-fru-vpd
inherit mrw-xml
inherit native

DEPENDS += " \
           mrw-native \
           mrw-perl-tools-native \
           virtual/openpower-fru-vpd-layout \
           "

PROVIDES += "virtual/openpower-fru-inventory"

S = "${WORKDIR}"

do_install() {
        DEST=${D}${inventory_datadir_native}
        install -d ${DEST}

        ${bindir}/perl-native/perl \
            ${bindir}/gen_openpower_fru.pl \
            -m ${mrw_datadir}/${MRW_XML} \
            -c ${vpdlayout_datadir}/layout.yaml \
            -o ${DEST}/inventory
}

repository: openbmc/openbmc

repo_name: openbmc/openbmc

gha_license_id: NOASSERTION

gha_language: Python

extension: bb


text:
package client

import (
	"encoding/json"
	"net/http"
	"sync"
	"time"

	"github.com/labstack/echo/v4/middleware"

	"github.com/team836/clowd-storage/internal/module/operationq"
	"github.com/team836/clowd-storage/internal/module/spool"

	"github.com/team836/clowd-storage/pkg/database"

	"github.com/team836/clowd-storage/internal/model"

	"github.com/team836/clowd-storage/pkg/errcorr"

	"github.com/team836/clowd-storage/pkg/logger"

	"github.com/labstack/echo/v4"
)

const (
	uploadLimit = "100M"
)

type fileOnClient struct {
	Name  string `json:"name"`
	Order int    `json:"order"`
	Data  string `json:"data"` // base64 encoded
}

type fileView struct {
	Name       string    `json:"name"`
	Size       uint      `json:"size"`
	UploadedAt time.Time `json:"uploadedAt"`
}

type fileToDown struct {
	Name string `json:"name"`
}

type fileToDelete struct {
	fileToDown
}

func RegisterHandlers(group *echo.Group) {
	group.GET("/dir", fileListController)
	group.POST("/files", uploadController, middleware.BodyLimit(uploadLimit))
	group.GET("/files", downloadController)
	group.DELETE("/files", deleteController)
}

/**
File upload requested by client(clowdee).

- Get uploaded file.
- Run Reed-Solomon algorithm to each files.
- Check all nodes' status by ping and pong.
- By all nodes' status, run the node selection.
- Schedule saving for every shards.
- Update the selected nodes' status by prediction.
- Finally save the files to the nodes.
*/
func uploadController(ctx echo.Context) error {
	clowdee := ctx.Get("clowdee").(*model.Clowdee)

	// bind uploaded data into array of `fileOnClient` struct
	files := make([]*fileOnClient, 0)
	if err := ctx.Bind(&files); err != nil {
		logger.File().Infof("Error binding client's uploaded file, %s", err)
		return err
	}

	// create upload queue
	uq := operationq.NewUQ()

	// encode every file data using reed solomon algorithm
	// and push to upload queue
	for _, file := range files {
		// encode the file data
		shards, size, err := errcorr.Encode(file.Data)
		if err != nil {
			logger.File().Infof("Error encoding the file, %s", err)
			return ctx.String(http.StatusNotAcceptable, "Cannot handle this file: "+file.Name)
		}

		encFile := &model.EncFile{
			Model: &model.File{
				GoogleID: clowdee.GoogleID,
				Name:     file.Name,
				Position: int16(file.Order),
				Size:     size,
			},
			Data: shards,
		}

		// if the file is already exists
		if !database.Conn().NewRecord(encFile.Model) {
			logger.File().Infof("The file is already exists")
			return ctx.String(http.StatusNotAcceptable, `"`+encFile.Model.Name+`" is already exists`)
		}

		// push to upload queue
		uq.Push(encFile)
	}

	// this area almost change all nodes' status
	// so, protect it using mutex for all node's status
	spool.Pool().NodesStatusLock.Lock()
	defer func() {
		// when panic is occurred, unlock the nodes status lock
		if r := recover(); r != nil {
			spool.Pool().NodesStatusLock.Unlock()
		}
	}()

	// check all nodes' status by ping&pong
	spool.Pool().CheckAllNodes()

	// node selection
	safeRing, unsafeRing := spool.Pool().SelectNodes()
	if safeRing.Len()+unsafeRing.Len() == 0 {
		spool.Pool().NodesStatusLock.Unlock()
		logger.File().Errorf("Available nodes are not exist.")
		return ctx.String(http.StatusNotAcceptable, "Cannot save the files because currently there are no available nodes")
	}

	// schedule saving for every shards to the nodes
	// and get results
	quotas, err := uq.Schedule(safeRing, unsafeRing)
	if err != nil {
		spool.Pool().NodesStatusLock.Unlock()
		logger.File().Errorf("Error scheduling upload, %s", err)

		if err == operationq.ErrLackOfStorage {
			return ctx.String(http.StatusNotAcceptable, err.Error())
		}

		return ctx.NoContent(http.StatusInternalServerError)
	}

	// save each quota using goroutine
	for nodeToSave, shards := range quotas {
		go func(a *spool.ActiveNode, s []*model.ShardToSave) {
			a.Save <- s
		}(nodeToSave, shards)
	}

	// end of mutex area for nodes status lock
	spool.Pool().NodesStatusLock.Unlock()

	return ctx.NoContent(http.StatusCreated)
}

/**
Get clowdee's all uploaded file list.
*/
func fileListController(ctx echo.Context) error {
	clowdee := ctx.Get("clowdee").(*model.Clowdee)

	fileList := make([]*fileView, 0)

	// find from database
	sqlResult := database.Conn().
		Table("files").
		Select("name, sum(size) as size, min(uploaded_at) as uploaded_at").
		Where("google_id = ?", clowdee.GoogleID).
		Group("name").
		Scan(&fileList)

	// sql error occurred
	if sqlResult.Error != nil && !sqlResult.RecordNotFound() {
		logger.File().Errorf("Error finding the node's file list in database, %s", sqlResult.Error.Error())
		return ctx.NoContent(http.StatusInternalServerError)
	}

	return ctx.JSON(http.StatusOK, &fileList)
}

/**
File download requested by client(clowdee).
*/
func downloadController(ctx echo.Context) error {
	clowdee := ctx.Get("clowdee").(*model.Clowdee)

	// bind download list from header
	downloadList := make([]*fileToDown, 0)
	if err := json.Unmarshal([]byte(ctx.Request().Header.Get("files")), &downloadList); err != nil {
		logger.File().Infof("Error binding client's download list, %s", err)
		return ctx.String(http.StatusNotAcceptable, "Invalid request format")
	}

	dq := operationq.NewDQ()

	// read download list and add them to download queue
	for _, file := range downloadList {
		if err := dq.Push(clowdee.GoogleID, file.Name); err != nil {
			if err == operationq.ErrFileNotExist {
				return ctx.String(http.StatusNotFound, err.Error()+": "+file.Name)
			}

			return ctx.NoContent(http.StatusInternalServerError)
		}
	}

	// schedule every shards for download to the each active nodes
	// and get quotas for each nodes
	quotas := dq.Schedule()

	// concurrently download each quota using goroutine
	var downloadWG sync.WaitGroup
	for machineID, shards := range quotas {
		// if the machine is active
		if activeNode := spool.Pool().FindActiveNode(machineID); activeNode != nil {
			downloadWG.Add(1)

			// start new worker for download
			go func(a *spool.ActiveNode, s []*model.ShardToLoad, wg *sync.WaitGroup) {
				a.Load <- &spool.LoadChan{Shards: s, WG: wg}
			}(activeNode, shards, &downloadWG)
		}
	}

	// wait for all download workers are done
	downloadWG.Wait()

	response := make([]*fileOnClient, 0)
	reconstructedShards := make([]*model.ShardToLoad, 0)

	// make response data
	for _, file := range dq.Files {
		var shards [][]byte
		var missedShards []*model.ShardToLoad

		// merge all shard data
		// if the shard is invalid, make to nil for reconstruction
		for _, loadedShard := range file.Shards {
			// if shard is missing or corrupted, make to nil data
			if len(loadedShard.Data) == 0 ||
				errcorr.IsCorruptedChecksum(loadedShard.Data, loadedShard.Model.Checksum) {
				loadedShard.Data = nil
			}

			// if shard data is missed, add to missed list
			if loadedShard.Data == nil {
				missedShards = append(missedShards, loadedShard)
			}

			shards = append(shards, loadedShard.Data)
		}

		// reconstruct the original file from the shards
		fileData, reconstructedShardData, err := errcorr.Decode(shards, int(file.Model.Size))
		if err != nil {
			logger.File().Infof("Error decoding the shards, %s", err)
			return ctx.String(http.StatusInternalServerError, "file download error")
		}

		// insert reconstructed data to the missed list
		for idx, missedShard := range missedShards {
			missedShard.Data = reconstructedShardData[idx]
		}

		// merge to all missed list
		reconstructedShards = append(reconstructedShards, missedShards...)

		response = append(
			response,
			&fileOnClient{
				Name:  file.Model.Name,
				Order: int(file.Model.Position),
				Data:  fileData,
			},
		)
	}

	go restoreShards(reconstructedShards)

	return ctx.JSON(http.StatusOK, &response)
}

/**
Restore(re-upload) the reconstruct shards to the another nodes.
*/
func restoreShards(reconstructedShards []*model.ShardToLoad) {
	// there are not exists shards to restore
	if len(reconstructedShards) == 0 {
		return
	}

	rq := operationq.NewRQ()
	rq.Push(reconstructedShards...)

	spool.Pool().NodesStatusLock.Lock()
	defer spool.Pool().NodesStatusLock.Unlock()

	spool.Pool().CheckAllNodes()

	// node selection
	safeRing, unsafeRing := spool.Pool().SelectNodes()
	if safeRing.Len()+unsafeRing.Len() == 0 {
		logger.File().Errorf("Available nodes are not exist.")
		return
	}

	// schedule restoring for every shards to the nodes
	// and get results
	quotas, err := rq.Schedule(safeRing, unsafeRing)
	if err != nil {
		logger.File().Errorf("Error scheduling restoring, %s", err)
		return
	}

	// save each quota using goroutine
	for nodeToSave, restoreShards := range quotas {
		go func(a *spool.ActiveNode, s []*model.ShardToSave) {
			a.Save <- s
		}(nodeToSave, restoreShards)
	}
}

/**
Controller for file deletion request.
*/
func deleteController(ctx echo.Context) error {
	clowdee := ctx.Get("clowdee").(*model.Clowdee)

	// bind deletion list from the request body
	files := make([]*fileToDelete, 0)
	if err := ctx.Bind(&files); err != nil {
		logger.File().Infof("Error binding client's delete list, %s", err)
		return err
	}

	// make file name list
	nameList := make([]string, 0)
	for _, file := range files {
		nameList = append(nameList, file.Name)
	}

	delQ := operationq.NewDelQ()

	// add deletion list to delete queue
	if err := delQ.Push(clowdee.GoogleID, nameList...); err != nil {
		if err != operationq.ErrFileNotExist {
			return ctx.NoContent(http.StatusInternalServerError)
		}
	}

	// schedule every shards for deletion to the each active nodes
	// and get quotas for each nodes
	quotas := delQ.Schedule()

	// delete quotas concurrently
	for machineID, shards := range quotas {
		// if the machine is active
		if activeNode := spool.Pool().FindActiveNode(machineID); activeNode != nil {
			// delete shards on the node concurrently
			go func(a *spool.ActiveNode, s []*model.ShardToDelete) {
				a.Delete <- s
			}(activeNode, shards)
		} else { // if the machine is not active (cannot delete currently)
			// record to database for later deletion
			for _, shard := range shards {
				database.Conn().
					Create(&model.DeletedShard{Name: shard.Name, MachineID: machineID})
			}
		}
	}

	return ctx.NoContent(http.StatusNoContent)
}

gha_license_id: MIT

gha_language: Go


text:
@inproceedings{E12-3001,
 address = {Avignon, France},
 author = {Guillou, Liane},
 booktitle = {Proceedings of the Student Research Workshop at the 13th Conference of the European Chapter of the Association for Computational Linguistics},
 month = {April},
 pages = {1--10},
 publisher = {Association for Computational Linguistics},
 title = {Improving Pronoun Translation for Statistical Machine Translation},
 year = {2012}
}

@inproceedings{E12-3002,
 address = {Avignon, France},
 author = {Petrenz, Philipp},
 booktitle = {Proceedings of the Student Research Workshop at the 13th Conference of the European Chapter of the Association for Computational Linguistics},
 month = {April},
 pages = {11--21},
 publisher = {Association for Computational Linguistics},
 title = {Cross-Lingual Genre Classification},
 year = {2012}
}

@inproceedings{E12-3003,
 address = {Avignon, France},
 author = {Papangelis, Alexandros},
 booktitle = {Proceedings of the Student Research Workshop at the 13th Conference of the European Chapter of the Association for Computational Linguistics},
 month = {April},
 pages = {22--31},
 publisher = {Association for Computational Linguistics},
 title = {A Comparative Study of Reinforcement Learning Techniques on Dialogue Management},
 year = {2012}
}

@inproceedings{E12-3004,
 address = {Avignon, France},
 author = {Hlaing, Tin Htay},
 booktitle = {Proceedings of the Student Research Workshop at the 13th Conference of the European Chapter of the Association for Computational Linguistics},
 month = {April},
 pages = {32--37},
 publisher = {Association for Computational Linguistics},
 title = {Manually constructed context-free grammar for Myanmar syllable structure},
 year = {2012}
}

@inproceedings{E12-3005,
 address = {Avignon, France},
 author = {Mih\v{a}il\v{a}, Claudiu  and  Batista-Navarro, Riza Theresa},
 booktitle = {Proceedings of the Student Research Workshop at the 13th Conference of the European Chapter of the Association for Computational Linguistics},
 month = {April},
 pages = {38--45},
 publisher = {Association for Computational Linguistics},
 title = {What's in a Name? Entity Type Variation across Two Biomedical Subdomains},
 year = {2012}
}

@inproceedings{E12-3006,
 address = {Avignon, France},
 author = {Majli\v{s}, Martin},
 booktitle = {Proceedings of the Student Research Workshop at the 13th Conference of the European Chapter of the Association for Computational Linguistics},
 month = {April},
 pages = {46--54},
 publisher = {Association for Computational Linguistics},
 title = {Yet Another Language Identifier},
 year = {2012}
}

@inproceedings{E12-3007,
 address = {Avignon, France},
 author = {Cocco, Christelle},
 booktitle = {Proceedings of the Student Research Workshop at the 13th Conference of the European Chapter of the Association for Computational Linguistics},
 month = {April},
 pages = {55--63},
 publisher = {Association for Computational Linguistics},
 title = {Discourse Type Clustering using POS n-gram Profiles and High-Dimensional Embeddings},
 year = {2012}
}

@inproceedings{E12-3008,
 address = {Avignon, France},
 author = {Botha, Jan A.},
 booktitle = {Proceedings of the Student Research Workshop at the 13th Conference of the European Chapter of the Association for Computational Linguistics},
 month = {April},
 pages = {64--73},
 publisher = {Association for Computational Linguistics},
 title = {Hierarchical Bayesian Language Modelling for the Linguistically Informed},
 year = {2012}
}

@inproceedings{E12-3009,
 address = {Avignon, France},
 author = {Wawer, Aleksander},
 booktitle = {Proceedings of the Student Research Workshop at the 13th Conference of the European Chapter of the Association for Computational Linguistics},
 month = {April},
 pages = {74--80},
 publisher = {Association for Computational Linguistics},
 title = {Mining Co-Occurrence Matrices for SO-PMI Paradigm Word Candidates},
 year = {2012}
}

@inproceedings{E12-3010,
 address = {Avignon, France},
 author = {Russo, Lorenza  and  Lo\'{a}iciga, Sharid  and  Gulati, Asheesh},
 booktitle = {Proceedings of the Student Research Workshop at the 13th Conference of the European Chapter of the Association for Computational Linguistics},
 month = {April},
 pages = {81--89},
 publisher = {Association for Computational Linguistics},
 title = {Improving machine translation of null subjects in Italian and Spanish},
 year = {2012}
}

extension: bib


text:
package secondly

import (
	"encoding/json"
	"testing"
)

type testConf struct {
	AppName  string           `json:"app_name"`
	Version  float32          `json:"version"`
	Database testDatabaseConf `json:"database"`
}

type testDatabaseConf struct {
	Adapter  string `json:"adapter"`
	Host     string `json:"host"`
	Port     int    `json:"port"`
	Username string `json:"username"`
	Password string `json:"password"`
}

const (
	goodJSON = `{"app_name": "Secondly", "version": 1}`
	badJSON  = `{"app_name": "noooo...`
)

func TestIsStructPtr(t *testing.T) {
	if ok := isStructPtr(1); ok {
		t.Error("Integer recognized as a struct pointer")
	}
	if ok := isStructPtr(testConf{}); ok {
		t.Error("Struct instance recognized as a struct pointer")
	}
	if ok := isStructPtr(&testConf{}); !ok {
		t.Error("Struct pointer was not recognized")
	}
}

func TestUnmarshal(t *testing.T) {
	conf := testConf{}
	var i interface{} = &conf

	if err := json.Unmarshal([]byte(badJSON), i); err == nil {
		t.Error("Expected error")
	}

	if err := json.Unmarshal([]byte(goodJSON), i); err != nil {
		t.Error("Unexpected error")
	}
	if conf.AppName != "Secondly" {
		t.Errorf("Expected Foo to equal %q, got %q", "Secondly", conf.AppName)
	}
	if conf.Version != 1 {
		t.Errorf("Expected Bar to equal %q, got %q", 1, conf.Version)
	}
}

func TestDuplicate(t *testing.T) {
	var i interface{} = &testConf{}

	dupe := duplicate(i)
	if _, ok := dupe.(*testConf); !ok {
		t.Error("Duplication failed")
	}
}

repository: localhots/secondly

repo_name: localhots/secondly


text:
// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.

package v1beta1

import (
	mattermostv1alpha1 "github.com/mattermost/mattermost-operator/apis/mattermost/v1alpha1"
	"github.com/mattermost/mattermost-operator/pkg/utils"
)

// FileStore utils

// SetDefaults sets the missing values in FileStore to the default ones.
func (fs *FileStore) SetDefaults() {
	if fs.isAnyExceptOperatorManaged() {
		return
	}

	fs.ensureDefault()
	fs.OperatorManaged.SetDefaults()
}

// IsExternal returns true if the MinIO/S3 instance is external.
func (fs *FileStore) IsExternal() bool {
	return fs.External != nil && fs.External.URL != ""
}

// IsExternalVolume returns true if the filestore requested is an externally
// managed volume.
func (fs *FileStore) IsExternalVolume() bool {
	return fs.ExternalVolume != nil && fs.ExternalVolume.VolumeClaimName != ""
}

// IsLocal returns true if the filestore requested is local (PVC backed).
func (fs *FileStore) IsLocal() bool {
	return fs.Local != nil && fs.Local.Enabled
}

// isAnyExceptOperatorManaged checks if any filestore types are configurated
// except the operator managed type. This is generally used to see if defaults
// should be applied.
func (fs *FileStore) isAnyExceptOperatorManaged() bool {
	return fs.IsExternal() || fs.IsExternalVolume() || fs.IsLocal()
}

func (fs *FileStore) ensureDefault() {
	if fs.OperatorManaged == nil {
		fs.OperatorManaged = &OperatorManagedMinio{}
	}
}

// SetDefaults sets the missing values in OperatorManagedMinio to the default ones.
func (omm *OperatorManagedMinio) SetDefaults() {
	if omm.StorageSize == "" {
		omm.StorageSize = DefaultFilestoreStorageSize
	}
}

func (fs *FileStore) SetDefaultReplicasAndResources() {
	if fs.isAnyExceptOperatorManaged() {
		return
	}
	fs.ensureDefault()
	fs.OperatorManaged.SetDefaultReplicasAndResources()
}

func (omm *OperatorManagedMinio) SetDefaultReplicasAndResources() {
	if omm.Replicas == nil {
		omm.Replicas = &mattermostv1alpha1.DefaultSize.Minio.Replicas
	}
	if omm.Resources.Size() == 0 {
		omm.Resources = mattermostv1alpha1.DefaultSize.Minio.Resources
	}
}

func (fs *FileStore) OverrideReplicasAndResourcesFromSize(size mattermostv1alpha1.ClusterInstallationSize) {
	if fs.isAnyExceptOperatorManaged() {
		return
	}
	fs.ensureDefault()
	fs.OperatorManaged.OverrideReplicasAndResourcesFromSize(size)
}

func (omm *OperatorManagedMinio) OverrideReplicasAndResourcesFromSize(size mattermostv1alpha1.ClusterInstallationSize) {
	omm.Replicas = utils.NewInt32(size.Minio.Replicas)
	omm.Resources = size.Minio.Resources
}

repository: mattermost/mattermost-operator

repo_name: mattermost/mattermost-operator


text:
package main

import (
	"encoding/json"
	"errors"
	"fmt"
	"io"
	"os"
	"strings"

	"github.com/containers/image/v5/pkg/cli"
	"github.com/containers/image/v5/signature"
	"github.com/spf13/cobra"
)

type standaloneSignOptions struct {
	output         string // Output file path
	passphraseFile string // Path pointing to a passphrase file when signing
}

func standaloneSignCmd() *cobra.Command {
	opts := standaloneSignOptions{}
	cmd := &cobra.Command{
		Use:   "standalone-sign [command options] MANIFEST DOCKER-REFERENCE KEY-FINGERPRINT --output|-o SIGNATURE",
		Short: "Create a signature using local files",
		RunE:  commandAction(opts.run),
	}
	adjustUsage(cmd)
	flags := cmd.Flags()
	flags.StringVarP(&opts.output, "output", "o", "", "output the signature to `SIGNATURE`")
	flags.StringVarP(&opts.passphraseFile, "passphrase-file", "", "", "file that contains a passphrase for the --sign-by key")
	return cmd
}

func (opts *standaloneSignOptions) run(args []string, stdout io.Writer) error {
	if len(args) != 3 || opts.output == "" {
		return errors.New("Usage: skopeo standalone-sign manifest docker-reference key-fingerprint -o signature")
	}
	manifestPath := args[0]
	dockerReference := args[1]
	fingerprint := args[2]

	manifest, err := os.ReadFile(manifestPath)
	if err != nil {
		return fmt.Errorf("Error reading %s: %w", manifestPath, err)
	}

	mech, err := signature.NewGPGSigningMechanism()
	if err != nil {
		return fmt.Errorf("Error initializing GPG: %w", err)
	}
	defer mech.Close()

	passphrase, err := cli.ReadPassphraseFile(opts.passphraseFile)
	if err != nil {
		return err
	}

	signature, err := signature.SignDockerManifestWithOptions(manifest, dockerReference, mech, fingerprint, &signature.SignOptions{Passphrase: passphrase})
	if err != nil {
		return fmt.Errorf("Error creating signature: %w", err)
	}

	if err := os.WriteFile(opts.output, signature, 0644); err != nil {
		return fmt.Errorf("Error writing signature to %s: %w", opts.output, err)
	}
	return nil
}

type standaloneVerifyOptions struct {
	publicKeyFile string
}

func standaloneVerifyCmd() *cobra.Command {
	opts := standaloneVerifyOptions{}
	cmd := &cobra.Command{
		Use:   "standalone-verify MANIFEST DOCKER-REFERENCE KEY-FINGERPRINTS SIGNATURE",
		Short: "Verify a signature using local files",
		Long: `Verify a signature using local files

KEY-FINGERPRINTS can be a comma separated list of fingerprints, or "any" if you trust all the keys in the public key file.`,
		RunE: commandAction(opts.run),
	}
	flags := cmd.Flags()
	flags.StringVar(&opts.publicKeyFile, "public-key-file", "", `File containing public keys. If not specified, will use local GPG keys.`)
	adjustUsage(cmd)
	return cmd
}

func (opts *standaloneVerifyOptions) run(args []string, stdout io.Writer) error {
	if len(args) != 4 {
		return errors.New("Usage: skopeo standalone-verify manifest docker-reference key-fingerprint signature")
	}
	manifestPath := args[0]
	expectedDockerReference := args[1]
	expectedFingerprints := strings.Split(args[2], ",")
	signaturePath := args[3]

	if opts.publicKeyFile == "" && len(expectedFingerprints) == 1 && expectedFingerprints[0] == "any" {
		return fmt.Errorf("Cannot use any fingerprint without a public key file")
	}
	unverifiedManifest, err := os.ReadFile(manifestPath)
	if err != nil {
		return fmt.Errorf("Error reading manifest from %s: %w", manifestPath, err)
	}
	unverifiedSignature, err := os.ReadFile(signaturePath)
	if err != nil {
		return fmt.Errorf("Error reading signature from %s: %w", signaturePath, err)
	}

	var mech signature.SigningMechanism
	var publicKeyfingerprints []string
	if opts.publicKeyFile != "" {
		publicKeys, err := os.ReadFile(opts.publicKeyFile)
		if err != nil {
			return fmt.Errorf("Error reading public keys from %s: %w", opts.publicKeyFile, err)
		}
		mech, publicKeyfingerprints, err = signature.NewEphemeralGPGSigningMechanism(publicKeys)
		if err != nil {
			return fmt.Errorf("Error initializing GPG: %w", err)

		}
	} else {
		mech, err = signature.NewGPGSigningMechanism()
		if err != nil {
			return fmt.Errorf("Error initializing GPG: %w", err)
		}
	}
	defer mech.Close()

	if len(expectedFingerprints) == 1 && expectedFingerprints[0] == "any" {
		expectedFingerprints = publicKeyfingerprints
	}

	sig, verificationFingerprint, err := signature.VerifyImageManifestSignatureUsingKeyIdentityList(unverifiedSignature, unverifiedManifest, expectedDockerReference, mech, expectedFingerprints)
	if err != nil {
		return fmt.Errorf("Error verifying signature: %w", err)
	}

	fmt.Fprintf(stdout, "Signature verified using fingerprint %s, digest %s\n", verificationFingerprint, sig.DockerManifestDigest)
	return nil
}

// WARNING: Do not use the contents of this for ANY security decisions,
// and be VERY CAREFUL about showing this information to humans in any way which suggest that these values “are probably” reliable.
// There is NO REASON to expect the values to be correct, or not intentionally misleading
// (including things like “✅ Verified by $authority”)
//
// The subcommand is undocumented, and it may be renamed or entirely disappear in the future.
type untrustedSignatureDumpOptions struct {
}

func untrustedSignatureDumpCmd() *cobra.Command {
	opts := untrustedSignatureDumpOptions{}
	cmd := &cobra.Command{
		Use:    "untrusted-signature-dump-without-verification SIGNATURE",
		Short:  "Dump contents of a signature WITHOUT VERIFYING IT",
		RunE:   commandAction(opts.run),
		Hidden: true,
	}
	adjustUsage(cmd)
	return cmd
}

func (opts *untrustedSignatureDumpOptions) run(args []string, stdout io.Writer) error {
	if len(args) != 1 {
		return errors.New("Usage: skopeo untrusted-signature-dump-without-verification signature")
	}
	untrustedSignaturePath := args[0]

	untrustedSignature, err := os.ReadFile(untrustedSignaturePath)
	if err != nil {
		return fmt.Errorf("Error reading untrusted signature from %s: %w", untrustedSignaturePath, err)
	}

	untrustedInfo, err := signature.GetUntrustedSignatureInformationWithoutVerifying(untrustedSignature)
	if err != nil {
		return fmt.Errorf("Error decoding untrusted signature: %v", err)
	}
	untrustedOut, err := json.MarshalIndent(untrustedInfo, "", "    ")
	if err != nil {
		return err
	}
	fmt.Fprintln(stdout, string(untrustedOut))
	return nil
}

repository: containers/skopeo

repo_name: containers/skopeo

branch_name: refs/heads/main


text:
package parser

import (
	"fmt"
	"math/rand"
	"regexp"
	"strings"

	"github.com/arr-ai/frozen"
)

type escape struct {
	openDelim  *regexp.Regexp
	closeDelim *regexp.Regexp
	external   ExternalRef
}

type Scope struct {
	m frozen.Map[string, any]
}

func (s Scope) String() string {
	return s.m.String()
}

func (s Scope) Keys() frozen.Set[string] {
	return s.m.Keys()
}

func (s Scope) With(ident string, v any) Scope {
	return Scope{m: s.m.With(ident, v)}
}

func (s Scope) Has(ident string) bool {
	return s.m.Has(ident)
}

func (s Scope) Merge(t Scope) Scope {
	return Scope{m: s.m.Update(t.m)}
}

type scopeBuilder struct {
	mb frozen.MapBuilder[string, any]
}

func (b *scopeBuilder) Put(ident string, v any) {
	b.mb.Put(ident, v)
}

func (b *scopeBuilder) Finish() Scope {
	return Scope{m: b.mb.Finish()}
}

type scopeVal struct {
	p   Parser
	val TreeElement
}

func (s Scope) WithVal(ident string, p Parser, val TreeElement) Scope {
	if ident != "" {
		s.m = s.m.With(ident, &scopeVal{p: p, val: val})
	}
	return s
}

func (s Scope) GetVal(ident string) (Parser, TreeElement, bool) {
	if val, ok := s.m.Get(ident); ok {
		sv := val.(*scopeVal)
		return sv.p, sv.val, ok
	}
	return nil, nil, false
}

const cutpointkey = ".Cutpoint-key."

type Cutpointdata int32

func (c Cutpointdata) valid() bool { return c >= 0 }

const invalidCutpoint = Cutpointdata(-1)

func (s Scope) ReplaceCutPoint(force bool) (newScope Scope, prev, replacement Cutpointdata) {
	prev = s.GetCutPoint()
	replacement = invalidCutpoint
	if prev.valid() || force {
		// TODO: What's with the random number?
		replacement = Cutpointdata(rand.Int31()) //nolint:gosec
		return s.With(cutpointkey, replacement), prev, replacement
	}
	return s, invalidCutpoint, invalidCutpoint
}

func (s Scope) GetCutPoint() Cutpointdata {
	return s.m.GetElse(cutpointkey, invalidCutpoint).(Cutpointdata)
}

const externalsKey = ".Externals-key."
const parseEscapeKey = ".ParseEscape-key."

func (s Scope) WithExternals(extRefs ExternalRefs) Scope {
	var e *escape
	var sb scopeBuilder
	for name, external := range extRefs {
		if strings.HasPrefix(name, "*") {
			if e != nil {
				panic(fmt.Errorf("too many escapes"))
			}
			openClose := strings.Split(name[1:], "()")
			e = &escape{
				openDelim:  regexp.MustCompile(`(?m)\A` + openClose[0]),
				closeDelim: regexp.MustCompile(`(?m)\A` + openClose[1]),
				external:   external,
			}
			sb.Put(parseEscapeKey, e)
		}
	}
	sb.Put(externalsKey, extRefs)
	return s.Merge(sb.Finish())
}

func (s Scope) GetExternal(ident string) ExternalRef {
	if e, has := s.m.GetElse(externalsKey, ExternalRefs{}).(ExternalRefs)[ident]; has {
		return e
	}
	return nil
}

func (s Scope) getParserEscape() *escape {
	if e, has := s.m.Get(parseEscapeKey); has {
		return e.(*escape)
	}
	return nil
}

type call struct {
	ident string
	term  Term
	next  *call
}

func (c *call) Error() string {
	var parts []string
	for ; c != nil; c = c.next {
		parts = append(parts, fmt.Sprintf("%+v", *c))
	}
	return strings.Join(parts, "\n")
}

func (c *call) push(ident string, t Term) *call {
	return &call{ident, t, c}
}

repository: arr-ai/wbnf

repo_name: arr-ai/wbnf


text:
SUMMARY = "Pygments theme using JupyterLab CSS variables"
LICENSE = "BSD-3-Clause"
LIC_FILES_CHKSUM = "file://LICENSE;md5=20a40995a0b2f0ae1f2a70d2dc995bbf"

SRC_URI[sha256sum] = "7405d7fde60819d905a9fa8ce89e4cd830e318cdad22a0030f7a901da705585d"
PYPI_PACKAGE = "jupyterlab_pygments"

inherit pypi setuptools3

DEPENDS += " \
    ${PYTHON_PN}-jupyter-packaging-native \
    "

RDEPENDS:${PN} += " \
    ${PYTHON_PN}-pygments \
    "

FILES:${PN} += " \
    ${datadir}/jupyter/labextensions/jupyterlab_pygments/install.json \
    ${datadir}/jupyter/labextensions/jupyterlab_pygments/package.json \
    ${datadir}/jupyter/labextensions/jupyterlab_pygments/static/568.1e2faa2ba0bbe59c4780.js \
    ${datadir}/jupyter/labextensions/jupyterlab_pygments/static/747.8eb3ddccc7ec4987bff9.js \
    ${datadir}/jupyter/labextensions/jupyterlab_pygments/static/remoteEntry.aa1060b2d1221f8e5688.js \
    ${datadir}/jupyter/labextensions/jupyterlab_pygments/static/style.js \
    ${datadir}/jupyter/labextensions/jupyterlab_pygments/static/third-party-licenses.json \
    "

repository: Xilinx/meta-jupyter

repo_name: Xilinx/meta-jupyter

gha_language: BitBake