/**
 * ステータスラインと、標準メッセージヘッダを出力します。
 */
NyLPC_TBool NyLPC_cHttpHeaderWriter_writeResponseHeader(NyLPC_TcHttpHeaderWriter_t* i_inst,NyLPC_TUInt16 i_status)
{
    NyLPC_TChar v[12];
    const char* m=getStatusMessage(i_status);
    //エラー状態ならなにもしない。
    if(i_inst->_is_error){
        return NyLPC_TBool_FALSE;
    }
    //検索に失敗したら500番に変更
    if(m==NULL){
        i_status=500;
        m=getStatusMessage(500);
    }
    //ステータスラインの記述
    if(!NyLPC_iHttpPtrStream_write(i_inst->_ref_stream,"HTTP/1.1 ",9)){
        NyLPC_OnErrorGoto(Error);
    }
    NyLPC_itoa(i_status,v,10);
    if(!NyLPC_iHttpPtrStream_write(i_inst->_ref_stream,v,-1)){
        NyLPC_OnErrorGoto(Error);
    }
    if(!NyLPC_iHttpPtrStream_write(i_inst->_ref_stream," ",1)){
        NyLPC_OnErrorGoto(Error);
    }
    if(!writeln(i_inst->_ref_stream,m,-1)){
        NyLPC_OnErrorGoto(Error);
    }
    if(!NyLPC_iHttpPtrStream_write(i_inst->_ref_stream,"Server: " NyLPC_cHttpdConfig_SERVER "\r\n",-1)){
        NyLPC_OnErrorGoto(Error);
    }
    if(i_inst->_is_close){
        if(!NyLPC_iHttpPtrStream_write(i_inst->_ref_stream,"Connection: CLOSE\r\n",-1)){
            NyLPC_OnErrorGoto(Error);
        }
    }
    //ヘッダの記述
    if(i_inst->_is_chunked){
        if(!NyLPC_iHttpPtrStream_write(i_inst->_ref_stream,"Transfer-Encoding: chunked\r\n",-1)){
            NyLPC_OnErrorGoto(Error);
        }
    }else{
        if(!NyLPC_iHttpPtrStream_write(i_inst->_ref_stream,"Content-Length: ",-1)){
            NyLPC_OnErrorGoto(Error);
        }
        NyLPC_uitoa(i_inst->_content_length,v,10);
        if(!writeln(i_inst->_ref_stream,v,-1)){
            NyLPC_OnErrorGoto(Error);
        }
    }
    //送信サイズをリセット
    i_inst->_size_of_sent=0;
    return NyLPC_TBool_TRUE;
Error:
    i_inst->_is_error=NyLPC_TUInt8_FALSE;
    return NyLPC_TBool_FALSE;
}
Exemple #2
0
void Core::loadConfiguration()
{
    QString path = Settings::getSettingsDirPath() + '/' + CONFIG_FILE_NAME;

    QFile configurationFile(path);

    if (!configurationFile.exists()) {
        qWarning() << "The Tox configuration file was not found";
        return;
    }

    if (!configurationFile.open(QIODevice::ReadOnly)) {
        qCritical() << "File " << path << " cannot be opened";
        return;
    }

    qint64 fileSize = configurationFile.size();
    if (fileSize > 0) {
        QByteArray data = configurationFile.readAll();
        tox_load(tox, reinterpret_cast<uint8_t *>(data.data()), data.size());
    }

    configurationFile.close();

    // set GUI with user and statusmsg
    QString name = getUsername();
    if (name != "")
        emit usernameSet(name);
    
    QString msg = getStatusMessage();
    if (msg != "")
        emit statusMessageSet(msg);

    loadFriends();
}
Exemple #3
0
// Constructor, init variables and open the specified file based on the
// specified mode (READ/WRITE).  Default is READ..
GlfFile::GlfFile(const char* filename, OpenType mode)
    : myFilePtr(NULL),
      myEndMarker()
{
    resetFile();

    bool openStatus = true;
    if(mode == READ)
    {
        // open the file for read.
        openStatus = openForRead(filename);
    }
    else
    {
        // open the file for write.
        openStatus = openForWrite(filename);
    }
    if(!openStatus)
    {
        // Failed to open the file - print error and abort.
        fprintf(stderr, "%s\n", getStatusMessage());
        std::cerr << "FAILURE - EXITING!!!" << std::endl;
        exit(-1);
    }
}
Exemple #4
0
	QString Status::toString(){
		OC_METHODGATE();
		if(isOK()){
			return "STATUS{OK}";
		}
		return "STATUS{ERROR MSG=" +getStatusMessage()+", CODE=" +QString::number(getStatusCode())+"}";
	}
