📄 epocstore.cpp
字号:
/* epocstore.cpp * * Symbian OS implementation of PuTTY settings storage interface * * Mostly copied from the SyOSsh EPOC Release 5 port by Gabor Keresztfalvi, * some additional fixes for the current Symbian port by Petteri Kangaslampi. * Originally based on winstore.c in the PuTTY distribution. * * [No copyright messages in the original, assumed to be copyrighted by * Gabor Keresztfavli and available through the PuTTY license] * * Portions copyright 2002,2003 Petteri Kangaslampi * * See license.txt for full copyright and license information.*//* * epocstore.cpp: EPOC-specific implementation of the interface * defined in storage.h. * FIXME: Partially this is a stub only... */#include <e32base.h>#include <f32file.h>#include <bautils.h>#include <stdio.h>#include <stdlib.h>extern "C" {#include "putty.h"#include "storage.h"#include "tree234.h"}#include "epocstore.h"#include <assert.h>#include "charutil.h"// Current settingsstruct TSetting { HBufC8 *iName; HBufC8 *iValue;};// Static bits (ugly, but the API gives us no choice - otherwise the data path// would have to be hardcoded)struct TStoreStatics { TFileName iDataPath; RFs iFs;};#define storeStatics ((TStoreStatics *const)((SymbianStatics *const)statics()->platform)->store_state)// Settings read statestruct TSettingsReadState { tree234 *iSettings;};// Settings write statestruct TSettingsWriteState { RFile iFile;};_LIT(KRandomFile,"random.dat");_LIT(KHostKeysFile,"hostkeys.dat");_LIT(KTmpHostKeysFile, "hostkeys.tmp");_LIT8(KSettingsId, "[PuTTYConfig]");_LIT8(KCRLF, "\r\n");static void FreeSettingsTree(tree234 *aSettings);void epoc_store_init(const TDesC &aDataPath) { // Allocate memory for statics TStoreStatics *statics = new TStoreStatics; if ( !statics ) fatalbox("Out of memory"); ((SymbianStatics*)statics()->platform)->store_state = statics; assert(aDataPath.Length() > 1); storeStatics->iDataPath = aDataPath; // Make sure the path ends with a backslash if ( storeStatics->iDataPath[storeStatics->iDataPath.Length()-1] != '\\' ) { storeStatics->iDataPath.Append('\\'); } TInt err = storeStatics->iFs.Connect(); if ( err != KErrNone ) fatalbox("File server connect failed");}void epoc_store_free() { TStoreStatics *statics = ((TStoreStatics*)((SymbianStatics*)statics()->platform)->store_state); statics->iFs.Close(); delete statics; ((SymbianStatics*)statics()->platform)->store_state = NULL;}/** * An utility class for reading files one line at a time. Handles all * related buffering and line feed conversion issues. */class CLineReader : public CBase {public: /** * Creates a new CLineReader object and pushes it to the cleanup stack. * * @param aFileName The file to read * @param aFs The file server session to use * * @return A new CLineReader object */ static CLineReader *NewLC(const TDesC &aFileName, RFs &aFs); /** * Destructor. */ ~CLineReader(); /** * Reads a line from the input file. Empty lines are discarded, * and the cr/lf characters are removed. Returns an empty * descriptor if called at the end of the file. * * @return The line that was read, or an empty descriptor if at EOF. */ TPtrC8 &ReadLineL();private: CLineReader(); void ConstructL(const TDesC &aFileName, RFs &aFs); TBool ReadDataL(); TUint8 *iBuffer; TUint iBufSize; TUint iDataLength; TUint iLineEnd; TUint iLineStart; TPtrC8 iThisLine; RFs *iFs; RFile iFile; TBool iFileOpen;};// Builds a new line reader objectCLineReader *CLineReader::NewLC(const TDesC &aFileName, RFs &aFs) { CLineReader *self = new (ELeave) CLineReader; CleanupStack::PushL(self); self->ConstructL(aFileName, aFs); return self;}CLineReader::CLineReader() : iThisLine(NULL, 0) { iFileOpen = EFalse; }void CLineReader::ConstructL(const TDesC &aFileName, RFs &aFs) { iFs = &aFs; User::LeaveIfError(iFile.Open(*iFs, aFileName, EFileShareReadersOnly)); iFileOpen = ETrue; iBufSize = 512; iDataLength = 0; iLineEnd = 0; iBuffer = new (ELeave) TUint8[iBufSize];}CLineReader::~CLineReader() { if ( iFileOpen ) { iFile.Close(); } delete iBuffer;}// Reads a line from the file. Empty lines are discarded, and the cr/lf// characters are removed. Returns an empty descriptor if at the end of the// file.TPtrC8 &CLineReader::ReadLineL() { // Discard previous line if ( iLineEnd > 0 ) { assert(iLineEnd <= iDataLength); if ( iLineEnd < iDataLength ) { Mem::Copy(&iBuffer[0], &iBuffer[iLineEnd], iDataLength - iLineEnd); iDataLength -= iLineEnd; } iLineEnd = 0; } iLineStart = 0; // Find where the next line starts, skipping any linefeed characters TBool startFound = EFalse; while ( !startFound ) { // Read more data if necessary if ( iLineStart >= iDataLength ) { if ( !ReadDataL() ) { // EOF iThisLine.Set(NULL, 0); return iThisLine; } } // Does the line start here? if ( (iBuffer[iLineStart] != '\r') && (iBuffer[iLineStart] != '\n') ) { startFound = ETrue; } else { iLineStart++; } } // Find where the line ends iLineEnd = iLineStart; TBool endFound = EFalse; while ( !endFound ) { // Read more data if necessary if ( iLineEnd >= iDataLength ) { if ( !ReadDataL() ) { // EOF -- use last line if we have one if ( iLineEnd > iLineStart ) { iThisLine.Set(&iBuffer[iLineStart], iLineEnd - iLineStart); } else { iThisLine.Set(NULL, 0); } return iThisLine; } } // Does the line end here? if ( (iBuffer[iLineEnd] == '\r') || (iBuffer[iLineEnd] == '\n') ) { endFound = ETrue; } else { iLineEnd++; } } // OK, we have the line iThisLine.Set(&iBuffer[iLineStart], iLineEnd - iLineStart); return iThisLine;}// Internal: Reads more data to the internal buffer. Returns EFalse if at the// EOF and couldn't read more.TBool CLineReader::ReadDataL() { // Need a bigger buffer? if ( iDataLength >= iBufSize ) { TUint newSize = 2 * iBufSize; TUint8 *newBuf = new (ELeave) TUint8[newSize]; Mem::Copy(newBuf, iBuffer, iBufSize); delete [] iBuffer; iBuffer = newBuf; iBufSize = newSize; } // Read some data assert(iBufSize > iDataLength); assert(iFileOpen); TPtr8 ptr(&iBuffer[iDataLength], iBufSize - iDataLength); User::LeaveIfError(iFile.Read(ptr)); if ( ptr.Length() == 0 ) { return EFalse; } iDataLength += ptr.Length(); return ETrue;}// Comparison function for sorting settings in the settings tree. Compared// two TSetting objectsstatic int cmp_setting_setting(void *s1, void *s2) { TSetting *set1 = (TSetting*) s1; TSetting *set2 = (TSetting*) s2; return set1->iName->Compare(*set2->iName);}// Comparison function for looking up settings from the settings tree. Compares// a char* string to a TSetting objectstatic int cmp_name_setting(void *n, void *s) { char *str = (char*) n; TSetting *set = (TSetting*) s; TPtrC8 ptr((TUint8*) str); return ptr.Compare(*set->iName);}static void open_settings_w_L(TSettingsWriteState* state, const char *sessionname) { // FIXME: Writing settings is pretty slow, and could be optimized by // gathering all settings to a buffer and writing that buffer in one go. // sessionname is really an absolute path to the settings file HBufC *buf = HBufC::NewLC(strlen(sessionname)); TPtr ptr = buf->Des(); StringToDes(sessionname, ptr); // Open the file and write header User::LeaveIfError(state->iFile.Replace(storeStatics->iFs, ptr, EFileWrite)); CleanupClosePushL(state->iFile); User::LeaveIfError(state->iFile.Write(KSettingsId)); User::LeaveIfError(state->iFile.Write(KCRLF)); CleanupStack::Pop(); // file CleanupStack::PopAndDestroy(buf);}void *open_settings_w(const char *sessionname, char **errmsg) { TSettingsWriteState *state = snew(TSettingsWriteState); if ( !state ) { *errmsg = "Out of memory"; return NULL; } TRAPD(error, open_settings_w_L(state, sessionname)); if ( error != KErrNone ) { sfree(state); *errmsg = "Failed top open settings file"; } return (void*) state;}static void write_settings_s_L(TSettingsWriteState *state, const char *key, const char *value) { // key = value\r\n\0 HBufC8 *buf = HBufC8::NewLC(strlen(key) + strlen(value) + 6); TPtr8 ptr = buf->Des(); char *strbuf = (char*) ptr.Ptr(); sprintf(strbuf, "%s = %s\r\n", key, value); ptr.SetLength(strlen(strbuf)); User::LeaveIfError(state->iFile.Write(ptr)); CleanupStack::PopAndDestroy();}void write_setting_s(void *handle, const char *key, const char *value) { TSettingsWriteState *state = (TSettingsWriteState*) handle; TRAPD(error, write_settings_s_L(state, key, value)); if ( error != KErrNone ) { fatalbox("write_setting_s: error %d", error); }}static void write_settings_i_L(TSettingsWriteState *state, const char *key, int value) { // key = 4294967296\r\n\0 HBufC8 *buf = HBufC8::NewLC(strlen(key) + 10 + 6); TPtr8 ptr = buf->Des(); char *strbuf = (char*) ptr.Ptr(); sprintf(strbuf, "%s = %u\r\n", key, value); ptr.SetLength(strlen(strbuf)); User::LeaveIfError(state->iFile.Write(ptr)); CleanupStack::PopAndDestroy();}void write_setting_i(void *handle, const char *key, int value) { TSettingsWriteState *state = (TSettingsWriteState*) handle; TRAPD(error, write_settings_i_L(state, key, value)); if ( error != KErrNone ) { fatalbox("write_setting_s: error %d", error); }}void close_settings_w(void *handle) { TSettingsWriteState *state = (TSettingsWriteState*) handle; state->iFile.Close(); sfree(state);}static void open_settings_r_L(TSettingsReadState *state, const char *sessionname) { // sessionname is really an absolute path to the settings file. We'll just // read the whole file into a tree and use it when the actual setting // values are requested. HBufC *buf = HBufC::NewLC(strlen(sessionname)); TPtr namePtr = buf->Des(); StringToDes(sessionname, namePtr); // Create a new settings tree tree234 *settings = newtree234(cmp_setting_setting); if ( settings == NULL ) { User::Leave(KErrNoMemory);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -