Example #1
0
void TApplicationServer::incomingConnection(int socketDescriptor)
{
    T_TRACEFUNC("socketDescriptor: %d", socketDescriptor);
 
    switch ( Tf::app()->multiProcessingModule() ) {
    case TWebApplication::Thread:
        for (;;) {
            if (actionContextCount() < maxServers) {
                TActionThread *thread = new TActionThread(socketDescriptor);
                connect(thread, SIGNAL(finished()), this, SLOT(deleteActionContext()));
                insertPointer(thread);
                thread->start();
                break;
            }
            Tf::msleep(1);
            qApp->processEvents(QEventLoop::ExcludeSocketNotifiers);
        }
        break;

    case TWebApplication::Prefork: {
        close();  // Closes the listening port
        TActionForkProcess *process = new TActionForkProcess(socketDescriptor);
        connect(process, SIGNAL(finished()), this, SLOT(deleteActionContext()));
        insertPointer(process);
        process->start();
        break; }

    default:
        break;
    }
}
Example #2
0
void TApplicationServer::deleteActionContext()
{
    T_TRACEFUNC();
    QMutexLocker locker(&setMutex);
    actionContexts.remove(reinterpret_cast<TActionThread *>(sender()));
    sender()->deleteLater();
}
/*!
  \~english
  Returns the rendering data of the partial template given by \a templateName.

  \~japanese
  部分テンプレート \a templateName に変数 \a vars を設定した描画データを返す
*/
QString TActionController::getRenderingData(const QString &templateName, const QVariantHash &vars)
{
    T_TRACEFUNC("templateName: %s", qPrintable(templateName));

    // Creates view-object
    QStringList names = templateName.split("/");
    if (names.count() != 2) {
        tError("Invalid patameter: %s", qPrintable(templateName));
        return QString();
    }

    TDispatcher<TActionView> viewDispatcher(viewClassName(names[0], names[1]));
    TActionView *view = viewDispatcher.object();
    if (!view) {
        return QString();
    }

    QVariantHash hash = allVariants();
    for (QHashIterator<QString, QVariant> i(vars); i.hasNext(); ) {
        i.next();
        hash.insert(i.key(), i.value()); // item's value of same key is replaced
    }

    view->setController(this);
    view->setVariantHash(hash);
    return view->toString();  
}
void TSmtpMailer::sendAndDeleteLater()
{
    T_TRACEFUNC("");
    send();
    mailMessage.clear();
    deleteLater();
}
TSendmailMailer::~TSendmailMailer()
{
    T_TRACEFUNC("");
    if (!mailMessage.isEmpty()) {
        tSystemWarn("Mail not sent. Deleted it.");
    }
}
void TSmtpMailer::sendLater(const TMailMessage &message)
{
    T_TRACEFUNC("");

    mailMessage = message;
    QTimer::singleShot(0, this, SLOT(sendAndDeleteLater()));
}
void TSendmailMailer::sendLater(const TMailMessage &message)
{
    T_TRACEFUNC("");

    mailMessage = message;
    QMetaObject::invokeMethod(this, "sendAndDeleteLater", Qt::QueuedConnection);
}
/*!
  Creates and returns a TSessionStore object that matches the given key,
  or returns 0 if no matching session store is found.
*/
TSessionStore *TSessionStoreFactory::create(const QString &key)
{
    T_TRACEFUNC("key: %s", qPrintable(key));

    static const QString COOKIE_KEY = TSessionCookieStore().key().toLower();
    static const QString SQLOBJECT_KEY = TSessionSqlObjectStore().key().toLower();
    static const QString FILE_KEY = TSessionFileStore().key().toLower();
    static const QString REDIS_KEY = TSessionRedisStore().key().toLower();

    QMutexLocker locker(&mutex);

    loadPlugins();
    TSessionStore *ret = 0;

    QString k = key.toLower();
    if (k == COOKIE_KEY) {
        ret = new TSessionCookieStore;
    } else if (k == SQLOBJECT_KEY) {
        ret = new TSessionSqlObjectStore;
    } else if (k == FILE_KEY) {
        ret = new TSessionFileStore;
    } else if (k == REDIS_KEY) {
        ret = new TSessionRedisStore;
    } else {
        TSessionStoreInterface *ssif = sessIfMap->value(k);
        if (ssif) {
            ret = ssif->create(key);
        }
    }

    return ret;
}
/*!
  Returns a QUrl to \a action of \a controller with arguments \a args.
  The current controller name is used, if the \a controller is a empty string.
  The current action name is used, if the \a action is a empty string.
  If \a query is not empty, sets the query string to an encoded version
  of \a query. 
 */
QUrl TActionHelper::url(const QString &controller, const QString &action,
                        const QStringList &args,
                        const QVariantMap &query) const
{
    T_TRACEFUNC("%s : %s", qPrintable(controller), qPrintable(action));
    Q_ASSERT(this->controller());
    QString path;
    QString ctrl = (controller.isEmpty()) ? this->controller()->name() : controller;
    QString act = (action.isEmpty()) ? this->controller()->activeAction() : action;
    path.append('/').append(ctrl).append('/').append(act);
    
    for (QStringListIterator i(args); i.hasNext(); ) {
        path.append('/').append(THttpUtility::toUrlEncoding(i.next()));
    }

    // appends query items
    QString querystr;
    for (QMapIterator<QString, QVariant> it(query); it.hasNext(); ) {
        it.next();
        if (!it.key().isEmpty()) {
            querystr += it.key();
            querystr += QLatin1Char('=');
            querystr += it.value().toString();
            querystr += QLatin1Char('&');
        }
    }
    querystr.chop(1);

    if (!querystr.isEmpty()) {
        path += QLatin1Char('?');
        path += querystr;
    }
    return QUrl(path);
}
bool TSendmailMailer::send(const TMailMessage &message)
{
    T_TRACEFUNC("");

    mailMessage = message;
    bool res = send();
    mailMessage.clear();
    return res;
}
Example #11
0
bool TApplicationServer::open()
{
    T_TRACEFUNC();

    if (!isListening()) {
        quint16 port = Tf::app()->treefrogSettings().value("ListenPort").toUInt();
        if (!nativeListen(QHostAddress::Any, port)) {
            tSystemError("listen failed.  port:%d", port);
            return false;
        } else {
            tSystemDebug("listen successfully.  port:%d", port);
        }
    }

    // Loads libraries
    if (!libLoaded) {

        // Sets work directory
        QString libPath = Tf::app()->libPath();
        if (QDir(libPath).exists()) {
            // To resolve the symbols in the app libraries
            QDir::setCurrent(libPath);
        } else {
            tSystemError("lib directory not found");
            return false;
        }
        
        QStringList filter;
#if defined(Q_OS_WIN)
        filter << "controller.dll" << "view.dll";
#elif defined(Q_OS_DARWIN)
        filter << "libcontroller.dylib" << "libview.dylib";
#elif defined(Q_OS_UNIX)
        filter << "libcontroller.so" << "libview.so";
#else
        filter << "libcontroller.*" << "libview.*";
#endif

        QDir controllerDir(".");
        QStringList list = controllerDir.entryList(filter, QDir::Files);
        for (QStringListIterator i(list); i.hasNext(); ) {
            QString path = controllerDir.absoluteFilePath(i.next());
            QLibrary lib(path);
            if (lib.load()) {
                tSystemDebug("Library loaded: %s", qPrintable(path));
                libLoaded = true;
            } else {
                tSystemDebug("%s", qPrintable(lib.errorString()));
            }
        }
    }

    TUrlRoute::initialize();
    TSqlDatabasePool::initialize();
    return true;
}
TKvsDatabase &TActionContext::getKvsDatabase(TKvsDatabase::Type type)
{
    T_TRACEFUNC("type:%d", (int)type);

    TKvsDatabase &db = kvsDatabases[(int)type];
    if (!db.isValid()) {
        db = TKvsDatabasePool2::instance()->database(type);
    }
    return db;
}
qint64 TActionContext::writeResponse(int statusCode, THttpResponseHeader &header, const QByteArray &contentType, QIODevice *body, qint64 length)
{
    T_TRACEFUNC("statusCode:%d  contentType:%s  length:%s", statusCode, contentType.data(), qPrintable(QString::number(length)));

    header.setStatusLine(statusCode, THttpUtility::getResponseReasonPhrase(statusCode));
    if (!contentType.isEmpty())
        header.setContentType(contentType);

    return writeResponse(header, body, length);
}
qint64 TActionContext::writeResponse(THttpResponseHeader &header, QIODevice *body, qint64 length)
{
    T_TRACEFUNC("length:%s", qPrintable(QString::number(length)));

    header.setContentLength(length);
    header.setRawHeader("Server", "TreeFrog server");
    header.setCurrentDate();

    // Write data
    return writeResponse(header, body);
}
TSmtpMailer::~TSmtpMailer()
{
    T_TRACEFUNC("");
    if (!mailMessage.isEmpty()) {
//        tSystemWarn("Mail not sent. Deleted it.");
    }

    if (pop) {
        delete pop;
    }
    delete socket;
}
bool TApplicationServerBase::loadLibraries()
{
    T_TRACEFUNC("");

    // Loads libraries
    if (libsLoaded.isEmpty()) {
        // Sets work directory
        QString libPath = Tf::app()->libPath();
        if (QDir(libPath).exists()) {
            // To resolve the symbols in the app libraries
            QDir::setCurrent(libPath);
        } else {
            tSystemError("lib directory not found");
            return false;
        }

        loadedTimestamp = latestLibraryTimestamp();

#if defined(Q_OS_WIN)
        QStringList libs = { "controller", "view" };
#elif defined(Q_OS_LINUX)
        QStringList libs = { "libcontroller.so", "libview.so" };
#elif defined(Q_OS_DARWIN)
        QStringList libs = { "libcontroller.dylib", "libview.dylib" };
#else
        QStringList libs = { "libcontroller.so", "libview.so" };
#endif

        for (const auto &libname : libs) {
            auto lib = new QLibrary(libname);
            if (lib->load()) {
                tSystemDebug("Library loaded: %s", qPrintable(lib->fileName()));
                libsLoaded << lib;
            } else {
                tSystemWarn("%s", qPrintable(lib->errorString()));
            }
        }

        QStringList controllers = TActionController::availableControllers();
        tSystemDebug("Available controllers: %s", qPrintable(controllers.join(" ")));
    }
    QDir::setCurrent(Tf::app()->webRootPath());

    TSystemBus::instantiate();
    TPublisher::instantiate();
    TUrlRoute::instantiate();
    TSqlDatabasePool::instantiate();
    TKvsDatabasePool::instantiate();
    return true;
}
Example #17
0
qint64 TActionContext::writeResponse(THttpResponseHeader& header, QIODevice *body, qint64 length)
{
    T_TRACEFUNC("length:%s", qPrintable(QString::number(length)));
    qint64 res = -1;
    if (httpSocket) {
        header.setContentLength(length);
        header.setRawHeader("Server", "TreeFrog server");
        header.setRawHeader("Date", QLocale::c().toString(QDateTime::currentDateTime().toUTC(),
                                                          QLatin1String("ddd, dd MMM yyyy hh:mm:ss 'GMT'")).toLatin1());
        header.setRawHeader("Connection", "close");
        res = httpSocket->write(static_cast<THttpHeader*>(&header), body);
    }
    return res;
}
QSqlDatabase &TActionContext::getDatabase(int id)
{
    T_TRACEFUNC("id:%d", id);

    if (id < 0 || id >= Tf::app()->databaseSettingsCount())
        return sqlDatabases[Tf::app()->databaseSettingsCount()];  // invalid db
    
    QSqlDatabase &db = sqlDatabases[id];
    if (!db.isValid()) {
        db = TSqlDatabasePool::instance()->pop(id);
        beginTransaction(db);
    }
    return db;
}
THttpSocket::THttpSocket(QObject *parent)
    : QTcpSocket(parent), lengthToRead(-1)
{
    T_TRACEFUNC("");

    do {
        sid = point.fetch_add(1);
    } while (!socketManager[sid].compareExchange(nullptr, this)); // store a socket
    tSystemDebug("THttpSocket  sid:%d", sid);

    connect(this, SIGNAL(readyRead()), this, SLOT(readRequest()));
    connect(this, SIGNAL(requestWrite(const QByteArray&)), this, SLOT(writeRawData(const QByteArray&)), Qt::QueuedConnection);

    idleElapsed = std::time(nullptr);
}
qint64 TActionContext::writeResponse(THttpResponseHeader &header, QIODevice *body, qint64 length)
{
    T_TRACEFUNC("length:%s", qPrintable(QString::number(length)));

    header.setContentLength(length);
    header.setRawHeader("Server", "TreeFrog server");
# if QT_VERSION >= 0x040700
    QDateTime utc = QDateTime::currentDateTimeUtc();
#else
    QDateTime utc = QDateTime::currentDateTime().toUTC();
#endif
    header.setRawHeader("Date", QLocale(QLocale::C).toString(utc, QLatin1String("ddd, dd MMM yyyy hh:mm:ss 'GMT'")).toLatin1());

    // Write data
    return writeResponse(header, body);
}
Example #21
0
TKvsDatabase &TDatabaseContext::getKvsDatabase(TKvsDatabase::Type type)
{
    T_TRACEFUNC("type:%d", (int)type);

    TKvsDatabase &db = kvsDatabases[(int)type];
    if (!db.isValid()) {
        db = TKvsDatabasePool::instance()->database(type);
    }

    if (db.driver()) {
        db.driver()->moveToThread(QThread::currentThread());
    }

    idleElapsed = (uint)std::time(nullptr);
    return db;
}
/*!
  \~english
  Renders the template of the action \a action with the layout \a layout.

  \~japanese
  レイアウト \a layout を適用し、アクション \a action のテンプレートを描画する
 */