/*
 * Sends a formatted response message to Sock with the given
 * status code and content type. The value of ContentType can
 * be NULL if no ContentType is required.
 */
static void httpSendStatusLine(Ssock_Handle ssock, int status, const char * contentType)
{
    char buf[MAXRESPONSESIZE];
    const char * msg;
    int len;

    Log_print1(Diags_ANALYSIS, "sendStatus> %d", (IArg)status);

    if (status < 0 || status > 999) {
        status = 999;
    }

    msg = getStatusMessage(status);

    if (contentType) {
        len = esnprintf(buf, sizeof(buf), "%s %3d %s\r\n%s%s\r\n", HTTP_VER,
                        status, msg, CONTENT_TYPE, contentType);
    }
    else {
        len = esnprintf(buf, sizeof(buf), "%s %3d %s\r\n\r\n", HTTP_VER,
                        status, msg);
    }

    if (len == sizeof(buf)) {
        Log_print1(Diags_WARNING, "sendStatus> Buffer size too small: %d", sizeof(buf));
    }

    Ssock_send(ssock, buf, len, 0);
}
Exemple #6
0
void lmcUpdateWindow::setUIText(void) {
	ui->retranslateUi(this);

	QString title = tr("%1 updates");
	setWindowTitle(title.arg(lmcStrings::appName()));

	ui->lblOutput->setText(getStatusMessage());
}
void HttpReqImpl::status(natural code, ConstStrA msg) {
	if (bHeaderSent)
		throw ErrorMessageException(THISLOCATION, "Headers already sent");

	statusCode = code;
	if (msg.empty())
		msg = getStatusMessage(statusCode);

	statusMsg = responseHdrPool.add(msg);
}
Exemple #8
0
// Constructor that opens the specified file for write.
GlfFileWriter::GlfFileWriter(const char* filename)
{
    if(!openForWrite(filename))
    {
        // Failed to open for reading - print error and abort.
        fprintf(stderr, "%s\n", getStatusMessage());
        std::cerr << "FAILURE - EXITING!!!" << std::endl;
        exit(-1);
    }
}
void HttpReqImpl::errorPage(natural code, ConstStrA msg, ConstStrA expl) {
	if (!bHeaderSent) {
		if (msg.empty()) msg = getStatusMessage(code);
		SeqFileOutput f(this);
		if (msg.empty()) msg = getStatusMessage(code);
		PrintTextA print(f);
		//clear some headers - they can damage output
		//delete content length - because we will show different page
		responseHdrs.erase(getHeaderFieldName(fldContentLength));
		//delete transfer encoding - because we need simplest encoding
		responseHdrs.erase(getHeaderFieldName(fldTransferEncoding));
		//delete content type - because we will set to text/html
		responseHdrs.erase(getHeaderFieldName(fldContentType));
		//delete eTag - don't store eTag with an error page
		responseHdrs.erase(getHeaderFieldName(fldETag));
		//delete lastModified - don't store error page
		responseHdrs.erase(getHeaderFieldName(fldLastModified));
		status(code,msg);
		//set new content type
		header(fldContentType,"text/html");

		if (code == 204 || code == 304) {
			//set ContentLength to zero even if it is not necesery, some clients can have issue
			header(fldContentLength,"0");
			sendHeaders();
			return;
		} else {
			closeConn = true;
		}
		print("<html><head><title>%1 %2</title></head><body><h1>%1 %2</h1>")
				<< code << msg;
		if (!expl.empty()) print("<pre>%1</pre>")<< expl;
		print("<hr>");
		print("<small><em>Powered by Bredy's JsonRpcServer - C++ http & jsonrpc server - <a href=\"https://github.com/ondra-novak/jsonrpcserver\">sources available</a></em></small>");
		print("</body></html>");
	}
	else {
		closeConn = true;
	}
}
Exemple #10
0
bool Core::loadConfiguration()
{
    QString path = QDir(Settings::getSettingsDirPath()).filePath(CONFIG_FILE_NAME);

    QFile configurationFile(path);

    if (!configurationFile.exists()) {
        qWarning() << "The Tox configuration file was not found";
        return true;
    }

    if (!configurationFile.open(QIODevice::ReadOnly)) {
        qCritical() << "File " << path << " cannot be opened";
        return true;
    }

    qint64 fileSize = configurationFile.size();
    if (fileSize > 0) {
        QByteArray data = configurationFile.readAll();
        int error = tox_load(tox, reinterpret_cast<uint8_t *>(data.data()), data.size());
        if (error < 0)
        {
            qWarning() << "Core: tox_load failed with error "<<error;
        }
        else if (error == 1) // Encrypted data save
        {
            qWarning() << "Core: Can not open encrypted tox save";
            if (QMessageBox::Ok != QMessageBox::warning(nullptr, tr("Encrypted profile"),
                tr("Your tox profile seems to be encrypted, qTox can't open it\nDo you want to erase this profile ?"),
                QMessageBox::Ok | QMessageBox::Cancel))
            {
                qWarning() << "Core: Couldn't open encrypted save, giving up";
                configurationFile.close();
                return false;
            }
        }
    }

    configurationFile.close();

    // set GUI with user and statusmsg
    QString name = getUsername();
    if (name != "")
        emit usernameSet(name);
    
    QString msg = getStatusMessage();
    if (msg != "")
        emit statusMessageSet(msg);

    loadFriends();
    return true;
}
void HTTPSrv_sendErrorResponse(Ssock_Handle ssock, int status)
{
    /* send a default response if there is no user callback */
    if (!HTTPSrv_errorResponseHook || !HTTPSrv_errorResponseHook(ssock, status)) {
        char buf[33];
        int len;

        len = esnprintf(buf, sizeof(buf), "Failed: %d %s", status,
                        getStatusMessage(status));
        //Log_print2(Diags_ANALYSIS, "len = %d: %s\n", len, (xdc_IArg)buf);
        HTTPSrv_sendResponse(ssock, status, CONTENT_TYPE_PLAIN, len, buf);
    }
}
Exemple #12
0
void Core::setStatusMessage(const QString& message)
{
    if (message == getStatusMessage())
        return;

    CString cMessage(message);

    if (!tox_self_set_status_message(tox, cMessage.data(), cMessage.size(), nullptr))
    {
        emit failedToSetStatusMessage(message);
        return;
    }

    if (ready)
        profile.saveToxSave();
    emit statusMessageSet(message);
}
void HttpReqImpl::sendHeaders() {
	if (bHeaderSent)
		return;

	if (bNeedContinue) {
		remainPostData = 0;
		chunkedPost = false;
	}
	bNeedContinue = false;

	bool hasServer = false;
	bool hasContentType = false;
	bool hasTransfEnc = false;
	bool hasConnection = false;
	bool hasLength = false;
	bool hasDate = false;
	static ConstStrA contentTypeKey = getHeaderFieldName(fldContentType);
	static ConstStrA serverKey = getHeaderFieldName(fldServer);
	static ConstStrA transfEnc = getHeaderFieldName(fldTransferEncoding);
	static ConstStrA connectionStr = getHeaderFieldName(fldConnection);
	static ConstStrA contenLenStr = getHeaderFieldName(fldContentLength);
	static ConstStrA dateStr = getHeaderFieldName(fldDate);
	ConstStrA statusMsgStr = this->statusMsg;
	if (statusMsgStr.empty())
		statusMsgStr = getStatusMessage(statusCode);


	PrintTextA print(*inout);
	print.setNL("\r\n");
	print("HTTP/%1.%2 %3 %4\n") << httpMajVer << httpMinVer << statusCode
			<< statusMsgStr;

	if (statusCode == 101) {
		hasTransfEnc = hasConnection = hasContentType = true;
		useChunked = false;
		remainPostData = naturalNull;
		switchedProtocol = true;
		TimeStamp reqEndTime = TimeStamp::now();
		natural reqTime = (reqEndTime - reqBeginTime).getMilis();
		logRequest(reqTime);
	}

	for (HeaderMap::Iterator iter = responseHdrs.getFwIter(); iter.hasItems();) {
		const HeaderMap::Entity hdrPair = iter.getNext();
		if (!hasContentType && hdrPair.key == contentTypeKey)
			hasContentType = true;

		if (!hasServer && hdrPair.key == serverKey)
			hasServer = true;

		if (!hasTransfEnc && hdrPair.key == transfEnc)
			hasTransfEnc = !(useChunked && hdrPair.value == ConstStrA("chunked"));

		if (!hasConnection && hdrPair.key == connectionStr)
			hasConnection = true;

		if (!hasDate && hdrPair.key == dateStr)
			hasDate = true;

		if (!hasLength && hdrPair.key == contenLenStr) {
			hasLength = true;
		}

		print("%1: %2\n") << ConstStrA(hdrPair.key) << ConstStrA(hdrPair.value);
	}
	if (!hasContentType)
		print("%1: %2\n") << contentTypeKey << "text/html;charset=UTF-8";

	if (!hasServer)
		print("%1: %2\n") << serverKey << serverIdent;

	if (hasLength) {
		useChunked = false;
	}

	if (!hasDate) {
		TimeStamp::RFC1123Time datenow = TimeStamp::now().asRFC1123Time();
		print("%1: %2\n") << dateStr << ConstStrA(datenow);
	}

	if (!hasTransfEnc && useChunked && !closeConn)
		print("%1: %2\n") << transfEnc << "chunked";
	else
		useChunked = false;

	if (!hasConnection && closeConn)
		print("%1: %2\n") << connectionStr << "close";

	print("\n");

/*	LogObject(THISLOCATION).progress("%7 - %3 %4 HTTP/%1.%2 %5 %6")
		<< httpMajVer << httpMajVer << ConstStrA(method)
		<< ConstStrA(path) << statusCode << statusMsgStr
		<< getIfc<IHttpPeerInfo>().getPeerRealAddr();*/

	responseHdrs.clear();
	//for code 100 or 101, additional header will be next
	if (statusCode == 100) {
		//set status code 200 to simply processing reply (handler don't need to reset 100 status
		statusCode = 200;
		//unset message
		this->statusMsg = HdrStr();
		//now, handler can exit function with status 100 - when data arrives, onData will be called
	} else {
		//header sent, prevent sending new headers
		bHeaderSent = true;
	}
}
Exemple #14
0
/**
 * @brief Initializes the core, must be called before anything else
 */
void Core::start()
{
    bool isNewProfile = profile.isNewProfile();
    if (isNewProfile)
    {
        qDebug() << "Creating a new profile";
        makeTox(QByteArray());
        setStatusMessage(tr("Toxing on qTox"));
        setUsername(profile.getName());
    }
    else
    {
        qDebug() << "Loading user profile";
        QByteArray savedata = profile.loadToxSave();
        if (savedata.isEmpty())
        {
            emit failedToStart();
            return;
        }
        makeTox(savedata);
    }

    qsrand(time(nullptr));

    if (!tox)
    {
        ready = true;
        GUI::setEnabled(true);
        return;
    }

    // set GUI with user and statusmsg
    QString name = getUsername();
    if (!name.isEmpty())
        emit usernameSet(name);

    QString msg = getStatusMessage();
    if (!msg.isEmpty())
        emit statusMessageSet(msg);

    QString id = getSelfId().toString();
    if (!id.isEmpty())
        emit idSet(id);

    // TODO: This is a backwards compatibility check,
    // once most people have been upgraded away from the old HistoryKeeper, remove this
    if (Nexus::getProfile()->isEncrypted())
        checkEncryptedHistory();

    loadFriends();

    tox_callback_friend_request(tox, onFriendRequest, this);
    tox_callback_friend_message(tox, onFriendMessage, this);
    tox_callback_friend_name(tox, onFriendNameChange, this);
    tox_callback_friend_typing(tox, onFriendTypingChange, this);
    tox_callback_friend_status_message(tox, onStatusMessageChanged, this);
    tox_callback_friend_status(tox, onUserStatusChanged, this);
    tox_callback_friend_connection_status(tox, onConnectionStatusChanged, this);
    tox_callback_friend_read_receipt(tox, onReadReceiptCallback, this);
    tox_callback_group_invite(tox, onGroupInvite, this);
    tox_callback_group_message(tox, onGroupMessage, this);
    tox_callback_group_namelist_change(tox, onGroupNamelistChange, this);
    tox_callback_group_title(tox, onGroupTitleChange, this);
    tox_callback_group_action(tox, onGroupAction, this);
    tox_callback_file_chunk_request(tox, CoreFile::onFileDataCallback, this);
    tox_callback_file_recv(tox, CoreFile::onFileReceiveCallback, this);
    tox_callback_file_recv_chunk(tox, CoreFile::onFileRecvChunkCallback, this);
    tox_callback_file_recv_control(tox, CoreFile::onFileControlCallback, this);

    QPixmap pic = profile.loadAvatar();
    if (!pic.isNull() && !pic.size().isEmpty())
    {
        QByteArray data;
        QBuffer buffer(&data);
        buffer.open(QIODevice::WriteOnly);
        pic.save(&buffer, "PNG");
        buffer.close();
        setAvatar(data);
    }
    else
    {
        qDebug() << "Self avatar not found, will broadcast empty avatar to friends";
        setAvatar({});
    }

    ready = true;

    // If we created a new profile earlier,
    // now that we're ready save it and ONLY THEN broadcast the new ID.
    // This is useful for e.g. the profileForm that searches for saves.
    if (isNewProfile)
    {
        profile.saveToxSave();
        emit idSet(getSelfId().toString());
    }

    if (isReady())
        GUI::setEnabled(true);

    process(); // starts its own timer
    av->start();
}
Exemple #15
0
/**
 * @brief Initializes the core, must be called before anything else
 */
void Core::start(const QByteArray& savedata)
{
    bool isNewProfile = profile.isNewProfile();
    if (isNewProfile) {
        qDebug() << "Creating a new profile";
        makeTox(QByteArray());
        makeAv();
        setStatusMessage(tr("Toxing on qTox"));
        setUsername(profile.getName());
    } else {
        qDebug() << "Loading user profile";
        if (savedata.isEmpty()) {
            emit failedToStart();
            return;
        }

        makeTox(savedata);
        makeAv();
    }

    qsrand(time(nullptr));
    if (!tox) {
        ready = true;
        GUI::setEnabled(true);
        return;
    }

    // set GUI with user and statusmsg
    QString name = getUsername();
    if (!name.isEmpty()) {
        emit usernameSet(name);
    }

    QString msg = getStatusMessage();
    if (!msg.isEmpty()) {
        emit statusMessageSet(msg);
    }

    ToxId id = getSelfId();
    // TODO: probably useless check, comes basically directly from toxcore
    if (id.isValid()) {
        emit idSet(id);
    }

    loadFriends();

    tox_callback_friend_request(tox, onFriendRequest);
    tox_callback_friend_message(tox, onFriendMessage);
    tox_callback_friend_name(tox, onFriendNameChange);
    tox_callback_friend_typing(tox, onFriendTypingChange);
    tox_callback_friend_status_message(tox, onStatusMessageChanged);
    tox_callback_friend_status(tox, onUserStatusChanged);
    tox_callback_friend_connection_status(tox, onConnectionStatusChanged);
    tox_callback_friend_read_receipt(tox, onReadReceiptCallback);
    tox_callback_conference_invite(tox, onGroupInvite);
    tox_callback_conference_message(tox, onGroupMessage);
    tox_callback_conference_namelist_change(tox, onGroupNamelistChange);
    tox_callback_conference_title(tox, onGroupTitleChange);
    tox_callback_file_chunk_request(tox, CoreFile::onFileDataCallback);
    tox_callback_file_recv(tox, CoreFile::onFileReceiveCallback);
    tox_callback_file_recv_chunk(tox, CoreFile::onFileRecvChunkCallback);
    tox_callback_file_recv_control(tox, CoreFile::onFileControlCallback);

    QByteArray data = profile.loadAvatarData(getSelfPublicKey().toString());
    if (data.isEmpty()) {
        qDebug() << "Self avatar not found, will broadcast empty avatar to friends";
    }

    setAvatar(data);

    ready = true;

    if (isNewProfile) {
        profile.saveToxSave();
    }

    if (isReady()) {
        GUI::setEnabled(true);
    }

    process(); // starts its own timer
    av->start();
}
void NetworkManipulationTool::activate(NetworkVisualization *visu) {
	mVisuContext = visu;
	updateStatusMessage(getStatusMessage());
}
Exemple #17
0
	if (!SearchesManager::getSearchEngines().contains(m_quickSearchEngine))
	{
		const QString engine = SettingsManager::getValue(QLatin1String("Search/DefaultSearchEngine")).toString();

		if (engine != m_quickSearchEngine)
		{
			m_quickSearchEngine = engine;

			emit quickSearchEngineChanged();
		}
	}
}

