Example #1
0
    string 
handle_STARTE(const string &rawtext)
{
    int err;
    string ret;

    const char *handlefind = "STAERE ";
    const char *strfind = "\r\nCookie: ";

    size_t start = rawtext.find(handlefind) + strlen(handlefind);

    if (start == string::npos)
    {
        err = PC_INPUTFORMATERROR;
        ret = sys_error(err);
        ret += "\r\n\r\n";
        return ret;
    }

    size_t stop = rawtext.find(strfind, start);

    if (stop == string::npos)
    {
        err = PC_INPUTFORMATERROR;
        ret = sys_error(err);
        ret += "\r\n\r\n";
        return ret;
    }

    eid_t eid = rawtext.substr(start, stop - start);

    start = stop + strlen(strfind);

    stop = rawtext.find("\r\n", start);

    if (stop == string::npos)
    {
        err = PC_INPUTFORMATERROR;
        ret = sys_error(err);
        ret += "\r\n\r\n";
        return ret;
    }

    string cookie = rawtext.substr(start, stop - start);

    DB db;
    PGconn *dbconn = db.getConn();

    uid_t uid = getUIDByCookie(cookie, err, dbconn);

    gid_t gid = getGIDByUID(uid, err, dbconn);

    if (GID_STUDENT == gid 
            || gid == GID_ADMIN || gid == GID_TEACHER)
    {
        char ceid[MAXBUF];
        PQescapeString(ceid, eid.c_str(), eid.size() + 1);

        char sql_buf[MAXBUF];
        PGresult *res_exam;
        snprintf(sql_buf, sizeof(sql_buf), 
                "SELECT start_time as start, end_time, status as end "
                " FROM exam WHERE exam_id=%s "
                    "AND status = 'started'",
                ceid);

        res_exam = PQexec(dbconn, sql_buf);

        if (PQresultStatus(res_exam) != PGRES_TUPLES_OK)
        {
            err = PC_DBERROR;
            ret = sys_error(err);
            ret += "\r\n\r\n";
            PQclear(res_exam);
            return ret;
        }

        if (PQntuples(res_exam) == 0)
        {
            err = PC_NOTFOUND;
            ret = sys_error(err);
            ret += "\r\n\r\n";
            PQclear(res_exam);
            return ret;
        }

        // Is exam started
        time_t start = strtoul(PQgetvalue(res_exam, 0, 0), NULL, 10);
        time_t end = strtoul(PQgetvalue(res_exam, 0, 1), NULL, 10);

#if DBG
        fprintf(stderr, "%s:%d::start: %ul, end: %ul", __FUNCTION__,
                __LINE__, start, end)

#endif

            time_t now = time(NULL);
        if ( ! (now >=start 
                    && now <= end 
                    && strcmp("started", PQgetvalue(res_exam, 0, 2) ) == 0) )
        {
            err = PC_NOPERMISSION;
            ret = sys_error(err);
            ret += "\r\n\r\n";
            PQclear(res_exam);
            return ret;
        }

        PQclear(res_exam);

        snprintf(sql_buf, sizeof(sql_buf), 
                "SELECT * FROM student_exam WHERE user_id = '%s' AND paper_id IN ( "
                    "SELECT paper_id FROM paper WHERE exam_id = %s "
                ") AND final_score IS NOT NULL ",
                uid.c_str(), ceid);

        res_exam = PQexec(dbconn, sql_buf);

        if (PQresultStatus(res_exam) != PGRES_TUPLES_OK)
        {
            err = PC_DBERROR;
            ret = sys_error(err);
            ret += "\r\n\r\n";

            std::cerr << PQerrorMessage(dbconn) << std::endl;
            std::cerr.flush();
            PQclear(res_exam);
            return ret;
        }
        
        if (PQntuples(res_exam) >= 1)
        {
            err = PC_NOPERMISSION;
            ret = sys_error(err);
            ret += "\r\n\r\n";

            std::cerr << "Student can't take part in the same exam twice. " << std::endl;
            std::cerr.flush();

            PQclear(res_exam);
            return ret;
        }

        PQclear(res_exam);

        // time is valid, start the exam


        // check if we are crashed
        // TODO: check resume action

        // SELECT paper_id FROM paper WHERE exam_id=eid and paper_id=(
        //     SELECT currentpaper FROM users WHERE user_id=uid
        // );
        //

        snprintf(sql_buf, sizeof(sql_buf), 
                "SELECT paper_id FROM paper "
                "WHERE exam_id = %s "
                "AND paper_id = ( "
                "SELECT currentp FROM users WHERE user_id = '%s' "
                ")",
                ceid, uid.c_str());

        res_exam = PQexec(dbconn, sql_buf);

        if (PQresultStatus(res_exam) != PGRES_TUPLES_OK)
        {
            err = PC_DBERROR;
            ret = sys_error(err);
            ret += "\r\n\r\n";
            ret += PQerrorMessage(dbconn);
            PQclear(res_exam);
            return ret;
        }


        if (PQntuples(res_exam) > 0)
        {
            //This is a resume action, do nothing
            return "200 OK\r\n\r\n";
        }

        PQclear(res_exam);

        // TODO: brand new paper, do init

        // It's SO ugly! Use std::vector to
        // store all the PGresult and free it
        // before return
        int number_of_paper = 0;
        snprintf(sql_buf, sizeof(sql_buf), 
                "SELECT paper_id FROM paper "
                "WHERE exam_id = '%s' ", ceid);
        PGresult *res = PQexec(dbconn, sql_buf);

        if (PQresultStatus(res) != PGRES_TUPLES_OK)
        {
            err = PC_DBERROR;
            ret = sys_error(err);
            ret += "\r\n\r\n";

            ret += PQerrorMessage(dbconn);
            //ret += PQerrorMessage(dbconn);
            PQclear(res);
            //     PQclear(res_paper);

            return ret;
        }

        vector<pid_t> plist;
        for (int i = 0; i < PQntuples(res); i++)
        {
            plist.push_back(PQgetvalue(res, i, 0));
        }

        number_of_paper = plist.size();

        PQclear(res);

        srand(now);
        pid_t currentp = plist[rand() % number_of_paper];

        //TODO: choose a paper differ from the nearby
        // SELECT paper_id as pid FROM paper WHERE 
        //   pid NOT IN (
        //     SELECT currentp FROM users WHERE userid = uid+1
        //       OR userid=uid-1
        // );

        // choose a sequence scheme

        snprintf(sql_buf, sizeof(sql_buf), 
                "SELECT count(*) FROM question WHERE paper_id = %s", 
                currentp.c_str());
        res = PQexec(dbconn, sql_buf);

        if (PQresultStatus(res) != PGRES_TUPLES_OK && PQntuples(res) == 0)
        {
            err = PC_DBERROR;
            ret = sys_error(err);
            ret += "\r\n\r\n";

            ret += PQerrorMessage(dbconn);
            PQclear(res);
            return ret;
        }

        int number_of_question = atoi(PQgetvalue(res, 0, 0));


        srand(now);
        int scheme = rand() % number_of_question;
        PQclear(res);
        //TODO: put scheme into DB
        // TODO: put the paper_id into DB
        // UPDATE users SET currentp=pid, scheme=scheme
        //  WHERE userid=uid;
        snprintf(sql_buf, sizeof(sql_buf), 
                "UPDATE users SET currentp = %s, scheme = %d, qflag = 0"
                "WHERE user_id = '%s'",
                currentp.c_str(), scheme, uid.c_str());

        res = PQexec(dbconn, sql_buf);

        if (PQresultStatus(res) != PGRES_COMMAND_OK)
        {
            err = PC_DBERROR;
            ret = sys_error(err);
            ret += "\r\n\r\n";

            ret += PQerrorMessage(dbconn);
            PQclear(res);
            return ret;
        }

        PQclear(res);

        snprintf(sql_buf, sizeof(sql_buf), 
                "INSERT INTO student_exam VALUES ("
                "'%s', %s, false, null)",
                uid.c_str(), currentp.c_str());

        res = PQexec(dbconn, sql_buf);

        if (PQresultStatus(res) != PGRES_COMMAND_OK)
        {
            err = PC_DBERROR;
            ret = sys_error(err);
            ret += "\r\n\r\n";

            ret += PQerrorMessage(dbconn);
            PQclear(res);
            return ret;
        }

        err = PC_SUCCESSFUL;
        ret = sys_error(err);
        ret += "\r\n\r\n";

        return ret;
    } else {
        err = PC_NOPERMISSION;
        ret = sys_error(err);
        ret += "\r\n\r\n";
        return ret;
    }
}
Example #2
0
    string 
handle_NEXTQ(const string &rawtext)
{
    int err;
    string ret;

    const char *handlefind = "NEXTQ ";
    const char *strfind = "\r\nCookie: ";

    size_t start = rawtext.find(handlefind) + strlen(handlefind);

    if (start == string::npos)
    {
        err = PC_INPUTFORMATERROR;
        ret = sys_error(err);
        ret += "\r\n\r\n";
        return ret;
    }

    size_t stop = rawtext.find(strfind, start);

    if (stop == string::npos)
    {
        err = PC_INPUTFORMATERROR;
        ret = sys_error(err);
        ret += "\r\n\r\n";
        return ret;
    }

    eid_t eid = rawtext.substr(start, stop - start);

    start = stop + strlen(strfind);

    stop = rawtext.find("\r\n", start);

    if (stop == string::npos)
    {
        err = PC_INPUTFORMATERROR;
        ret = sys_error(err);
        ret += "\r\n\r\n";
        return ret;
    }

    string cookie = rawtext.substr(start, stop - start);

    DB db;
    PGconn *dbconn = db.getConn();

    char sql_buf[MAXBUF];

    uid_t uid = getUIDByCookie(cookie, err, dbconn);

    snprintf(sql_buf, sizeof(sql_buf),
            "SELECT question_id FROM question WHERE "
            "paper_id = ( "
                "SELECT currentp FROM users WHERE "
                "user_id = '%s'"
            ") ORDER BY question_id ",
            uid.c_str());

    PGresult *res = PQexec(dbconn, sql_buf);

    if (PQresultStatus(res) != PGRES_TUPLES_OK)
    {
        err = PC_DBERROR;
        ret = sys_error(err);
        ret += "\r\n\r\n";
        ret += PQerrorMessage(dbconn);
        PQclear(res);
        return ret;
    }
    
    vector<qid_t> qlist;
    qlist.reserve(PQntuples(res));

    for (int i = 0; i < PQntuples(res); ++i)
    {
        qlist.push_back(PQgetvalue(res, i, 0));
    }
    
    PQclear(res);

    snprintf(sql_buf, sizeof(sql_buf),
            "SELECT scheme, qflag, currentp FROM users "
            "WHERE user_id = '%s' ",
            uid.c_str());

    res = PQexec(dbconn, sql_buf);

    if (PQresultStatus(res) != PGRES_TUPLES_OK)
//            || PQgetisnull(res, 0, 0) 
//            || PQgetisnull(res, 0, 1)
//            || PQgetisnull(res, 0, 2))
    {
        err = PC_DBERROR;
        ret = sys_error(err);
        ret += "\r\n\r\n";
        ret += PQerrorMessage(dbconn);
        PQclear(res);
        return ret;
    }

    int scheme = atoi(PQgetvalue(res, 0, 0));

    //qflag
    unsigned int current = atoi(PQgetvalue(res, 0, 1));

    //current paper
    pid_t pid = PQgetvalue(res, 0, 2);

    PQclear(res);

    if (current >= qlist.size())
    {


        //TODO: Call judge 
        //TODO: Remove the flag From user;

        snprintf(sql_buf, sizeof(sql_buf), 
                "UPDATE users SET scheme = null, qflag = null, currentp = null "
                "WHERE user_id = '%s'",
                uid.c_str());

        res = PQexec(dbconn, sql_buf);

        if (PQresultStatus(res) != PGRES_COMMAND_OK)
        {
            err = PC_DBERROR;
            ret = sys_error(err);
            ret += "\r\n\r\n";
            ret += PQerrorMessage(dbconn);

            PQclear(res);
            return ret;
        }

        PQclear(res);

        getScore(uid, pid, err, dbconn);

        if (err != PC_SUCCESSFUL)
        {
            ret = sys_error(err);
            ret += "\r\n\r\n";

            ret += PQerrorMessage(dbconn);
            return ret;
        }

        //Exam is over
        err = PC_EXAMOVER;
        ret = sys_error(err);
        ret += "\r\n\r\n";

        return ret;
    }

    // now get the pid!
    qid_t qidnum = getNextQ(qlist, scheme, current);

    snprintf(sql_buf, sizeof(sql_buf),
            "SELECT content, choice_id, answer_content, timelimit FROM question, choice "
            "WHERE question.question_id = %s "
            "AND choice.question_id = question.question_id ",
            qidnum.c_str());

    res = PQexec(dbconn, sql_buf);
    if (PQresultStatus(res) != PGRES_TUPLES_OK 
            || PQntuples(res) == 0)
    {
        err = PC_DBERROR;
        ret = sys_error(err);
        ret += "\r\n\r\n";

        ret += PQerrorMessage(dbconn);
        PQclear(res);
        return ret;
    }


    // now that we've got the pid, generate the paper
    // TODO: generate the XML tree
    
    xmlDocPtr doc = xmlNewDoc(BAD_CAST "1.0");

    xmlNodePtr root_node = xmlNewNode(NULL, BAD_CAST "NEXTQ");
    
    xmlDocSetRootElement(doc, root_node);

    xmlNewChild(root_node, NULL, BAD_CAST "qid", BAD_CAST qidnum.c_str());

    xmlNewChild(root_node, NULL, BAD_CAST "description", BAD_CAST PQgetvalue(res, 0, 0));

    xmlNewChild(root_node, NULL, BAD_CAST "time", BAD_CAST PQgetvalue(res, 0, 3));

    for (int i = 0; i < PQntuples(res); ++i)
    {
        xmlNodePtr c_node = xmlNewNode(NULL, BAD_CAST "choice");
        xmlAddChild(root_node, c_node);
        xmlNewChild(c_node, NULL, BAD_CAST "cid", BAD_CAST PQgetvalue(res, i, 1));
        xmlNewChild(c_node, NULL, BAD_CAST "description", BAD_CAST PQgetvalue(res, i, 2));
    }

    snprintf(sql_buf, sizeof(sql_buf),
            "%d", current);

    xmlNewChild(root_node, NULL, BAD_CAST "fnum", BAD_CAST sql_buf);

    snprintf(sql_buf, sizeof(sql_buf),
            "%lu", qlist.size());
    xmlNewChild(root_node, NULL, BAD_CAST "tnum", BAD_CAST sql_buf);

    xmlChar *xmlbuffer;
    int buffersize;

    xmlDocDumpFormatMemory(doc, &xmlbuffer, &buffersize, 1);

    err = PC_SUCCESSFUL;
    ret = sys_error(err);
    ret += "\r\n\r\n";

    ret += (char *) xmlbuffer;
    xmlFreeDoc(doc);
    xmlFree(xmlbuffer);



    PQclear(res);


    return ret;
}
Example #3
0
string handle_MPSTA(const string &rawtext)
{
    uid_t userID;
    pid_t pid;
    string cookie = "";
    string status = "true";

    string response = "";

    int err = PC_UNKNOWNERROR;
    DB db;

    size_t start = rawtext.find(' ') + 1;
    size_t end = 0;

    //Get the pid
    end = rawtext.find("\r\n", start);
    pid = rawtext.substr(start, end - start);

    //Get the cookie
    start = rawtext.find(' ', end) + 1;
    end = rawtext.find("\r\n", start);
    cookie = rawtext.substr(start, end - start);

    //get the userID
    PGresult *dbres = PQexec(db.getConn(), "BEGIN");
    if (PQresultStatus(dbres) != PGRES_COMMAND_OK)
    {
        response = sys_error(PC_DBERROR);
        response += "\r\n\r\n";
        PQclear(dbres);
        return response;
    }
    PQclear(dbres);

    userID = getUIDByCookie(cookie, err, db.getConn());
    //check whether the cookie is right
     if (err != PC_SUCCESSFUL)
    {
        response = sys_error(err);
        response += "\r\n\r\n";
        PQexec(db.getConn(), "ROLLBACK");
        return response;
    }

    //check the group id
    gid_t gid = getGIDByUID(userID, err, db.getConn());
    if ((gid != GID_ADMIN) && (gid != GID_TEACHER))
    {
        err = PC_NOPERMISSION;
        response = sys_error(err);
        response += "\r\n\r\n";
        PQexec(db.getConn(), "ROLLBACK");
        return response;
    }

    char sql[300];
    size_t number_pid;
    stringstream ss;

    ss << pid;
    ss >> number_pid;
    
    //Check if there is some questions in the paper.
    snprintf(sql, sizeof(sql), "SELECT * FROM question WHERE paper_id = %lu", number_pid);

    //Exec the SQL query
    PGresult *res;
    res = PQexec(db.getConn(), sql);

    
    if( PQntuples(res) == 0)
    {
        //If there is no question in the paper, 
        //the paper won't be accomplished.

        err = PC_NOTFOUND;
        response = sys_error(err);
        response += "\r\n\r\n";
        PQclear(res);
        PQexec(db.getConn(), "ROLLBACK");
        return response;
    }

    snprintf(sql, sizeof(sql), 
            "UPDATE paper SET status = '%s' WHERE paper_id = %lu", 
            status.c_str(), number_pid);
    res = PQexec(db.getConn(), sql);
    if ((PQresultStatus(res) != PGRES_COMMAND_OK))
    {
        PQclear(res);
        err = PC_SYSTEMERROR;
        response = sys_error(err);
        response += "\r\n\r\n";
        PQexec(db.getConn(), "ROLLBACK");
        return response;
    }

    PQclear(res);
    err = PC_SUCCESSFUL;

    dbres = PQexec(db.getConn(), "COMMIT");
    PQclear(dbres);

    response = sys_error(err);
    response += "\r\n\r\n";

    return response;
}