Ответы пользователя по тегу C++
  • Как синхронизовать файл через Google Drive API?

    SerJook
    @SerJook
    кодер
    Ну наверно надо начать с чтения документации Google Drive API.
    Логин и пароль вам не понадобятся.
    Аутентификация производится с помощью OAuth 2.0.
    Первое что вам нужно сделать, это создать приложение через Google API Console,получить реквизиты вашего приложения и подключить к нему Google Drive API.

    Один из способов аутентификации с использованием кода подтверждения я опишу ниже.

    1. Cначала открываете пользователю (в системном браузере) URL:
      https://accounts.google.com/o/oauth2/auth?scope={scope}&redirect_uri={redirect_uri}&response_type=code&client_id={client_id}

      (Это можно сделать с помощью метода QDesktopServices::openUrl
      где {scope} = "https://www.googleapis.com/auth/drive"
      {redirect_uri} = "urn:ietf:wg:oauth:2.0:oob"
      {client_id}= blablabla.apps.googleusercontent.com (айди вашего приложения)

      Пользователь подтверждает доступ и копирует код подтверждения.
      Вы предлагаете ввести код подтверждения в вашем приложении. Пользователь его вводит.

    2. Для получения access token нужно отправить POST запрос на сервер https://www.googleapis.com/oauth2/v3/token
      с параметрами:
      code - код подтверждения, введенный пользователем
      client_id - айди вашего приложения (blablabla.apps.googleusercontent.com)
      client_secret - секретный ключ вашего приложения
      redirect_uri - тот же самый redirect uri, что и в первом случае
      grant_type = "authorization_code"
      Запрос можно сделать с помощью qnetworkaccessmanager
      В ответе вы получаете access_token, который нужно будет использовать для запросов к Google Drive API.

      Также в ответе будет refresh_token, который нужен для обновления access_token.

    3. Чтобы создать папку, вам понадобится отправить POST запрос на URL:
      https://www.googleapis.com/drive/v3/files
      В заголовках запроса прописать:
      Authorization:  Bearer <полученный access_token>
      Content-Type: application/json


      В теле запроса отправить json:
      {
         "title": "Название папки"
         "mimeType":  "application/vnd.google-apps.folder"
      }

      В ответ вам придет json с ID папки.


      Как загрузить файл описано
    здесь
    Короче все элементарно.
    Ответ написан
    Комментировать
  • Как преобразовать NULL const char* в string?

    SerJook
    @SerJook
    кодер
    const char* str1 = NULL;
    std::string str2 = str1 ? str1 : "";
    Ответ написан
    Комментировать
  • Как исправить C2061?

    SerJook
    @SerJook
    кодер
    У вас круговая зависимость файлов заголовков.
    Решается с помощью forward-declaration.
    Добавьте в файл mob.h до "class Mob" следующее:
    class Player;

    а также удалите строку
    #include "Player.h"
    Ответ написан
    3 комментария
  • Нужна ли DlgProc при использовании собственного класса для диалога?

    SerJook
    @SerJook
    кодер
    Оконный класс должен быть зарегистрирован с
    wc.cbWndExtra = DLGWINDOWEXTRA;
    В оконной процедуре (WndProc) класса нужно реализовать общий функционал для всех диалогов данного класса и вызывать DefDlgProc. Эта функция пересылает сообщения в DlgProc, и обеспечивает дефолтную обработку для тех сообщений, для которых DlgProc вернула FALSE.

    В диалоговой процедуре DlgProc, которую вы передаете в CreateDialogParam, реализуйте функционал для конкретного диалога.
    Ответ написан
  • Внешние команды в C++?

    SerJook
    @SerJook
    кодер
    Boost.Process
    Ответ написан
    Комментировать
  • Почему не получается переписать функцию под С++?

    SerJook
    @SerJook
    кодер
    По-моему оба варианта функции какие-то странные.
    Если вам нужно шестнадцатеричное представление, то на C# это будет примерно так:

    string s = "876c0e09-70f7-4190-ab3a-254b6e5f461e";
    byte[] data = Encoding.Unicode.GetBytes(s);
    byte[] hash = new MD5CryptoServiceProvider().ComputeHash(data);
    StringBuilder sb = new StringBuilder();
    foreach (var b in hash)
    {
       sb.Append(b.ToString("x2"));
    }
    string outVAR = sb.ToString();
    Console.WriteLine(outVAR);


    а на c++ так:
    string ToBytes(const wstring& str) {
        const char* d = reinterpret_cast<const char*>(&str[0]);
        string result(d, d+str.size()*2);
        return result;
    }
    
    int main() {
        wstring data = L"876c0e09-70f7-4190-ab3a-254b6e5f461e"; // на винде это будет UTF-16 строка, как и в C#
        cout << md5(ToBytes(data)) << endl;
        system("pause");
    }


    результат будет одинаков (по крайней мере на винде)

    d1206f6bcf6d9b31860482123c288650

    Но если вам прям так нужен результат точь-в-точь как в C#, то попробуйте этот код:

    spoiler
    std::string WinMD5(const void * data, const size_t data_size)
    {
        HCRYPTPROV hProv = NULL;
    
        if (!CryptAcquireContext(&hProv, NULL, NULL, PROV_RSA_AES, CRYPT_VERIFYCONTEXT)) {
            return std::string();
        }
    
        HCRYPTPROV hHash = NULL;
        BOOL hash_ok = CryptCreateHash(hProv, CALG_MD5, 0, 0, &hHash);
       
    
        if (!hash_ok) {
            CryptReleaseContext(hProv, 0);
            return std::string();
        }
    
        if (!CryptHashData(hHash, static_cast<const BYTE *>(data), static_cast<DWORD>(data_size), 0)) {
            CryptDestroyHash(hHash);
            CryptReleaseContext(hProv, 0);
            return std::string();
        }
    
        DWORD cbHashSize = 0, dwCount = sizeof(DWORD);
        if (!CryptGetHashParam(hHash, HP_HASHSIZE, (BYTE *)&cbHashSize, &dwCount, 0)) {
            CryptDestroyHash(hHash);
            CryptReleaseContext(hProv, 0);
            return std::string();
        }
    
        std::vector<BYTE> buffer(cbHashSize);
        if (!CryptGetHashParam(hHash, HP_HASHVAL, reinterpret_cast<BYTE*>(&buffer[0]), &cbHashSize, 0)) {
            CryptDestroyHash(hHash);
            CryptReleaseContext(hProv, 0);
            return std::string();
        }
    
        std::ostringstream oss;
    
        for (auto item: buffer) {
            oss << static_cast<unsigned int>(item);
        }
    
        CryptDestroyHash(hHash);
        CryptReleaseContext(hProv, 0);
        return oss.str();
    }
    
    string ToBytes(const wstring& str) {
        const char* d = reinterpret_cast<const char*>(&str[0]);
        string result(d, d+str.size()*2);
        return result;
    }
    
    
    int main() {
        wstring data = L"876c0e09-70f7-4190-ab3a-254b6e5f461e";
        cout << WinMD5(data.data(), data.size()* sizeof(wchar_t));
        system("pause");
    }



    результат:
    2093211110720710915549134413018604013480
    Ответ написан
    1 комментарий
  • Как добавить в comboBox.Items строку std::string в c++ WinForms?

    SerJook
    @SerJook
    кодер
    combobox->Items->Add(gcnew String(str.c_str()));
    Ответ написан
    Комментировать
  • Как в qt creator узнать размер диска?

    SerJook
    @SerJook
    кодер
    QStorageInfo storage("e:/");
    qDebug() << "name:" << storage.name();
    qDebug() << "fileSystemType:" << storage.fileSystemType();
    qDebug() << "size:" << storage.bytesTotal()/1000/1000 << "MB";
    qDebug() << "availableSize:" << storage.bytesAvailable()/1000/1000 << "MB";


    Ну и вверху не забудьте добавить
    #include <QStorageInfo>
    #include <QDebug>
    Ответ написан
    Комментировать
  • Почему не получается верифицировать подпись на С++ сделанную на Python?

    SerJook
    @SerJook
    кодер
    Потому что на вход RSA_verify надо подавать хэш данных, а не сами данные.

    std::string text = "hello world";
    SHA512_CTX sha_ctx = { 0 };
    unsigned char digest[SHA512_DIGEST_LENGTH];
    SHA512_Init(&sha_ctx);
    SHA512_Update(&sha_ctx, text.data(), text.length());
    SHA512_Final(digest, &sha_ctx);
    
    if (RSA_verify(NID_sha512, digest, SHA512_DIGEST_LENGTH, (const unsigned char*)sign.data(), sign.length(), publicRSA) == 1) {
       // Успех
    }
    Ответ написан
    3 комментария
  • Как работать с библиотекой CImg C++?

    SerJook
    @SerJook
    кодер
    Здесь полно примеров: https://github.com/dtschump/CImg/tree/master/examples
    Чтобы сохранить в файл используйте метод save()
    Ответ написан
    Комментировать
  • Как переопределить метод setData() QSqlQueryModel, что бы изменять цвет текста?

    SerJook
    @SerJook
    кодер
    Унаследуйся от класса QSqlQueryModel и переопредели метод data():

    QVariant MyModel::data(const QModelIndex &index, int role) const {
      if(role == Qt::TextColorRole) {
        return QVariant(QColor(Qt::blue));
      }
      return QSqlQueryModel::data(index, role);
    }
    Ответ написан
    Комментировать
  • Почему нет треугольника?

    SerJook
    @SerJook
    кодер
    Неправильная обработка сообщения WM_SIZE:
    The low-order word of lParam specifies the new width of the client area.
    The high-order word of lParam specifies the new height of the client area.

    case WM_SIZE:
            glViewport(0, 0, LOWORD(lParam), HIWORD(lParam));


    5cd2ef0534175926741512.png
    Ответ написан
    1 комментарий
  • Как подключить библиотеку с GitHub в свой проект (C++)?

    SerJook
    @SerJook
    кодер
    Предположим что вы используете Windows и Visual Studio. Тогда:

    1. Для работы этой библиотеки вам понадобится библиотека libcurl.
    Скорее всего вам придется собирать libcurl из исходников. В архиве с исходниками есть инструкция, как ее собирать на Windows (winbuild\BUILD.WINDOWS.txt). Соберите к примеру статическую библиотеку (.lib).

    2. Распакуйте файлы исходников из архива с библиотекой Kolsha/VK (из папки src) в папку вашего проекта.
    Добавьте эти файлы в ваш проект в Visual Studio.

    3. Укажите в свойствах проекта (С++ ->General->Additional include directories) путь к папке, содержащей хедеры libcurl (к примеру "с:\dev\curl-7.58.0\include\" )
    а также в (Linker->general->Additional library directories) путь к папке, содержащей собранную библиотеку (к примеру "c:\dev\curl-7.58.0\builds\libcurl-vc12-x86-release-static-zlib-static-ipv6-sspi-winssl\lib\").
    В свойства проекта -> Linker->Input->Additional dependencies добавьте "libcurl_a.lib".
    Ответ написан
    Комментировать
  • Как загрузить файл на сервер не используя cURL?

    SerJook
    @SerJook
    кодер
    Если размер файла не очень большой, можно попробовать с помощью WinInet:

    КОД
    #include <windows.h>
    #include <wininet.h>
    #include <fstream>
    #include <sstream>
    #include <iostream>
    #pragma comment(lib,"wininet.lib")
    
    int main(int argc, char* argv[])
    {
        // инициализируем WinInet
        HINTERNET hInternet = ::InternetOpen(TEXT("WinInet Test"), INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0);
    
        if (hInternet != NULL) {
            // открываем HTTP сессию
            HINTERNET hConnect = ::InternetConnect(hInternet, TEXT("localhost"), INTERNET_DEFAULT_HTTP_PORT, NULL, NULL,
                                                    INTERNET_SERVICE_HTTP, 0, 1u);
    
            if (hConnect != NULL) {
                // открываем запрос
                HINTERNET hRequest = ::HttpOpenRequest(hConnect, TEXT("POST"), TEXT("test.php"), NULL, NULL, 0, INTERNET_FLAG_KEEP_CONNECTION, 1);
    
                if (hRequest != NULL) {
                    // посылаем запрос
                    std::string fileName = "c:\\test.png"; // путь к файлу
                    char hdrs[] = "Content-Type: multipart/form-data; boundary=---------------------------7d82751e2bc0858";
                    std::string frmdata = "-----------------------------7d82751e2bc0858\r\n";
                    // В этой строке "uploadedfile" - название поля формы
                    frmdata += "Content-Disposition: form-data; name=\"uploadedfile\"; filename=\"" + fileName + "\"\r\nContent-Type: application/octet-stream\r\n\r\n";
                    std::ostringstream ostrm;
                    std::ifstream fin(fileName, std::ios::binary);
                    if (fin) {
                        ostrm << fin.rdbuf();
    
                        frmdata.append(ostrm.str());
                        frmdata += "\r\n-----------------------------7d82751e2bc0858--\r\n";
    
                        BOOL bSend = ::HttpSendRequestA(hRequest, hdrs, strlen(hdrs), &frmdata[0], frmdata.size());
                        if (bSend) {
                            std::string res; // В этой переменной будет ответ сервера
                            for (;;) {
                                // читаем данные
                                char szData[1024];
                                DWORD dwBytesRead;
                                BOOL bRead = ::InternetReadFile(hRequest, szData, sizeof(szData) - 1, &dwBytesRead);
    
                                // выход из цикла при ошибке или завершении
                                if (bRead == FALSE || dwBytesRead == 0)
                                    break;
    
                                // сохраняем результат
                                szData[dwBytesRead] = 0;
                                res.append(szData);
                            }
                            std::cout << res;
                        }
                    }
                    // закрываем запрос
                    ::InternetCloseHandle(hRequest);
                }
                // закрываем сессию
                ::InternetCloseHandle(hConnect);
            }
            // закрываем WinInet
            ::InternetCloseHandle(hInternet);
        }
    
        return 0;
    }
    Ответ написан
    6 комментариев
  • Почему это компилируется и вообще как работает место в коде и что, так можно было (QSharedPointer)?

    SerJook
    @SerJook
    кодер
    Согласно стандарту C++11 такое не должно компилироваться. Но у Майкрософта своё видение стандартов.
    GCC выдаст ошибку
    error: could not convert ‘false’ from ‘bool’ to ‘QSharedPointer<QDataStream>'
    Ответ написан
  • При вводе пути к файлу через консоль CURL перестает работать, что делать?

    SerJook
    @SerJook
    кодер
    После CURLFORM_FILE должен идти указатель на "голую" строку (массив char, заканчивающийся нулем), вы же передаете объект типа string.
    Должно быть так:

    curl_formadd(&post, &last,
          CURLFORM_COPYNAME, "userfile",
          CURLFORM_FILE, filepath.c_str(),
          CURLFORM_END);
    Ответ написан
    Комментировать
  • Как правильно найти длину строки с кириллицей в юникоде на C++?

    SerJook
    @SerJook
    кодер
    Если под линуксом, то как-то так можно посчитать:

    #include <cstdlib>
    //....
    setlocale(LC_ALL, "ru_RU.utf8");
    int strLength = mbstowcs(NULL, strBody.c_str(), 0);


    в винде это работать увы не будет
    Ответ написан
    1 комментарий
  • Не создаётся дочернее окно WinAPI или CreateWindows возвращает нуль?

    SerJook
    @SerJook
    кодер
    Может потому, что вы регистрируете класс с именем "ChildMain", а пытаетесь создать окно класса "ChildWnd" ??
    Ответ написан
    Комментировать
  • Как удалить линии вокруг кнопок и прочих элементов в WinAPI?

    SerJook
    @SerJook
    кодер
    Попробуйте так:

    SendMessage(hWndButton, WM_CHANGEUISTATE, MAKEWPARAM(UIS_SET, UISF_HIDEFOCUS), 0);


    Можете отослать это сообщение родительскому окну, и тогда прямоугольник фокуса должен пропасть со всех дочерних контролов.
    Ответ написан
    1 комментарий