void WebWidget::setStatusMessage(const QString &message, bool override)
{
	const QString oldMessage = getStatusMessage();

	if (override)
	{
		m_overridingStatusMessage = message;
	}
	else
	{
		m_javaScriptStatusMessage = message;
	}

	const QString newMessage = getStatusMessage();

	if (newMessage != oldMessage)
	{
		emit statusMessageChanged(newMessage);
Exemple #18
0
void Core::start()
{
    qDebug() << "Core: Starting up";

    QByteArray savedata = loadToxSave(loadPath);

    make_tox(savedata);

    // Do we need to create a new save & profile?
    if (savedata.isNull())
    {
        qDebug() << "Save file not found, creating a new profile";
        Settings::getInstance().load();
        setStatusMessage(tr("Toxing on qTox"));
        setUsername(tr("qTox User"));
    }

    qsrand(time(nullptr));

    // set GUI with user and statusmsg
    QString name = getUsername();
    if (!name.isEmpty())
        emit usernameSet(name);

    QString msg = getStatusMessage();
    if (!msg.isEmpty())
        emit statusMessageSet(msg);

    QString id = getSelfId().toString();
    if (!id.isEmpty())
        emit idSet(id);

    // tox core is already decrypted
    if (Settings::getInstance().getEnableLogging() && Settings::getInstance().getEncryptLogs())
        checkEncryptedHistory();

    loadFriends();

    tox_callback_friend_request(tox, onFriendRequest, this);
    tox_callback_friend_message(tox, onFriendMessage, this);
    tox_callback_friend_name(tox, onFriendNameChange, this);
    tox_callback_friend_typing(tox, onFriendTypingChange, this);
    tox_callback_friend_status_message(tox, onStatusMessageChanged, this);
    tox_callback_friend_status(tox, onUserStatusChanged, this);
    tox_callback_friend_connection_status(tox, onConnectionStatusChanged, this);
    tox_callback_friend_read_receipt(tox, onReadReceiptCallback, this);
    tox_callback_group_invite(tox, onGroupInvite, this);
    tox_callback_group_message(tox, onGroupMessage, this);
    tox_callback_group_namelist_change(tox, onGroupNamelistChange, this);
    tox_callback_group_title(tox, onGroupTitleChange, this);
    tox_callback_group_action(tox, onGroupAction, this);
    tox_callback_file_chunk_request(tox, CoreFile::onFileDataCallback, this);
    tox_callback_file_recv(tox, CoreFile::onFileReceiveCallback, this);
    tox_callback_file_recv_chunk(tox, CoreFile::onFileRecvChunkCallback, this);
    tox_callback_file_recv_control(tox, CoreFile::onFileControlCallback, this);

    toxav_register_callstate_callback(toxav, onAvInvite, av_OnInvite, this);
    toxav_register_callstate_callback(toxav, onAvStart, av_OnStart, this);
    toxav_register_callstate_callback(toxav, onAvCancel, av_OnCancel, this);
    toxav_register_callstate_callback(toxav, onAvReject, av_OnReject, this);
    toxav_register_callstate_callback(toxav, onAvEnd, av_OnEnd, this);
    toxav_register_callstate_callback(toxav, onAvRinging, av_OnRinging, this);
    toxav_register_callstate_callback(toxav, onAvMediaChange, av_OnPeerCSChange, this);
    toxav_register_callstate_callback(toxav, onAvMediaChange, av_OnSelfCSChange, this);
    toxav_register_callstate_callback(toxav, onAvRequestTimeout, av_OnRequestTimeout, this);
    toxav_register_callstate_callback(toxav, onAvPeerTimeout, av_OnPeerTimeout, this);

    toxav_register_audio_callback(toxav, playCallAudio, this);
    toxav_register_video_callback(toxav, playCallVideo, this);

    QPixmap pic = Settings::getInstance().getSavedAvatar(getSelfId().toString());
    if (!pic.isNull() && !pic.size().isEmpty())
    {
        QByteArray data;
        QBuffer buffer(&data);
        buffer.open(QIODevice::WriteOnly);
        pic.save(&buffer, "PNG");
        buffer.close();
        setAvatar(data);
    }
    else
    {
        qDebug() << "Core: Error loading self avatar";
    }

    ready = true;

    // If we created a new profile earlier,
    // now that we're ready save it and ONLY THEN broadcast the new ID.
    // This is useful for e.g. the profileForm that searches for saves.
    if (savedata.isNull())
    {
        saveConfiguration();
        emit idSet(getSelfId().toString());
    }

    if (isReady())
        GUI::setEnabled(true);

    process(); // starts its own timer
}