PACK *WpcCallEx(char *url, INTERNET_SETTING *setting, UINT timeout_connect, UINT timeout_comm, char *function_name, PACK *pack, X *cert, K *key, void *sha1_cert_hash, bool *cancel, UINT max_recv_size, char *additional_header_name, char *additional_header_value) { URL_DATA data; BUF *b, *recv; UINT error; WPC_PACKET packet; // Validate arguments if (function_name == NULL || pack == NULL) { return PackError(ERR_INTERNAL_ERROR); } if (ParseUrl(&data, url, true, NULL) == false) { return PackError(ERR_INTERNAL_ERROR); } PackAddStr(pack, "function", function_name); b = WpcGeneratePacket(pack, cert, key); if (b == NULL) { return PackError(ERR_INTERNAL_ERROR); } SeekBuf(b, b->Size, 0); WriteBufInt(b, 0); SeekBuf(b, 0, 0); if (IsEmptyStr(additional_header_name) == false && IsEmptyStr(additional_header_value) == false) { StrCpy(data.AdditionalHeaderName, sizeof(data.AdditionalHeaderName), additional_header_name); StrCpy(data.AdditionalHeaderValue, sizeof(data.AdditionalHeaderValue), additional_header_value); } recv = HttpRequestEx(&data, setting, timeout_connect, timeout_comm, &error, false, b->Buf, NULL, NULL, sha1_cert_hash, cancel, max_recv_size); FreeBuf(b); if (recv == NULL) { return PackError(error); } if (WpcParsePacket(&packet, recv) == false) { FreeBuf(recv); return PackError(ERR_PROTOCOL_ERROR); } FreeBuf(recv); FreeX(packet.Cert); return packet.Pack; }
// Parse the data entry LIST *WpcParseDataEntry(BUF *b) { char entry_name[WPC_DATA_ENTRY_SIZE]; char size_str[11]; LIST *o; // Validate arguments if (b == NULL) { return NULL; } SeekBuf(b, 0, 0); o = NewListFast(NULL); while (true) { UINT size; WPC_ENTRY *e; if (ReadBuf(b, entry_name, WPC_DATA_ENTRY_SIZE) != WPC_DATA_ENTRY_SIZE) { break; } Zero(size_str, sizeof(size_str)); if (ReadBuf(b, size_str, 10) != 10) { break; } size = ToInt(size_str); if ((b->Size - b->Current) < size) { break; } e = ZeroMalloc(sizeof(WPC_ENTRY)); e->Data = (UCHAR *)b->Buf + b->Current; Copy(e->EntryName, entry_name, WPC_DATA_ENTRY_SIZE); e->Size = size; SeekBuf(b, size, 1); Add(o, e); } return o; }
// Save the Unicode cache void SaveUnicodeCache(wchar_t *strfilename, UINT strfilesize, UCHAR *hash) { UNICODE_CACHE c; BUF *b; UINT i; IO *io; wchar_t name[MAX_PATH]; UCHAR binhash[MD5_SIZE]; // Validate arguments if (strfilename == NULL || hash == NULL) { return; } Zero(&c, sizeof(c)); UniToStr(c.StrFileName, sizeof(c.StrFileName), strfilename); c.StrFileSize = strfilesize; GetMachineName(c.MachineName, sizeof(c.MachineName)); c.OsType = GetOsInfo()->OsType; Copy(c.hash, hash, MD5_SIZE); #ifdef OS_UNIX GetCurrentCharSet(c.CharSet, sizeof(c.CharSet)); #else // OS_UNIX { UINT id = MsGetThreadLocale(); Copy(c.CharSet, &id, sizeof(id)); } #endif // OS_UNIX b = NewBuf(); WriteBuf(b, &c, sizeof(c)); WriteBufInt(b, LIST_NUM(TableList)); for (i = 0;i < LIST_NUM(TableList);i++) { TABLE *t = LIST_DATA(TableList, i); WriteBufInt(b, StrLen(t->name)); WriteBuf(b, t->name, StrLen(t->name)); WriteBufInt(b, StrLen(t->str)); WriteBuf(b, t->str, StrLen(t->str)); WriteBufInt(b, UniStrLen(t->unistr)); WriteBuf(b, t->unistr, UniStrLen(t->unistr) * sizeof(wchar_t)); } Hash(binhash, b->Buf, b->Size, false); WriteBuf(b, binhash, MD5_SIZE); GenerateUnicodeCacheFileName(name, sizeof(name), strfilename, strfilesize, hash); io = FileCreateW(name); if (io != NULL) { SeekBuf(b, 0, 0); BufToFile(io, b); FileClose(io); } FreeBuf(b); }
// ICMPv6 パケットのオプションのビルド BUF *BuildICMPv6Options(ICMPV6_OPTION_LIST *o) { BUF *b; // 引数チェック if (o == NULL) { return NULL; } b = NewBuf(); if (o->SourceLinkLayer != NULL) { BuildICMPv6OptionValue(b, ICMPV6_OPTION_TYPE_SOURCE_LINK_LAYER, o->SourceLinkLayer, sizeof(ICMPV6_OPTION_LINK_LAYER)); } if (o->TargetLinkLayer != NULL) { BuildICMPv6OptionValue(b, ICMPV6_OPTION_TYPE_TARGET_LINK_LAYER, o->TargetLinkLayer, sizeof(ICMPV6_OPTION_LINK_LAYER)); } if (o->Prefix != NULL) { BuildICMPv6OptionValue(b, ICMPV6_OPTION_TYPE_PREFIX, o->Prefix, sizeof(ICMPV6_OPTION_PREFIX)); } if (o->Mtu != NULL) { BuildICMPv6OptionValue(b, ICMPV6_OPTION_TYPE_MTU, o->Mtu, sizeof(ICMPV6_OPTION_MTU)); } SeekBuf(b, 0, 0); return b; }
// Read an INI file LIST *ReadIni(BUF *b) { LIST *o; // Validate arguments if (b == NULL) { return NULL; } o = NewListFast(NULL); SeekBuf(b, 0, 0); while (true) { char *line = CfgReadNextLine(b); if (line == NULL) { break; } Trim(line); if (IsEmptyStr(line) == false) { if (StartWith(line, "#") == false && StartWith(line, "//") == false && StartWith(line, ";") == false) { char *key, *value; UINT size = StrLen(line) + 1; key = ZeroMalloc(size); value = ZeroMalloc(size); if (GetKeyAndValue(line, key, size, value, size, NULL)) { UINT uni_size; INI_ENTRY *e = ZeroMalloc(sizeof(INI_ENTRY)); e->Key = CopyStr(key); e->Value = CopyStr(value); uni_size = CalcUtf8ToUni((BYTE *)value, StrLen(value)); e->UnicodeValue = ZeroMalloc(uni_size); Utf8ToUni(e->UnicodeValue, uni_size, (BYTE *)value, StrLen(value)); Add(o, e); } Free(key); Free(value); } } Free(line); } return o; }
void CfgTest() { #if 0 FOLDER *root; BUF *b; Debug("\nCFG Test Begin\n"); root = CfgCreateFolder(NULL, TAG_ROOT); CfgTest2(root, 5); b = CfgFolderToBufText(root); //Print("%s\n", b->Buf); SeekBuf(b, 0, 0); CfgDeleteFolder(root); DumpBuf(b, "test1.config"); root = CfgBufTextToFolder(b); FreeBuf(b); b = CfgFolderToBufText(root); // Print("%s\n", b->Buf); DumpBuf(b, "test2.config"); FreeBuf(b); CfgSave(root, "test.txt"); CfgDeleteFolder(root); Debug("\nCFG Test End\n"); #endif }
// 文字列リストを文字列に変換する BUF *StrListToStr(LIST *o) { BUF *b; UINT i; char c; // 引数チェック if (o == NULL) { return NULL; } b = NewBuf(); for (i = 0;i < LIST_NUM(o);i++) { char *s = LIST_DATA(o, i); WriteBuf(b, s, StrLen(s) + 1); } c = 0; WriteBuf(b, &c, 1); SeekBuf(b, 0, 0); return b; }
// Generate the packet BUF *WpcGeneratePacket(PACK *pack, X *cert, K *key) { UCHAR hash[SHA1_SIZE]; BUF *pack_data; BUF *cert_data = NULL; BUF *sign_data = NULL; BUF *b; // Validate arguments if (pack == NULL) { return NULL; } pack_data = PackToBuf(pack); HashSha1(hash, pack_data->Buf, pack_data->Size); if (cert != NULL && key != NULL) { UCHAR sign[128]; cert_data = XToBuf(cert, false); RsaSign(sign, hash, sizeof(hash), key); sign_data = NewBuf(); WriteBuf(sign_data, sign, sizeof(sign)); SeekBuf(sign_data, 0, 0); } b = NewBuf(); WpcAddDataEntryBin(b, "PACK", pack_data->Buf, pack_data->Size); WpcAddDataEntryBin(b, "HASH", hash, sizeof(hash)); if (cert_data != NULL) { WpcAddDataEntryBin(b, "CERT", cert_data->Buf, cert_data->Size); WpcAddDataEntryBin(b, "SIGN", sign_data->Buf, sign_data->Size); } FreeBuf(pack_data); FreeBuf(cert_data); FreeBuf(sign_data); SeekBuf(b, 0, 0); return b; }
// Read the certificate object X *ReadSecCertFromObject(SECURE *sec, SEC_OBJ *obj) { UINT size; X *x; UCHAR value[4096]; BUF *b; CK_ATTRIBUTE get[] = { {CKA_VALUE, value, sizeof(value)}, }; // Validate arguments if (sec == NULL) { return false; } if (sec->SessionCreated == false) { sec->Error = SEC_ERROR_NO_SESSION; return false; } if (sec->LoginFlag == false && obj->Private) { sec->Error = SEC_ERROR_NOT_LOGIN; return false; } if (obj->Type != SEC_X) { sec->Error = SEC_ERROR_BAD_PARAMETER; return false; } // Acquisition if (sec->Api->C_GetAttributeValue( sec->SessionId, obj->Object, get, sizeof(get) / sizeof(get[0])) != CKR_OK) { sec->Error = SEC_ERROR_HARDWARE_ERROR; return 0; } size = A_SIZE(get, 0); // Conversion b = NewBuf(); WriteBuf(b, value, size); SeekBuf(b, 0, 0); x = BufToX(b, false); if (x == NULL) { sec->Error = SEC_ERROR_INVALID_CERT; } FreeBuf(b); return x; }
// Read one line char *CfgReadNextLine(BUF *b) { char *tmp; char *buf; UINT len; // Validate arguments if (b == NULL) { return NULL; } // Examine the number of characters up to the next newline tmp = (char *)b->Buf + b->Current; if ((b->Size - b->Current) == 0) { // Read to the end return NULL; } len = 0; while (true) { if (tmp[len] == 13 || tmp[len] == 10) { if (tmp[len] == 13) { if (len < (b->Size - b->Current)) { len++; } } break; } len++; if (len >= (b->Size - b->Current)) { break; } } // Read ahead only 'len' bytes buf = ZeroMalloc(len + 1); ReadBuf(b, buf, len); SeekBuf(b, 1, 1); if (StrLen(buf) >= 1) { if (buf[StrLen(buf) - 1] == 13) { buf[StrLen(buf) - 1] = 0; } } return buf; }
// Write to the lang.config file bool SaveLangConfig(wchar_t *filename, char *str) { BUF *b; LIST *o; UINT i; bool ret; // Validate arguments if (filename == NULL) { return false; } // Read the template b = ReadDump(LANG_CONFIG_TEMPLETE); if (b == NULL) { return false; } SeekBuf(b, b->Size, 0); o = LoadLangList(); if (o != NULL) { wchar_t tmp[MAX_SIZE]; AppendBufStr(b, "# Available Language IDs are:\r\n"); for (i = 0;i < LIST_NUM(o);i++) { LANGLIST *e = LIST_DATA(o, i); UniFormat(tmp, sizeof(tmp), L"# %S: %s (%s)\r\n", e->Name, e->TitleEnglish, e->TitleLocal); AppendBufUtf8(b, tmp); } AppendBufStr(b, "\r\n\r\n# Specify a Language ID here.\r\n"); AppendBufStr(b, str); AppendBufStr(b, "\r\n\r\n"); FreeLangList(o); } ret = DumpBufW(b, filename); FreeBuf(b); return ret; }
// Extract the resource from the EXE file BUF *ViExtractResource(char *exe, char *type, char *name) { HINSTANCE h; HRSRC hr; HGLOBAL hg; UINT size; void *data; BUF *buf; // Validate arguments if (exe == NULL || type == NULL || name == NULL) { return NULL; } h = LoadLibraryExA(exe, NULL, LOAD_LIBRARY_AS_DATAFILE); if (h == NULL) { return NULL; } hr = FindResourceA(h, name, type); if (hr == NULL) { FreeLibrary(h); return NULL; } hg = LoadResource(h, hr); if (hg == NULL) { FreeLibrary(h); return NULL; } size = SizeofResource(h, hr); data = (void *)LockResource(hg); buf = NewBuf(); WriteBuf(buf, data, size); FreeResource(hg); FreeLibrary(h); SeekBuf(buf, 0, 0); return buf; }
// Get the byte[] type as a BUF BUF *CfgGetBuf(FOLDER *f, char *name) { ITEM *t; BUF *b; // Validate arguments if (f == NULL || name == NULL) { return NULL; } t = CfgFindItem(f, name); if (t == NULL) { return NULL; } b = NewBuf(); WriteBuf(b, t->Buf, t->size); SeekBuf(b, 0, 0); return b; }
// Decode the buffer from WPC_ENTRY BUF *WpcDataEntryToBuf(WPC_ENTRY *e) { void *data; UINT data_size; UINT size; BUF *b; // Validate arguments if (e == NULL) { return NULL; } data_size = e->Size + 4096; data = Malloc(data_size); size = DecodeSafe64(data, e->Data, e->Size); b = NewBuf(); WriteBuf(b, data, size); SeekBuf(b, 0, 0); Free(data); return b; }
bool FileCopyExW(wchar_t *src, wchar_t *dst, bool read_lock) { BUF *b; bool ret = false; // Validate arguments if (src == NULL || dst == NULL) { return false; } b = ReadDumpExW(src, false); if (b == NULL) { return false; } SeekBuf(b, 0, 0); ret = DumpBufW(b, dst); FreeBuf(b); return ret; }
// Copy a file bool FileCopy(char *src, char *dst) { BUF *b; bool ret = false; // Validate arguments if (src == NULL || dst == NULL) { return false; } b = ReadDump(src); if (b == NULL) { return false; } SeekBuf(b, 0, 0); ret = DumpBuf(b, dst); FreeBuf(b); return ret; }
// Attempts Radius authentication (with specifying retry interval and multiple server) bool RadiusLogin(CONNECTION *c, char *server, UINT port, UCHAR *secret, UINT secret_size, wchar_t *username, char *password, UINT interval, UCHAR *mschap_v2_server_response_20) { UCHAR random[MD5_SIZE]; UCHAR id; BUF *encrypted_password = NULL; BUF *user_name = NULL; //IP ip; bool ret = false; TOKEN_LIST *token; UINT i; LIST *ip_list; IPC_MSCHAP_V2_AUTHINFO mschap; bool is_mschap; char client_ip_str[MAX_SIZE]; static UINT packet_id = 0; // Validate arguments if (server == NULL || port == 0 || (secret_size != 0 && secret == NULL) || username == NULL || password == NULL) { return false; } Zero(client_ip_str, sizeof(client_ip_str)); if (c != NULL && c->FirstSock != NULL) { IPToStr(client_ip_str, sizeof(client_ip_str), &c->FirstSock->RemoteIP); } // Parse the MS-CHAP v2 authentication data Zero(&mschap, sizeof(mschap)); is_mschap = ParseAndExtractMsChapV2InfoFromPassword(&mschap, password); // Split the server into tokens token = ParseToken(server, " ,;\t"); // Get the IP address of the server ip_list = NewListFast(NULL); for(i = 0; i < token->NumTokens; i++) { IP *tmp_ip = Malloc(sizeof(IP)); if (GetIP(tmp_ip, token->Token[i])) { Add(ip_list, tmp_ip); } else if (GetIPEx(tmp_ip, token->Token[i], true)) { Add(ip_list, tmp_ip); } else { Free(tmp_ip); } } FreeToken(token); if(LIST_NUM(ip_list) == 0) { ReleaseList(ip_list); return false; } // Random number generation Rand(random, sizeof(random)); // ID generation id = (UCHAR)(packet_id % 254 + 1); packet_id++; if (is_mschap == false) { // Encrypt the password encrypted_password = RadiusEncryptPassword(password, random, secret, secret_size); if (encrypted_password == NULL) { // Encryption failure ReleaseList(ip_list); return false; } } // Generate the user name packet user_name = RadiusCreateUserName(username); if (user_name != NULL) { // Generate a password packet BUF *user_password = (is_mschap ? NULL : RadiusCreateUserPassword(encrypted_password->Buf, encrypted_password->Size)); BUF *nas_id = RadiusCreateNasId(CEDAR_SERVER_STR); if (is_mschap || user_password != NULL) { UINT64 start; UINT64 next_send_time; UCHAR tmp[MAX_SIZE]; UINT recv_buf_size = 32768; UCHAR *recv_buf = MallocEx(recv_buf_size, true); // Generate an UDP packet BUF *p = NewBuf(); UCHAR type = 1; SOCK *sock; USHORT sz = 0; UINT pos = 0; BOOL *finish = ZeroMallocEx(sizeof(BOOL) * LIST_NUM(ip_list), true); Zero(tmp, sizeof(tmp)); WriteBuf(p, &type, 1); WriteBuf(p, &id, 1); WriteBuf(p, &sz, 2); WriteBuf(p, random, 16); WriteBuf(p, user_name->Buf, user_name->Size); if (is_mschap == false) { UINT ui; // PAP WriteBuf(p, user_password->Buf, user_password->Size); WriteBuf(p, nas_id->Buf, nas_id->Size); // Service-Type ui = Endian32(2); RadiusAddValue(p, 6, 0, 0, &ui, sizeof(ui)); // NAS-Port-Type ui = Endian32(5); RadiusAddValue(p, 61, 0, 0, &ui, sizeof(ui)); // Tunnel-Type ui = Endian32(1); RadiusAddValue(p, 64, 0, 0, &ui, sizeof(ui)); // Tunnel-Medium-Type ui = Endian32(1); RadiusAddValue(p, 65, 0, 0, &ui, sizeof(ui)); // Calling-Station-Id RadiusAddValue(p, 31, 0, 0, client_ip_str, StrLen(client_ip_str)); // Tunnel-Client-Endpoint RadiusAddValue(p, 66, 0, 0, client_ip_str, StrLen(client_ip_str)); } else { // MS-CHAP v2 static UINT session_id = 0; USHORT us; UINT ui; char *ms_ras_version = "MSRASV5.20"; UCHAR ms_chapv2_response[50]; // Acct-Session-Id us = Endian16(session_id % 254 + 1); session_id++; RadiusAddValue(p, 44, 0, 0, &us, sizeof(us)); // NAS-IP-Address if (c != NULL && c->FirstSock != NULL && c->FirstSock->IPv6 == false) { ui = IPToUINT(&c->FirstSock->LocalIP); RadiusAddValue(p, 4, 0, 0, &ui, sizeof(ui)); } // Service-Type ui = Endian32(2); RadiusAddValue(p, 6, 0, 0, &ui, sizeof(ui)); // MS-RAS-Vendor ui = Endian32(311); RadiusAddValue(p, 26, 311, 9, &ui, sizeof(ui)); // MS-RAS-Version RadiusAddValue(p, 26, 311, 18, ms_ras_version, StrLen(ms_ras_version)); // NAS-Port-Type ui = Endian32(5); RadiusAddValue(p, 61, 0, 0, &ui, sizeof(ui)); // Tunnel-Type ui = Endian32(1); RadiusAddValue(p, 64, 0, 0, &ui, sizeof(ui)); // Tunnel-Medium-Type ui = Endian32(1); RadiusAddValue(p, 65, 0, 0, &ui, sizeof(ui)); // Calling-Station-Id RadiusAddValue(p, 31, 0, 0, client_ip_str, StrLen(client_ip_str)); // Tunnel-Client-Endpoint RadiusAddValue(p, 66, 0, 0, client_ip_str, StrLen(client_ip_str)); // MS-RAS-Client-Version RadiusAddValue(p, 26, 311, 35, ms_ras_version, StrLen(ms_ras_version)); // MS-RAS-Client-Name RadiusAddValue(p, 26, 311, 34, client_ip_str, StrLen(client_ip_str)); // MS-CHAP-Challenge RadiusAddValue(p, 26, 311, 11, mschap.MsChapV2_ServerChallenge, sizeof(mschap.MsChapV2_ServerChallenge)); // MS-CHAP2-Response Zero(ms_chapv2_response, sizeof(ms_chapv2_response)); Copy(ms_chapv2_response + 2, mschap.MsChapV2_ClientChallenge, 16); Copy(ms_chapv2_response + 2 + 16 + 8, mschap.MsChapV2_ClientResponse, 24); RadiusAddValue(p, 26, 311, 25, ms_chapv2_response, sizeof(ms_chapv2_response)); // NAS-ID WriteBuf(p, nas_id->Buf, nas_id->Size); } SeekBuf(p, 0, 0); WRITE_USHORT(((UCHAR *)p->Buf) + 2, (USHORT)p->Size); // Create a socket sock = NewUDPEx(0, IsIP6(LIST_DATA(ip_list, pos))); // Transmission process start start = Tick64(); if(interval < RADIUS_RETRY_INTERVAL) { interval = RADIUS_RETRY_INTERVAL; } else if(interval > RADIUS_RETRY_TIMEOUT) { interval = RADIUS_RETRY_TIMEOUT; } next_send_time = start + (UINT64)interval; while (true) { UINT server_port; UINT recv_size; //IP server_ip; SOCKSET set; UINT64 now; SEND_RETRY: //SendTo(sock, &ip, port, p->Buf, p->Size); SendTo(sock, LIST_DATA(ip_list, pos), port, p->Buf, p->Size); Debug("send to host:%u\n", pos); next_send_time = Tick64() + (UINT64)interval; RECV_RETRY: now = Tick64(); if (next_send_time <= now) { // Switch the host to refer pos++; pos = pos % LIST_NUM(ip_list); goto SEND_RETRY; } if ((start + RADIUS_RETRY_TIMEOUT) < now) { // Time-out break; } InitSockSet(&set); AddSockSet(&set, sock); Select(&set, (UINT)(next_send_time - now), NULL, NULL); recv_size = RecvFrom(sock, LIST_DATA(ip_list, pos), &server_port, recv_buf, recv_buf_size); if (recv_size == 0) { Debug("Radius recv_size 0\n"); finish[pos] = TRUE; for(i = 0; i < LIST_NUM(ip_list); i++) { if(finish[i] == FALSE) { // Switch the host to refer pos++; pos = pos % LIST_NUM(ip_list); goto SEND_RETRY; } } // Failure break; } else if (recv_size == SOCK_LATER) { // Waiting goto RECV_RETRY; } else { // Check such as the IP address if (/*Cmp(&server_ip, &ip, sizeof(IP)) != 0 || */server_port != port) { goto RECV_RETRY; } // Success if (recv_buf[0] == 2) { ret = true; if (is_mschap && mschap_v2_server_response_20 != NULL) { // Cutting corners Zurukko UCHAR signature[] = {0x1A, 0x33, 0x00, 0x00, 0x01, 0x37, 0x1A, 0x2D, 0x00, 0x53, 0x3D, }; UINT i = SearchBin(recv_buf, 0, recv_buf_size, signature, sizeof(signature)); if (i == INFINITE || ((i + sizeof(signature) + 40) > recv_buf_size)) { ret = false; } else { char tmp[MAX_SIZE]; BUF *b; Zero(tmp, sizeof(tmp)); Copy(tmp, recv_buf + i + sizeof(signature), 40); b = StrToBin(tmp); if (b != NULL && b->Size == 20) { WHERE; Copy(mschap_v2_server_response_20, b->Buf, 20); } else { WHERE; ret = false; } FreeBuf(b); } } } break; } } Free(finish); // Release the socket ReleaseSock(sock); FreeBuf(p); FreeBuf(user_password); Free(recv_buf); } FreeBuf(nas_id); FreeBuf(user_name); } // Release the ip_list for(i = 0; i < LIST_NUM(ip_list); i++) { IP *tmp_ip = LIST_DATA(ip_list, i); Free(tmp_ip); } ReleaseList(ip_list); // Release the memory FreeBuf(encrypted_password); return ret; }
// Read the inf file from the buffer bool ViLoadInfFromBuf(VI_SETTING *set, BUF *buf) { bool ret; if (set == NULL || buf == NULL) { return false; } Zero(set, sizeof(VI_SETTING)); SeekBuf(buf, 0, 0); while (true) { char *tmp = CfgReadNextLine(buf); TOKEN_LIST *tokens; if (tmp == NULL) { break; } tokens = ParseToken(tmp, " \t"); if (tokens != NULL) { if (tokens->NumTokens >= 2) { if (StartWith(tokens->Token[0], "#") == false || StartWith(tokens->Token[0], "//") == false) { char *name, *value; name = tokens->Token[0]; value = tokens->Token[1]; if (StrCmpi(name, "VpnInstallBuild") == 0) { set->VpnInstallBuild = ToInt(value); } else if (StrCmpi(name, "NormalMode") == 0) { set->NormalMode = ToBool(value); } else if (StrCmpi(name, "VpnSettingPath") == 0) { StrCpy(set->SettingPath, sizeof(set->SettingPath), value); } else if (StrCmpi(name, "VpnClientBuild") == 0) { set->x86.Build = ToInt(value); } else if (StrCmpi(name, "VpnClientPath") == 0) { StrCpy(set->x86.Path, sizeof(set->x86.Path), value); } } } FreeToken(tokens); } Free(tmp); } ret = false; StrCpy(set->x86.VpnCMgrExeFileName, sizeof(set->x86.VpnCMgrExeFileName), (MsIsX64() ? "vpncmgr_x64.exe" : "vpncmgr.exe")); if (set->VpnInstallBuild != 0) { if (set->x86.Build != 0 && IsEmptyStr(set->x86.Path) == false) { set->x86.Supported = true; ret = true; } } return ret; }
// // Get a remote file, calling the update function after each block arrives // Returns the total bytes received. // fi_errno MUST be checked for errors // Returns -2 for AmigaDos errors - Use IoErr() to report/handle them // Returns -3 for FTP server errors - Use the fi_reply and fi_iobuf fields to report/handle them // Returns -1 for rare unlikely errors - Could cause DisplayBeep() etc... // now uses IOBUFSIZE // // Update callback must specify 0xffffffff for total and length if REST fails // Update callback must specify 0xffffffff for unknown total // Update callback must specify 0 for length of final call // unsigned int get( struct ftp_info *info, int (*updatefn)(void *,unsigned int,unsigned int), void *updateinfo, char *remote_path, char *local_path, BOOL restart ) { // Needed because socket library base is in our task's tc_userdata field //struct opusftp_globals *ogp = info->fi_og; unsigned int total = 0xffffffff; // Length of file unsigned int bytes = 0; // Bytes received so far APTR f; // Output file int ds; // Data socket int b; // Byte count int reply; // FTP reply fd_set rd, ex; ULONG flags; struct timeval timer = {0}; int display_bytes; int done; D(bug( "get() '%s' -> '%s'\n", remote_path, local_path )); // Valid? if (!info) return 0; // No abort/error yet info->fi_aborted = 0; info->fi_errno = 0; info->fi_ioerr = 0; *info->fi_serverr = 0; // More validity if (!remote_path || !local_path) { info->fi_errno |= FTPERR_XFER_RARERR; return 0; } // init counters etc display_bytes = done = 0; // open output file for writing if ((f = OpenBuf( (char *)local_path, restart ? MODE_OLDFILE : MODE_NEWFILE, WBUFSIZE ))) { // Resuming? So find out where to resume from if (restart) { SeekBuf( f, 0, OFFSET_END ); bytes = SeekBuf( f, 0, OFFSET_CURRENT ); } // get connected - bytes is a market flag 0/x for RETR/REST if ((ds = dataconna( info, bytes, "RETR %s", remote_path )) < 0) { // Source (server error)? if (ds == -2 || ds == -3) { info->fi_errno |= FTPERR_XFER_SRCERR; stccpy( info->fi_serverr, info->fi_iobuf, IOBUFSIZE + 1 ); } else info->fi_errno |= FTPERR_XFER_RARERR; } else { char *p; // Reset bytes if REST failed if (bytes && (info->fi_flags & FTP_NO_REST)) { if (updatefn) (*updatefn)( updateinfo, 0xffffffff, 0xffffffff ); SeekBuf( f, 0, OFFSET_BEGINNING ); bytes = 0; } // First update tells callback where we're starting from if (updatefn) (*updatefn)( updateinfo, total, bytes ); // Does the RETR reply contain the file length? if ((p = strstr( info->fi_iobuf, " bytes)" ))) if (isdigit(*--p)) { while (isdigit(*p--)) ; total = atoi(p+2); } // do the transfer FD_ZERO( &rd ); FD_ZERO( &ex ); // set network timeout for the select wait call set_timeout(info,&timer); // loop fetch tcp data and save it while (!done) { // Note: these masks must be set before every call and // are all cleared by select wait. Examine the masks // afterwards to see what was set FD_SET( ds, &rd ); FD_SET( ds, &ex ); flags = SIGBREAKF_CTRL_D; if (WaitSelect( ds + 1 , &rd, NULL, &ex, &timer, &flags ) >= 0) { // Is there some data ready for us? if (FD_ISSET( ds, &rd )) { // then get it and store it if ((b = recv( ds, info->fi_iobuf, IOBUFSIZE, 0 ))) { // save data if (WriteBuf( f, info->fi_iobuf, b ) == b) { bytes += b; // progress bar uprate display_bytes += b; if (display_bytes >= UPDATE_BYTE_LIMIT) { if (updatefn) (*updatefn)( updateinfo, total, display_bytes ); display_bytes = 0; } } // Write Error else { info->fi_errno |= FTPERR_XFER_DSTERR; info->fi_ioerr = IoErr(); info->fi_aborted = 1; ftp_abor( info ); done = TRUE; } } else done = TRUE; } // did we get a signal to abort? if (!done && (flags & SIGBREAKF_CTRL_D)) { D(bug( "*** get() CTRL-D SIGNAL ***\n" )); info->fi_abortsignals = 0; info->fi_aborted = 1; ftp_abor( info ); // NEEDED why not just close socket? done = TRUE; } // did we get an exception? Other end closed connection maybe if (FD_ISSET( ds, &ex )) { D(bug("** get() socket exception\n")); // has been aborted from remote ? done = TRUE; } } else { // some socket error -ve a 0 == timeout D(bug( "** get() WaitSelect error\n" )); done = TRUE; } } // Final progress bar redraw at 100% (if it finished) if (!info->fi_aborted && !info->fi_errno && updatefn) (*updatefn)( updateinfo, total, 0 ); //D(bug( "--> close(%ld)\n", ds )); CloseSocket( ds ); #ifdef DEBUG // if (ui) // timeit( ui, bytes ); #endif // Get reply to socket closure Can TIMEOUT reply = getreply( info ); // If transfer was aborted, read the ABOR reply (426) // (This could get the reply to RETR (226) but it don't matter) if (info->fi_aborted && reply != 421) reply = getreply( info ); // RETR successful? - Don't set error if we forced it! // (This could get the reply to ABOR (225) but it don't matter) if (reply / 100 != COMPLETE) if (!info->fi_errno) { info->fi_errno |= FTPERR_XFER_SRCERR; stccpy( info->fi_serverr, info->fi_iobuf, IOBUFSIZE + 1 ); } } CloseBuf( f ); // Delete empty files if there was an error and we created it if (info->fi_errno && bytes == 0 && !restart) DeleteFile( (char *)local_path ); } else { info->fi_errno |= FTPERR_XFER_DSTERR; info->fi_ioerr = IoErr(); } return bytes; }
FOLDER *CfgReadW(wchar_t *name) { wchar_t tmp[MAX_SIZE]; wchar_t newfile[MAX_SIZE]; BUF *b; IO *o; UINT size; void *buf; FOLDER *f; bool delete_new = false; bool binary_file = false; bool invalid_file = false; UCHAR header[8]; // Validate arguments if (name == NULL) { return NULL; } // Generate a new file name UniFormat(newfile, sizeof(newfile), L"%s.new", name); // Generate a temporary file name UniFormat(tmp, sizeof(tmp), L"%s.log", name); // Read the new file if it exists o = FileOpenW(newfile, false); if (o == NULL) { // Read the temporary file o = FileOpenW(tmp, false); } else { delete_new = true; } if (o == NULL) { // Read the original file if there is no temporary file o = FileOpenW(name, false); } else { // Read the original file too if the size of temporary file is 0 if (FileSize(o) == 0) { invalid_file = true; } if (invalid_file) { FileClose(o); o = FileOpenW(name, false); } } if (o == NULL) { // Failed to read return NULL; } // Read into the buffer size = FileSize(o); buf = Malloc(size); FileRead(o, buf, size); b = NewBuf(); WriteBuf(b, buf, size); SeekBuf(b, 0, 0); // Close the file FileClose(o); if (delete_new) { // Delete the new file FileDeleteW(newfile); } // If the beginning 8 character of the buffer is "SEVPN_DB", it is binary file ReadBuf(b, header, sizeof(header)); if (Cmp(header, TAG_BINARY, 8) == 0) { UCHAR hash1[SHA1_SIZE], hash2[SHA1_SIZE]; binary_file = true; // Check the hash ReadBuf(b, hash1, sizeof(hash1)); Hash(hash2, ((UCHAR *)b->Buf) + 8 + SHA1_SIZE, b->Size - 8 - SHA1_SIZE, true); if (Cmp(hash1, hash2, SHA1_SIZE) != 0) { // Corrupted file invalid_file = true; FreeBuf(b); return NULL; } } SeekBuf(b, 0, 0); if (binary_file) { SeekBuf(b, 8 + SHA1_SIZE, 0); } // Convert the buffer into a folder if (binary_file == false) { // Text mode f = CfgBufTextToFolder(b); } else { // Binary mode f = CfgBufBinToFolder(b); } // Memory release Free(buf); FreeBuf(b); FileDeleteW(newfile); return f; }
// Reading the Unicode cache bool LoadUnicodeCache(wchar_t *strfilename, UINT strfilesize, UCHAR *hash) { UNICODE_CACHE c, t; BUF *b; UINT i, num; IO *io; wchar_t name[MAX_PATH]; UCHAR binhash[MD5_SIZE]; UCHAR binhash_2[MD5_SIZE]; // Validate arguments if (strfilename == NULL || hash == NULL) { return false; } GenerateUnicodeCacheFileName(name, sizeof(name), strfilename, strfilesize, hash); io = FileOpenW(name, false); if (io == NULL) { return false; } b = FileToBuf(io); if (b == NULL) { FileClose(io); return false; } SeekBuf(b, 0, 0); FileClose(io); Hash(binhash, b->Buf, b->Size >= MD5_SIZE ? (b->Size - MD5_SIZE) : 0, false); Copy(binhash_2, ((UCHAR *)b->Buf) + (b->Size >= MD5_SIZE ? (b->Size - MD5_SIZE) : 0), MD5_SIZE); if (Cmp(binhash, binhash_2, MD5_SIZE) != 0) { FreeBuf(b); return false; } Zero(&c, sizeof(c)); UniToStr(c.StrFileName, sizeof(c.StrFileName), strfilename); c.StrFileSize = strfilesize; DisableNetworkNameCache(); GetMachineName(c.MachineName, sizeof(c.MachineName)); EnableNetworkNameCache(); c.OsType = GetOsInfo()->OsType; Copy(c.hash, hash, MD5_SIZE); #ifdef OS_UNIX GetCurrentCharSet(c.CharSet, sizeof(c.CharSet)); #else // OS_UNIX { UINT id = MsGetThreadLocale(); Copy(c.CharSet, &id, sizeof(id)); } #endif // OS_UNIX Zero(&t, sizeof(t)); ReadBuf(b, &t, sizeof(t)); if (Cmp(&c, &t, sizeof(UNICODE_CACHE)) != 0) { FreeBuf(b); return false; } num = ReadBufInt(b); FreeTable(); TableList = NewList(CmpTableName); for (i = 0;i < num;i++) { UINT len; TABLE *t = ZeroMalloc(sizeof(TABLE)); len = ReadBufInt(b); t->name = ZeroMalloc(len + 1); ReadBuf(b, t->name, len); len = ReadBufInt(b); t->str = ZeroMalloc(len + 1); ReadBuf(b, t->str, len); len = ReadBufInt(b); t->unistr = ZeroMalloc((len + 1) * sizeof(wchar_t)); ReadBuf(b, t->unistr, len * sizeof(wchar_t)); Add(TableList, t); } FreeBuf(b); Sort(TableList); return true; }
BUF *HttpRequestEx2(URL_DATA *data, INTERNET_SETTING *setting, UINT timeout_connect, UINT timeout_comm, UINT *error_code, bool check_ssl_trust, char *post_data, WPC_RECV_CALLBACK *recv_callback, void *recv_callback_param, void *sha1_cert_hash, bool *cancel, UINT max_recv_size, char *header_name, char *header_value) { WPC_CONNECT con; SOCK *s; HTTP_HEADER *h; bool use_http_proxy = false; char target[MAX_SIZE * 4]; char *send_str; BUF *send_buf; BUF *recv_buf; UINT http_error_code; char len_str[100]; UINT content_len; void *socket_buffer; UINT socket_buffer_size = WPC_RECV_BUF_SIZE; UINT num_continue = 0; INTERNET_SETTING wt_setting; // Validate arguments if (data == NULL) { return NULL; } if (setting == NULL) { Zero(&wt_setting, sizeof(wt_setting)); setting = &wt_setting; } if (error_code == NULL) { static UINT ret = 0; error_code = &ret; } if (timeout_comm == 0) { timeout_comm = WPC_TIMEOUT; } // Connection Zero(&con, sizeof(con)); StrCpy(con.HostName, sizeof(con.HostName), data->HostName); con.Port = data->Port; con.ProxyType = setting->ProxyType; StrCpy(con.ProxyHostName, sizeof(con.ProxyHostName), setting->ProxyHostName); con.ProxyPort = setting->ProxyPort; StrCpy(con.ProxyUsername, sizeof(con.ProxyUsername), setting->ProxyUsername); StrCpy(con.ProxyPassword, sizeof(con.ProxyPassword), setting->ProxyPassword); if (setting->ProxyType != PROXY_HTTP || data->Secure) { use_http_proxy = false; StrCpy(target, sizeof(target), data->Target); } else { use_http_proxy = true; CreateUrl(target, sizeof(target), data); } if (use_http_proxy == false) { // If the connection is not via HTTP Proxy, or is a SSL connection even via HTTP Proxy s = WpcSockConnectEx(&con, error_code, timeout_connect, cancel); } else { // If the connection is not SSL via HTTP Proxy s = TcpConnectEx3(con.ProxyHostName, con.ProxyPort, timeout_connect, cancel, NULL, true, NULL, false, false, NULL); if (s == NULL) { *error_code = ERR_PROXY_CONNECT_FAILED; } } if (s == NULL) { return NULL; } if (data->Secure) { // Start the SSL communication if (StartSSLEx(s, NULL, NULL, true, 0, NULL) == false) { // SSL connection failed *error_code = ERR_PROTOCOL_ERROR; Disconnect(s); ReleaseSock(s); return NULL; } if (sha1_cert_hash != NULL) { UCHAR hash[SHA1_SIZE]; Zero(hash, sizeof(hash)); GetXDigest(s->RemoteX, hash, true); if (Cmp(hash, sha1_cert_hash, SHA1_SIZE) != 0) { // Destination certificate hash mismatch *error_code = ERR_CERT_NOT_TRUSTED; Disconnect(s); ReleaseSock(s); return NULL; } } } // Timeout setting SetTimeout(s, timeout_comm); // Generate a request h = NewHttpHeader(data->Method, target, use_http_proxy ? "HTTP/1.0" : "HTTP/1.1"); AddHttpValue(h, NewHttpValue("Keep-Alive", HTTP_KEEP_ALIVE)); AddHttpValue(h, NewHttpValue("Connection", "Keep-Alive")); AddHttpValue(h, NewHttpValue("Accept-Language", "ja")); AddHttpValue(h, NewHttpValue("User-Agent", WPC_USER_AGENT)); AddHttpValue(h, NewHttpValue("Pragma", "no-cache")); AddHttpValue(h, NewHttpValue("Cache-Control", "no-cache")); AddHttpValue(h, NewHttpValue("Host", data->HeaderHostName)); if (IsEmptyStr(header_name) == false && IsEmptyStr(header_value) == false) { AddHttpValue(h, NewHttpValue(header_name, header_value)); } if (IsEmptyStr(data->Referer) == false) { AddHttpValue(h, NewHttpValue("Referer", data->Referer)); } if (StrCmpi(data->Method, WPC_HTTP_POST_NAME) == 0) { ToStr(len_str, StrLen(post_data)); AddHttpValue(h, NewHttpValue("Content-Type", "application/x-www-form-urlencoded")); AddHttpValue(h, NewHttpValue("Content-Length", len_str)); } if (IsEmptyStr(data->AdditionalHeaderName) == false && IsEmptyStr(data->AdditionalHeaderValue) == false) { AddHttpValue(h, NewHttpValue(data->AdditionalHeaderName, data->AdditionalHeaderValue)); } if (use_http_proxy) { AddHttpValue(h, NewHttpValue("Proxy-Connection", "Keep-Alive")); if (IsEmptyStr(setting->ProxyUsername) == false || IsEmptyStr(setting->ProxyPassword) == false) { char auth_tmp_str[MAX_SIZE], auth_b64_str[MAX_SIZE * 2]; char basic_str[MAX_SIZE * 2]; // Generate the authentication string Format(auth_tmp_str, sizeof(auth_tmp_str), "%s:%s", setting->ProxyUsername, setting->ProxyPassword); // Base64 encode Zero(auth_b64_str, sizeof(auth_b64_str)); Encode64(auth_b64_str, auth_tmp_str); Format(basic_str, sizeof(basic_str), "Basic %s", auth_b64_str); AddHttpValue(h, NewHttpValue("Proxy-Authorization", basic_str)); } } send_str = HttpHeaderToStr(h); FreeHttpHeader(h); send_buf = NewBuf(); WriteBuf(send_buf, send_str, StrLen(send_str)); Free(send_str); // Append to the sending data in the case of POST if (StrCmpi(data->Method, WPC_HTTP_POST_NAME) == 0) { WriteBuf(send_buf, post_data, StrLen(post_data)); } // Send if (SendAll(s, send_buf->Buf, send_buf->Size, s->SecureMode) == false) { Disconnect(s); ReleaseSock(s); FreeBuf(send_buf); *error_code = ERR_DISCONNECTED; return NULL; } FreeBuf(send_buf); CONT: // Receive h = RecvHttpHeader(s); if (h == NULL) { Disconnect(s); ReleaseSock(s); *error_code = ERR_DISCONNECTED; return NULL; } http_error_code = 0; if (StrLen(h->Method) == 8) { if (Cmp(h->Method, "HTTP/1.", 7) == 0) { http_error_code = ToInt(h->Target); } } *error_code = ERR_NO_ERROR; switch (http_error_code) { case 401: case 407: // Proxy authentication error *error_code = ERR_PROXY_AUTH_FAILED; break; case 404: // 404 File Not Found *error_code = ERR_OBJECT_NOT_FOUND; break; case 100: // Continue num_continue++; if (num_continue >= 10) { goto DEF; } FreeHttpHeader(h); goto CONT; case 200: // Success break; default: // Protocol error DEF: *error_code = ERR_PROTOCOL_ERROR; break; } if (*error_code != ERR_NO_ERROR) { // An error has occured Disconnect(s); ReleaseSock(s); FreeHttpHeader(h); return NULL; } // Get the length of the content content_len = GetContentLength(h); if (max_recv_size != 0) { content_len = MIN(content_len, max_recv_size); } FreeHttpHeader(h); socket_buffer = Malloc(socket_buffer_size); // Receive the content recv_buf = NewBuf(); while (true) { UINT recvsize = MIN(socket_buffer_size, content_len - recv_buf->Size); UINT size; if (recv_callback != NULL) { if (recv_callback(recv_callback_param, content_len, recv_buf->Size, recv_buf) == false) { // Cancel the reception *error_code = ERR_USER_CANCEL; goto RECV_CANCEL; } } if (recvsize == 0) { break; } size = Recv(s, socket_buffer, recvsize, s->SecureMode); if (size == 0) { // Disconnected *error_code = ERR_DISCONNECTED; RECV_CANCEL: FreeBuf(recv_buf); Free(socket_buffer); Disconnect(s); ReleaseSock(s); return NULL; } WriteBuf(recv_buf, socket_buffer, size); } SeekBuf(recv_buf, 0, 0); Free(socket_buffer); Disconnect(s); ReleaseSock(s); // Transmission return recv_buf; }
// RPC internal call PACK *RpcCallInternal(RPC *r, PACK *p) { BUF *b; UINT size; PACK *ret; void *tmp; // Validate arguments if (r == NULL || p == NULL) { return NULL; } if (r->Sock == NULL) { return NULL; } b = PackToBuf(p); size = Endian32(b->Size); SendAdd(r->Sock, &size, sizeof(UINT)); SendAdd(r->Sock, b->Buf, b->Size); FreeBuf(b); if (SendNow(r->Sock, r->Sock->SecureMode) == false) { return NULL; } if (RecvAll(r->Sock, &size, sizeof(UINT), r->Sock->SecureMode) == false) { return NULL; } size = Endian32(size); if (size > MAX_PACK_SIZE) { return NULL; } tmp = MallocEx(size, true); if (RecvAll(r->Sock, tmp, size, r->Sock->SecureMode) == false) { Free(tmp); return NULL; } b = NewBuf(); WriteBuf(b, tmp, size); SeekBuf(b, 0, 0); Free(tmp); ret = BufToPack(b); if (ret == NULL) { FreeBuf(b); return NULL; } FreeBuf(b); return ret; }
// Wait for the next RPC call bool RpcRecvNextCall(RPC *r) { UINT size; void *tmp; SOCK *s; BUF *b; PACK *p; PACK *ret; // Validate arguments if (r == NULL) { return false; } s = r->Sock; if (RecvAll(s, &size, sizeof(UINT), s->SecureMode) == false) { return false; } size = Endian32(size); if (size > MAX_PACK_SIZE) { return false; } tmp = MallocEx(size, true); if (RecvAll(s, tmp, size, s->SecureMode) == false) { Free(tmp); return false; } b = NewBuf(); WriteBuf(b, tmp, size); SeekBuf(b, 0, 0); Free(tmp); p = BufToPack(b); FreeBuf(b); if (p == NULL) { return false; } ret = CallRpcDispatcher(r, p); FreePack(p); if (ret == NULL) { ret = PackError(ERR_NOT_SUPPORTED); } b = PackToBuf(ret); FreePack(ret); size = Endian32(b->Size); SendAdd(s, &size, sizeof(UINT)); SendAdd(s, b->Buf, b->Size); if (SendNow(s, s->SecureMode) == false) { FreeBuf(b); return false; } FreeBuf(b); return true; }
unsigned int put( struct ftp_info *info, int (*updatefn)(void *,unsigned int,unsigned int), void *updateinfo, char *local_path, char *remote_path, unsigned int restart ) { //struct opusftp_globals *ogp = info->fi_og; unsigned int bytes = 0; APTR f; // Output file int ds; // Data socket int b; // Byte count fd_set wd, ex; ULONG flags = SIGBREAKF_CTRL_D; struct timeval timer = {0}; BOOL done = FALSE; int display_bytes = 0; // Valid? if (!info) return 0; // No abort/error yet info->fi_aborted = 0; info->fi_errno = 0; info->fi_ioerr = 0; *info->fi_serverr = 0; // More validity if (!remote_path || !local_path) { info->fi_errno |= FTPERR_XFER_RARERR; return 0; } if ((f = OpenBuf( (char *)local_path, MODE_OLDFILE, WBUFSIZE ))) { // Can TIMEOUT if ((ds = dataconna( info, restart, "STOR %s", remote_path )) < 0) { // Destination (server) error? if (ds == -2 || ds == -3) { info->fi_errno |= FTPERR_XFER_DSTERR; stccpy( info->fi_serverr, info->fi_iobuf, IOBUFSIZE + 1 ); } else info->fi_errno |= FTPERR_XFER_RARERR; } else { // Resuming a transfer? if (restart) { // Start at 0 if REST failed if (info->fi_flags & FTP_NO_REST) { if (updatefn) (*updatefn)( updateinfo, 0xffffffff, 0xffffffff ); bytes = restart = 0; } // Otherwise seek to restart position else { SeekBuf( f, restart, OFFSET_BEGINNING ); bytes = restart; } } // First update tells callback where we're starting from if (updatefn) (*updatefn)( updateinfo, 0xffffffff, bytes ); // Transfer FD_ZERO( &wd ); FD_ZERO( &ex ); // set network timeout for the select wait call set_timeout(info,&timer); while (!done) { // Note: these masks must be set before every call and // are all cleared by select wait. Examine the masks // afterwards to see what was set FD_SET( ds, &wd ); FD_SET( ds, &ex ); flags = SIGBREAKF_CTRL_D; if (WaitSelect(ds+1, 0L, &wd, &ex, &timer, &flags ) >= 0) { if (FD_ISSET( ds, &wd )) { if ((b = ReadBuf( f, info->fi_iobuf, IOBUFSIZE )) > 0) { send( ds, info->fi_iobuf, b, 0 ); bytes += b; if ((display_bytes += b) >= UPDATE_BYTE_LIMIT || bytes < UPDATE_BYTE_LIMIT) { if (updatefn) (*updatefn)( updateinfo, 0xffffffff, display_bytes ); display_bytes = 0; } } else { done = TRUE; if (b < 0) { info->fi_errno |= FTPERR_XFER_SRCERR; info->fi_ioerr = IoErr(); } } } if (!done && (flags & SIGBREAKF_CTRL_D)) { D(bug( "*** put() CTRL-D SIGNAL ***\n" )); info->fi_abortsignals = 0; info->fi_aborted = TRUE; done = TRUE; } if (FD_ISSET( ds, &ex )) { D(bug( "** put() socket exception\n" )); info->fi_abortsignals = 0; done = TRUE; } } else { // some socket error -ve a 0== timeout D(bug("** put() WaitSelect error\n")); done = TRUE; } } // Final progress bar redraw at 100% (if it finished) if (!info->fi_aborted && !info->fi_errno && updatefn) (*updatefn)( updateinfo, 0xffffffff, 0 ); // Close data socket //D(bug( "--> close(%ld)\n", ds )); CloseSocket( ds ); // Get reply to socket closure - Can TIMEOUT if (getreply( info ) / 100 != COMPLETE) { info->fi_errno |= FTPERR_XFER_DSTERR; stccpy( info->fi_serverr, info->fi_iobuf, IOBUFSIZE + 1 ); } } CloseBuf( f ); } else { info->fi_errno |= FTPERR_XFER_SRCERR; info->fi_ioerr = IoErr(); } return bytes; }
// IPv6 パケットヘッダ部のビルド BUF *BuildIPv6PacketHeader(IPV6_HEADER_PACKET_INFO *info, UINT *bytes_before_payload) { BUF *b; QUEUE *q; UINT bbp = 0; // 引数チェック if (info == NULL) { return NULL; } b = NewBuf(); q = NewQueueFast(); // オプションヘッダの一覧を作成 if (info->HopHeader != NULL) { InsertQueueInt(q, IPV6_HEADER_HOP); } if (info->EndPointHeader != NULL) { InsertQueueInt(q, IPV6_HEADER_ENDPOINT); } if (info->RoutingHeader != NULL) { InsertQueueInt(q, IPV6_HEADER_ROUTING); } if (info->FragmentHeader != NULL) { InsertQueueInt(q, IPV6_HEADER_FRAGMENT); } InsertQueueInt(q, info->Protocol); // IPv6 ヘッダ info->IPv6Header->NextHeader = IPv6GetNextHeaderFromQueue(q); WriteBuf(b, info->IPv6Header, sizeof(IPV6_HEADER)); // ホップバイホップオプションヘッダ if (info->HopHeader != NULL) { BuildAndAddIPv6PacketOptionHeader(b, info->HopHeader, IPv6GetNextHeaderFromQueue(q), info->HopHeaderSize); } // 終点オプションヘッダ if (info->EndPointHeader != NULL) { BuildAndAddIPv6PacketOptionHeader(b, info->EndPointHeader, IPv6GetNextHeaderFromQueue(q), info->EndPointHeaderSize); } // ルーティングヘッダ if (info->RoutingHeader != NULL) { BuildAndAddIPv6PacketOptionHeader(b, info->RoutingHeader, IPv6GetNextHeaderFromQueue(q), info->RoutingHeaderSize); } // フラグメントヘッダ if (info->FragmentHeader != NULL) { info->FragmentHeader->NextHeader = IPv6GetNextHeaderFromQueue(q); WriteBuf(b, info->FragmentHeader, sizeof(IPV6_FRAGMENT_HEADER)); } bbp = b->Size; if (info->FragmentHeader == NULL) { bbp += sizeof(IPV6_FRAGMENT_HEADER); } // ペイロード if (info->Protocol != IPV6_HEADER_NONE) { WriteBuf(b, info->Payload, info->PayloadSize); } ReleaseQueue(q); SeekBuf(b, 0, 0); // ペイロード長さ ((IPV6_HEADER *)b->Buf)->PayloadLength = Endian16(b->Size - (USHORT)sizeof(IPV6_HEADER)); if (bytes_before_payload != NULL) { // ペイロードの直前までの長さ (ただしフラグメントヘッダは必ず含まれると仮定) // を計算する *bytes_before_payload = bbp; } return b; }
// Search a file (either on disk or in memory) int search_file( APTR file, UBYTE *search_text, ULONG flags, UBYTE *buffer, ULONG buffer_size) { UBYTE match_text[256]; long match_size; long search_len,buf_pos; search_handle handle; // Get length of search string search_len=strlen(search_text); // Matching hex? if (search_text[0]=='$') { // Convert hex to ASCII string for (buf_pos=1,match_size=0;buf_pos<search_len;buf_pos+=2,match_size++) { // Wildcard? if (search_text[buf_pos]=='?') match_text[match_size]='?'; // Else do hex conversion else match_text[match_size]=Atoh(&search_text[buf_pos],2); } // Can't have cast-insensitivity or only words on a hex search flags&=~(SEARCH_NOCASE|SEARCH_ONLYWORDS); } // Else normal search else { // Go through search text for (buf_pos=0,match_size=0;buf_pos<search_len;buf_pos++) { // \ indicates a control sequence if (search_text[buf_pos]=='\\') { // Increment position ++buf_pos; // If followed by another \, match a normal \ character if (search_text[buf_pos]=='\\') match_text[match_size++]='\\'; // Otherwise, indicates a decimal value else { match_text[match_size++]=atoi(search_text+buf_pos); // Skip over number while (search_text[buf_pos+1]>='0' && search_text[buf_pos+1]<='9') ++buf_pos; } } // Otherwise, store character else { // Case insensitive - convert to upper case if (flags&SEARCH_NOCASE) match_text[match_size++]=toupper(search_text[buf_pos]); // Store vertbatim else match_text[match_size++]=search_text[buf_pos]; } } } // Zero result settings handle.v_search_found_lines=0; handle.v_search_last_line_pos=0; // If we have a buffer, search it and return if (buffer) return search_buffer(&handle,buffer,buffer_size,match_text,match_size,flags); // Allocate buffer to read file into if (!(buffer=AllocVec(32004,MEMF_CLEAR))) return -1; // Loop until aborted, or end of file FOREVER { long oldpos,size; // Remember old file position oldpos=SeekBuf(file,0,OFFSET_CURRENT); // Read some data if ((size=ReadBuf(file,buffer,32000))<1) break; // Search what we've got if (search_buffer(&handle,buffer,size,match_text,match_size,flags)==1) { // Free buffer FreeVec(buffer); // Return match position return oldpos+(int)(handle.v_search_found_position-buffer); } // If end of file, break if (size<32000) break; // Seek back the size of the match (in case we had it spread over the end of the buffer) SeekBuf(file,-match_size,OFFSET_CURRENT); } // Free buffer FreeVec(buffer); // No match return -1; }