void cb_downloadStart(AuthServer_Private& client) { START_REPLY(e_AuthToCli_FileDownloadChunk); // Trans ID uint32_t transId = DS::CryptRecvValue<uint32_t>(client.m_sock, client.m_crypt); client.m_buffer.write<uint32_t>(transId); // Download filename DS::String filename = DS::CryptRecvString(client.m_sock, client.m_crypt); // Ensure filename is jailed to our data path if (filename.find("..") != -1) { client.m_buffer.write<uint32_t>(DS::e_NetFileNotFound); client.m_buffer.write<uint32_t>(0); // File size client.m_buffer.write<uint32_t>(0); // Chunk offset client.m_buffer.write<uint32_t>(0); // Data packet size SEND_REPLY(); return; } filename.replace("\\", "/"); filename = DS::Settings::AuthRoot() + filename; DS::FileStream* stream = new DS::FileStream(); try { stream->open(filename.c_str(), "rb"); } catch (const DS::FileIOException& ex) { fprintf(stderr, "[Auth] Could not open file %s: %s\n[Auth] Requested by %s\n", filename.c_str(), ex.what(), DS::SockIpAddress(client.m_sock).c_str()); client.m_buffer.write<uint32_t>(DS::e_NetFileNotFound); client.m_buffer.write<uint32_t>(0); // File size client.m_buffer.write<uint32_t>(0); // Chunk offset client.m_buffer.write<uint32_t>(0); // Data packet size SEND_REPLY(); delete stream; return; } client.m_buffer.write<uint32_t>(DS::e_NetSuccess); client.m_buffer.write<uint32_t>(stream->size()); client.m_buffer.write<uint32_t>(stream->tell()); uint8_t data[CHUNK_SIZE]; if (stream->size() > CHUNK_SIZE) { client.m_buffer.write<uint32_t>(CHUNK_SIZE); stream->readBytes(data, CHUNK_SIZE); client.m_buffer.writeBytes(data, CHUNK_SIZE); client.m_downloads[transId] = stream; } else { client.m_buffer.write<uint32_t>(stream->size()); stream->readBytes(data, stream->size()); client.m_buffer.writeBytes(data, stream->size()); delete stream; } SEND_REPLY(); }