bool TActionController::render(const QString &action, const QString &layout)
{
    T_TRACEFUNC("");

    if (rendered) {
        tWarn("Has rendered already: %s", qPrintable(className() + '#' + activeAction()));
        return false;
    }
    rendered = true;

    // Creates view-object and displays it
    TDispatcher<TActionView> viewDispatcher(viewClassName(action));
    setLayout(layout);
    response.setBody(renderView(viewDispatcher.object()));
    return !response.isBodyNull();
}
bool TSessionManager::store(TSession &session)
{
    T_TRACEFUNC("");

    if (session.id().isEmpty()) {
        tSystemError("Internal Error  [%s:%d]", __FILE__, __LINE__); 
        return false;
    }
    
    bool res = false;
    TSessionStore *store = TSessionStoreFactory::create(storeType());
    if (store) {
        res = store->store(session);
        delete store;
    }
    return res;
}
TSession TSessionManager::findSession(const QByteArray &id)
{
    T_TRACEFUNC("");

    QDateTime now = QDateTime::currentDateTime();
    QDateTime validCreated = (sessionLifeTime() > 0) ? now.addSecs(-sessionLifeTime()) : now.addYears(-20);
    
    TSession session;
    if (!id.isEmpty()) {
        TSessionStore *store = TSessionStoreFactory::create(storeType());
        if (store) {
            session = store->find(id, validCreated);
            delete store;
        }
    }
    return session;
}
/*!
  \~english
  Renders the text \a text with the layout \a layout.

  \~japanese
  レイアウト \a layout を適用し、テキストを描画する
*/
bool TActionController::renderText(const QString &text, bool layoutEnable, const QString &layout)
{
    T_TRACEFUNC("");

    if (rendered) {
        tWarn("Has rendered already: %s", qPrintable(className() + '#' + activeAction()));
        return false;
    }
    rendered = true;

    // Creates TTextView object and displays it
    setLayout(layout);
    setLayoutEnabled(layoutEnable);
    TTextView *view = new TTextView(text);
    response.setBody(renderView(view));
    delete view;
    return (!response.isBodyNull());
}
QSqlDatabase &TActionContext::getSqlDatabase(int id)
{
    T_TRACEFUNC("id:%d", id);

    if (!Tf::app()->isSqlDatabaseAvailable()) {
        return sqlDatabases[0];  // invalid database
    }

    if (id < 0 || id >= Tf::app()->sqlDatabaseSettingsCount()) {
        throw RuntimeException("error database id", __FILE__, __LINE__);
    }

    QSqlDatabase &db = sqlDatabases[id];
    if (!db.isValid()) {
        db = TSqlDatabasePool2::instance()->database(id);
        beginTransaction(db);
    }
    return db;
}
Example #27
0
QList<THttpRequest> THttpSocket::read()
{
    T_TRACEFUNC("");

    QList<THttpRequest> reqList;

    if (canReadRequest()) {
        if (fileBuffer.isOpen()) {
            fileBuffer.close();
            THttpRequest req(readBuffer, fileBuffer.fileName(), peerAddress());
            reqList << req;
        } else {
            reqList = THttpRequest::generate(readBuffer, peerAddress());
        }
        readBuffer.clear();
        lengthToRead = -1;
    }
    return reqList;
}
Example #28
0
THttpRequest THttpSocket::read()
{
    T_TRACEFUNC("");
    THttpRequest req;
    if (canReadRequest()) {
        int idx = readBuffer.indexOf("\r\n\r\n");
        if (idx > 0) {
            if (fileBuffer.isOpen()) {
                fileBuffer.close();
                req.setRequest(readBuffer.left(idx + 4), fileBuffer.fileName());
            } else {
                req.setRequest(readBuffer.left(idx + 4), readBuffer.mid(idx + 4));
            }
            readBuffer.clear();
            req.setClientAddress(peerAddress());
        }
    }
    return req;
}
/*!
  \~english
  Renders the \a view view.

  \~japanese
  ビューを描画する
*/
QByteArray TActionController::renderView(TActionView *view)
{
    T_TRACEFUNC("view: %p  layout: %s", view, qPrintable(layout()));

    if (!view) {
        tSystemError("view null pointer.  action:%s", qPrintable(activeAction()));
        return QByteArray();
    }
    view->setController(this);
    view->setVariantHash(allVariants());

    if (!layoutEnabled()) {
        // Renders without layout
        tSystemDebug("Renders without layout");
        return Tf::app()->codecForHttpOutput()->fromUnicode(view->toString());
    }
  
    // Displays with layout
    QString lay = (layout().isNull()) ? name().toLower() : layout().toLower();
    TDispatcher<TActionView> layoutDispatcher(layoutClassName(lay));
    TActionView *layoutView = layoutDispatcher.object();

    TDispatcher<TActionView> defLayoutDispatcher(layoutClassName("application"));
    if (!layoutView) {
        if (!layout().isNull()) {
            tSystemDebug("Not found layout: %s", qPrintable(layout()));
            return QByteArray();
        } else {
            // Use default layout
            layoutView = defLayoutDispatcher.object();
            if (!layoutView) {
                tSystemDebug("Not found default layout. Renders without layout.");
                return Tf::app()->codecForHttpOutput()->fromUnicode(view->toString());
            }
        }
    }

    // Renders layout
    layoutView->setVariantHash(allVariants());
    layoutView->setController(this);
    layoutView->setSubActionView(view);
    return Tf::app()->codecForHttpOutput()->fromUnicode(layoutView->toString());
}
/*!
  \~english
  Renders the template given by \a templateName with the layout \a layout.
 
  \~japanese
  レイアウト \a layout を適用し、テンプレート \a templateName を描画する
*/
bool TActionController::renderTemplate(const QString &templateName, const QString &layout)
{
    T_TRACEFUNC("");

    if (rendered) {
        tWarn("Has rendered already: %s", qPrintable(className() + '#' + activeAction()));
        return false;
    }
    rendered = true;

    // Creates view-object and displays it
    QStringList names = templateName.split("/");
    if (names.count() != 2) {
        tError("Invalid patameter: %s", qPrintable(templateName));
        return false;
    }
    TDispatcher<TActionView> viewDispatcher(viewClassName(names[0], names[1]));
    setLayout(layout);
    response.setBody(renderView(viewDispatcher.object()));
    return (!response.isBodyNull());
}