Added archived echoes support
This commit is contained in:
parent
f8a2159f0a
commit
4d4f620053
@ -12,6 +12,27 @@ ______________________________________________________________________
|
||||
Notes for GoldED+ 1.1.5, /snapshot/
|
||||
______________________________________________________________________
|
||||
|
||||
+ Added ability to READ packed messagebases. You need to add PKD
|
||||
attribute to such echo definition and specify UNPACKER for the
|
||||
extension defined. You should pack all files from the single
|
||||
messagebase to the archive with the same name. For *.msg areas you
|
||||
should add the directory as well. When entering to the archived area
|
||||
UNPACKER will be executed to unpack files to TEMPPATH. On exit, all
|
||||
files will be deleted.
|
||||
|
||||
New UNPACKER keyword have the following syntax:
|
||||
|
||||
UNPACKER <extension> <"commandline">
|
||||
|
||||
The commandline should provide the ability to extract all files from
|
||||
@file.<extension> to the current directory. F.e.:
|
||||
|
||||
UNPACKER zip "unzip @file"
|
||||
|
||||
Note that all changes to the messagebase will be discarded.
|
||||
|
||||
This feature is not supported for Hudson and GoldBase messagebases.
|
||||
|
||||
! AREAPATH now used as default path for all SEMAPHOREs rather than
|
||||
occasionally.
|
||||
|
||||
|
@ -611,6 +611,7 @@ CfgGed::CfgGed() {
|
||||
// tpl.clear();
|
||||
// twitname.clear();
|
||||
// twitsubj.clear();
|
||||
// unpacker.clear();
|
||||
// username.clear();
|
||||
// wtpl.clear();
|
||||
// xlatcharset.clear();
|
||||
|
@ -359,6 +359,7 @@ const word CRC_TWITMODE = 0x9DC8;
|
||||
const word CRC_TWITNAME = 0x2055;
|
||||
const word CRC_TWITSUBJ = 0x08C0;
|
||||
const word CRC_TWITTO = 0x9DFE;
|
||||
const word CRC_UNPACKER = 0x5691;
|
||||
const word CRC_URLHANDLER = 0x688E;
|
||||
const word CRC_USEAREA = 0x2FD4;
|
||||
const word CRC_USECHARSET = 0xE1B9;
|
||||
|
@ -555,6 +555,7 @@ SwitchT:
|
||||
|
||||
SwitchU:
|
||||
switch(crc) {
|
||||
case CRC_UNPACKER : CfgUnpacker (); break;
|
||||
case CRC_URLHANDLER : CfgUrlhandler (); break;
|
||||
case CRC_USEAREA : CfgUsearea (); break;
|
||||
case CRC_USECHARSET : CfgUsecharset (); break;
|
||||
|
@ -274,6 +274,20 @@ void CfgTwitsubj() {
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
|
||||
void CfgUnpacker() {
|
||||
|
||||
char* key;
|
||||
std::pair<std::string, std::string> unpackerentry;
|
||||
|
||||
getkeyval(&key, &val);
|
||||
|
||||
unpackerentry.first = key;
|
||||
unpackerentry.second = StripQuotes(val);
|
||||
CFG->unpacker.push_back(unpackerentry);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
|
||||
void CfgUrlhandler() {
|
||||
|
||||
// Get util number
|
||||
|
@ -341,6 +341,7 @@ void CfgTwitmode ();
|
||||
void CfgTwitname ();
|
||||
void CfgTwitsubj ();
|
||||
void CfgTwitto ();
|
||||
void CfgUnpacker ();
|
||||
void CfgUrlhandler ();
|
||||
void CfgUsearea ();
|
||||
void CfgUsecharset ();
|
||||
|
@ -337,6 +337,7 @@ public:
|
||||
int twitmode; // showtwits;
|
||||
std::vector<Node> twitname;
|
||||
gstrarray twitsubj;
|
||||
std::vector< std::pair<std::string, std::string> > unpacker;
|
||||
ExtUtil urlhandler;
|
||||
bool usearea;
|
||||
bool usecharset;
|
||||
|
@ -26,6 +26,7 @@
|
||||
|
||||
|
||||
#include <golded.h>
|
||||
#include <gdirposx.h>
|
||||
#include <gutlos.h>
|
||||
#include <gmoprot.h>
|
||||
#ifdef __UNIX__
|
||||
@ -122,6 +123,7 @@ void Cleanup(void) {
|
||||
CFG->xlatescset.clear();
|
||||
CFG->cmdkey.clear();
|
||||
CFG->macro.clear();
|
||||
CFG->unpacker.clear();
|
||||
|
||||
// Free misc data
|
||||
throw_xrelease(CharTable);
|
||||
@ -465,6 +467,87 @@ int ShellToDos(char* command, char* message, int cls, int cursor, int pause) {
|
||||
}
|
||||
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
|
||||
const char* Unpack(const char* archive) {
|
||||
|
||||
static Path newname;
|
||||
const char *filename = CleanFilename(archive);
|
||||
|
||||
std::vector< std::pair<std::string, std::string> >::iterator i;
|
||||
for(i = CFG->unpacker.begin(); i != CFG->unpacker.end(); i++) {
|
||||
int dots;
|
||||
const char *ext, *myext;
|
||||
for(dots = 0, ext = i->first.c_str() - 1; ext != NULL; dots++)
|
||||
ext = strchr(ext+1, '.');
|
||||
for(myext = filename + strlen(filename); (myext != filename) and (dots != 0); dots--) {
|
||||
do
|
||||
--myext;
|
||||
while((myext != filename) and (myext[0] != '.'));
|
||||
}
|
||||
if(dots or not strieql(myext+1, i->first.c_str()))
|
||||
continue;
|
||||
|
||||
Path newdir;
|
||||
mktemp(strxcpy(newdir, AddPath(CFG->temppath, "GDXXXXXX"), sizeof(Path)));
|
||||
mkdir(newdir, S_IWUSR);
|
||||
char cmdline[1024];
|
||||
strxcpy(cmdline, i->second.c_str(), sizeof(cmdline));
|
||||
strxcpy(newname, archive, sizeof(Path));
|
||||
strchg(newname, GOLD_WRONG_SLASH_CHR, GOLD_SLASH_CHR);
|
||||
strischg(cmdline, "@file", newname);
|
||||
// Store current drive/dir and change it to the temporary
|
||||
Path orgdir;
|
||||
getcwd(orgdir, sizeof(Path));
|
||||
gchdir(newdir);
|
||||
// Now unpack it
|
||||
ShellToDos(cmdline, "", LGREY|_BLACK, 0, -1);
|
||||
// Restore current directory
|
||||
gchdir(orgdir);
|
||||
strxcpy(newname, AddPath(AddBackslash(newdir), filename), sizeof(Path));
|
||||
newname[strlen(newname) - (i->first.length() + 1)] = NUL;
|
||||
return newname;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
|
||||
void CleanUnpacked(const char* unpacked) {
|
||||
|
||||
gposixdir d(unpacked);
|
||||
const gdirentry *de;
|
||||
std::string removeme;
|
||||
if(is_dir(unpacked)) {
|
||||
while((de = d.nextentry("*", true)) != NULL) {
|
||||
removeme = de->dirname;
|
||||
removeme += GOLD_SLASH_CHR;
|
||||
removeme += de->name;
|
||||
if(is_dir(removeme.c_str()))
|
||||
rmdir(removeme.c_str());
|
||||
else
|
||||
remove(removeme.c_str());
|
||||
}
|
||||
}
|
||||
Path tmpdir, tmpdir2;
|
||||
strxcpy(tmpdir2, unpacked, sizeof(Path));
|
||||
StripBackslash(tmpdir2);
|
||||
extractdirname(tmpdir, tmpdir2);
|
||||
d.cd(tmpdir);
|
||||
while((de = d.nextentry("*", true)) != NULL) {
|
||||
removeme = de->dirname;
|
||||
removeme += GOLD_SLASH_CHR;
|
||||
removeme += de->name;
|
||||
if(is_dir(removeme.c_str()))
|
||||
rmdir(removeme.c_str());
|
||||
else
|
||||
remove(removeme.c_str());
|
||||
}
|
||||
rmdir(tmpdir);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// Error exit function
|
||||
|
||||
|
@ -115,14 +115,15 @@ const gdirentry *gposixdir::nextentry(const char *mask, bool nameonly)
|
||||
}
|
||||
ret.name = entries[last_entry];
|
||||
ret.dirname = dirname.c_str();
|
||||
if(!nameonly) {
|
||||
std::string pn = ret.dirname;
|
||||
pn += "/";
|
||||
pn += ret.name;
|
||||
size_t skipfrom;
|
||||
while((skipfrom=pn.find("//")) != pn.npos)
|
||||
pn.erase(skipfrom, 1);
|
||||
if(!nameonly)
|
||||
stat(pn.c_str(), &ret.stat_info);
|
||||
}
|
||||
++last_entry;
|
||||
return &ret;
|
||||
}
|
||||
|
@ -81,6 +81,8 @@ void ftn_attr::add(const ftn_attr& b) {
|
||||
if(b.nok()) nok1();
|
||||
if(b.fax()) fax1();
|
||||
if(b.prn()) prn1();
|
||||
|
||||
if(b.pkd()) pkd1();
|
||||
}
|
||||
|
||||
|
||||
@ -188,6 +190,7 @@ void ftn_attr::get(const std::string& __s) {
|
||||
if(striinc("NOK", s)) nok1();
|
||||
if(striinc("FAX", s)) fax1();
|
||||
if(striinc("PRN", s)) prn1();
|
||||
if(striinc("PKD", s)) pkd1();
|
||||
}
|
||||
|
||||
|
||||
|
@ -114,6 +114,8 @@ const ulong GATTR_FWD = 0x02000000UL; // forwarded (wildcat)
|
||||
const ulong GATTR_EFL = 0x04000000UL; // echoflag (wildcat)
|
||||
const ulong GATTR_HRP = 0x08000000UL; // has replies (wildcat)
|
||||
|
||||
const ulong GATTR_PKD = 0x10000000UL; // Archived
|
||||
|
||||
class ftn_attr {
|
||||
|
||||
protected:
|
||||
@ -219,6 +221,8 @@ public:
|
||||
int efl() const { return (attr2 & GATTR_EFL) != 0; }
|
||||
int hrp() const { return (attr2 & GATTR_HRP) != 0; }
|
||||
|
||||
int pkd() const { return (attr2 & GATTR_PKD) != 0; }
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
|
||||
void pvt(ulong x) { if(x) attr1 |= GATTR_PVT; else attr1 &= ~GATTR_PVT; }
|
||||
@ -296,6 +300,8 @@ public:
|
||||
void efl(ulong x) { if(x) attr2 |= GATTR_EFL; else attr2 &= ~GATTR_EFL; }
|
||||
void hrp(ulong x) { if(x) attr2 |= GATTR_HRP; else attr2 &= ~GATTR_HRP; }
|
||||
|
||||
void pkd(ulong x) { if(x) attr2 |= GATTR_PKD; else attr2 &= ~GATTR_PKD; }
|
||||
|
||||
// -------------------------------------------------------------
|
||||
|
||||
void pvt0() { attr1 &= ~GATTR_PVT; }
|
||||
@ -414,6 +420,8 @@ public:
|
||||
|
||||
void prn1() { attr2 |= GATTR_PRN; }
|
||||
|
||||
void pkd1() { attr2 |= GATTR_PKD; }
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
|
||||
void pvtX() { attr1 ^= GATTR_PVT; }
|
||||
|
@ -86,6 +86,7 @@ public:
|
||||
const ftn_addr& aka() const { return cfg.aka; }
|
||||
int originno() const { return cfg.originno; }
|
||||
Attr& attr() { return cfg.attr; }
|
||||
bool ispacked() const { return cfg.attr.pkd(); }
|
||||
|
||||
bool ascan() { return (bool)cfg.scan; }
|
||||
bool ascanexcl() { return (bool)cfg.scanexcl; }
|
||||
@ -185,6 +186,11 @@ public:
|
||||
|
||||
virtual void set_highwater_mark() { }
|
||||
virtual void reset_highwater_mark() { }
|
||||
|
||||
protected:
|
||||
Path realpath;
|
||||
const char* real_path() const { return ispacked() ? realpath : path(); }
|
||||
void set_real_path(const char* newpath) { strxcpy(realpath, newpath, sizeof(Path)); }
|
||||
};
|
||||
|
||||
|
||||
@ -281,6 +287,8 @@ extern int WidePersonalmail;
|
||||
// ------------------------------------------------------------------
|
||||
|
||||
int PopupLocked(long __tries, int __isopen, const char* __file);
|
||||
const char* Unpack(const char* archive);
|
||||
void CleanUnpacked(const char* unpacked);
|
||||
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
|
@ -338,6 +338,12 @@ void EzycomArea::open() {
|
||||
TestErrorExit();
|
||||
}
|
||||
if(isopen == 1) {
|
||||
if(ispacked()) {
|
||||
isopen--;
|
||||
const char* newpath = Unpack(path());
|
||||
set_real_path(newpath ? newpath : path());
|
||||
isopen++;
|
||||
}
|
||||
data_open();
|
||||
test_raw_open(__LINE__);
|
||||
scan();
|
||||
@ -390,6 +396,9 @@ void EzycomArea::close() {
|
||||
raw_close();
|
||||
Msgn->Reset();
|
||||
data_close();
|
||||
if(ispacked()) {
|
||||
CleanUnpacked(real_path());
|
||||
}
|
||||
}
|
||||
isopen--;
|
||||
}
|
||||
|
@ -170,6 +170,12 @@ void FidoArea::open() {
|
||||
TestErrorExit();
|
||||
}
|
||||
if(isopen == 1) {
|
||||
if(ispacked()) {
|
||||
isopen--;
|
||||
const char* newpath = Unpack(path());
|
||||
set_real_path(newpath ? newpath : path());
|
||||
isopen++;
|
||||
}
|
||||
data_open();
|
||||
scan();
|
||||
}
|
||||
@ -207,6 +213,9 @@ void FidoArea::close() {
|
||||
save_lastread();
|
||||
Msgn->Reset();
|
||||
data_close();
|
||||
if(ispacked()) {
|
||||
CleanUnpacked(real_path());
|
||||
}
|
||||
}
|
||||
isopen--;
|
||||
}
|
||||
|
@ -93,6 +93,12 @@ void JamArea::open() {
|
||||
TestErrorExit();
|
||||
}
|
||||
if(isopen == 1) {
|
||||
if(ispacked()) {
|
||||
isopen--;
|
||||
const char* newpath = Unpack(path());
|
||||
set_real_path(newpath ? newpath : path());
|
||||
isopen++;
|
||||
}
|
||||
data_open();
|
||||
open_area();
|
||||
scan();
|
||||
@ -161,6 +167,9 @@ void JamArea::close() {
|
||||
raw_close();
|
||||
Msgn->Reset();
|
||||
data_close();
|
||||
if(ispacked()) {
|
||||
CleanUnpacked(real_path());
|
||||
}
|
||||
}
|
||||
isopen--;
|
||||
}
|
||||
|
@ -181,6 +181,12 @@ void PcbArea::open() {
|
||||
TestErrorExit();
|
||||
}
|
||||
if(isopen == 1) {
|
||||
if(ispacked()) {
|
||||
isopen--;
|
||||
const char* newpath = Unpack(path());
|
||||
set_real_path(newpath ? newpath : path());
|
||||
isopen++;
|
||||
}
|
||||
PcbWideOpen();
|
||||
data_open();
|
||||
raw_open();
|
||||
@ -237,6 +243,9 @@ void PcbArea::close() {
|
||||
Msgn->Reset();
|
||||
data_close();
|
||||
PcbWideClose();
|
||||
if(ispacked()) {
|
||||
CleanUnpacked(real_path());
|
||||
}
|
||||
}
|
||||
isopen--;
|
||||
}
|
||||
|
@ -93,6 +93,12 @@ void SMBArea::open() {
|
||||
TestErrorExit();
|
||||
}
|
||||
if(isopen == 1) {
|
||||
if(ispacked()) {
|
||||
isopen--;
|
||||
const char* newpath = Unpack(path());
|
||||
set_real_path(newpath ? newpath : path());
|
||||
isopen++;
|
||||
}
|
||||
data_open();
|
||||
|
||||
int _tries = 0;
|
||||
@ -150,6 +156,9 @@ void SMBArea::close()
|
||||
if(isopen == 1) {
|
||||
smb_close(data);
|
||||
data_close();
|
||||
if(ispacked()) {
|
||||
CleanUnpacked(real_path());
|
||||
}
|
||||
}
|
||||
isopen--;
|
||||
}
|
||||
|
@ -162,8 +162,8 @@ void SquishArea::raw_open() {
|
||||
|
||||
GFTRK("SquishRawOpen");
|
||||
|
||||
data->fhsqd = test_open(AddPath(path(), ".sqd"));
|
||||
data->fhsqi = test_open(AddPath(path(), ".sqi"));
|
||||
data->fhsqd = test_open(AddPath(real_path(), ".sqd"));
|
||||
data->fhsqi = test_open(AddPath(real_path(), ".sqi"));
|
||||
|
||||
GFTRK(NULL);
|
||||
}
|
||||
@ -186,6 +186,12 @@ void SquishArea::open() {
|
||||
TestErrorExit();
|
||||
}
|
||||
if(isopen == 1) {
|
||||
if(ispacked()) {
|
||||
isopen--;
|
||||
const char* newpath = Unpack(path());
|
||||
set_real_path(newpath ? newpath : path());
|
||||
isopen++;
|
||||
}
|
||||
data_open();
|
||||
raw_open();
|
||||
refresh();
|
||||
@ -202,7 +208,7 @@ void SquishArea::save_lastread() {
|
||||
|
||||
GFTRK("SquishSaveLastread");
|
||||
|
||||
int _fh = ::sopen(AddPath(path(), ".sql"), O_RDWR|O_CREAT|O_BINARY, WideSharemode, S_STDRW);
|
||||
int _fh = ::sopen(AddPath(real_path(), ".sql"), O_RDWR|O_CREAT|O_BINARY, WideSharemode, S_STDRW);
|
||||
if(_fh != -1) {
|
||||
lseekset(_fh, wide->userno, sizeof(dword));
|
||||
dword _lastread = Msgn->CvtReln(lastread);
|
||||
@ -227,6 +233,9 @@ void SquishArea::close() {
|
||||
Msgn->Reset();
|
||||
throw_xrelease(data->idx);
|
||||
data_close();
|
||||
if(ispacked()) {
|
||||
CleanUnpacked(real_path());
|
||||
}
|
||||
}
|
||||
isopen--;
|
||||
}
|
||||
|
@ -45,7 +45,7 @@ void SquishArea::refresh() {
|
||||
SqshBase& _base = data->base;
|
||||
memset(&_base, 0, sizeof(SqshBase));
|
||||
_base.size = sizeof(SqshBase);
|
||||
strxcpy(_base.name, path(), sizeof(_base.name));
|
||||
strxcpy(_base.name, real_path(), sizeof(_base.name));
|
||||
_base.endframe = _base.size;
|
||||
_base.framesize = sizeof(SqshFrm);
|
||||
_base.nextmsgno = 2;
|
||||
@ -85,7 +85,7 @@ void SquishArea::raw_scan(int __keep_index, int __scanpm) {
|
||||
|
||||
// Load the lastread
|
||||
dword _lastread = 0;
|
||||
int _fh = ::sopen(AddPath(path(), ".sql"), O_RDONLY|O_BINARY, WideSharemode, S_STDRD);
|
||||
int _fh = ::sopen(AddPath(real_path(), ".sql"), O_RDONLY|O_BINARY, WideSharemode, S_STDRD);
|
||||
if(_fh != -1) {
|
||||
lseekset(_fh, wide->userno, sizeof(dword));
|
||||
read(_fh, &_lastread, sizeof(dword));
|
||||
@ -99,7 +99,7 @@ void SquishArea::raw_scan(int __keep_index, int __scanpm) {
|
||||
data->base.totalmsgs = 0;
|
||||
|
||||
// Open index file
|
||||
data->fhsqi = ::sopen(AddPath(path(), ".sqi"), O_RDONLY|O_BINARY, WideSharemode, S_STDRD);
|
||||
data->fhsqi = ::sopen(AddPath(real_path(), ".sqi"), O_RDONLY|O_BINARY, WideSharemode, S_STDRD);
|
||||
if(data->fhsqi != -1) {
|
||||
|
||||
// Get the number of index records
|
||||
@ -111,7 +111,7 @@ void SquishArea::raw_scan(int __keep_index, int __scanpm) {
|
||||
if((data->base.totalmsgs == 1) or (wide->squishscan == SQS_API)) {
|
||||
|
||||
// Open, read and close data file
|
||||
data->fhsqd = ::sopen(AddPath(path(), ".sqd"), O_RDONLY|O_BINARY, WideSharemode, S_STDRD);
|
||||
data->fhsqd = ::sopen(AddPath(real_path(), ".sqd"), O_RDONLY|O_BINARY, WideSharemode, S_STDRD);
|
||||
if(data->fhsqd != -1) {
|
||||
read(data->fhsqd, &data->base, sizeof(SqshBase));
|
||||
::close(data->fhsqd);
|
||||
|
@ -46,11 +46,11 @@ void SquishArea::lock() {
|
||||
if(WideCanLock) {
|
||||
long _tries = 0;
|
||||
while(::lock(data->fhsqd, 0, 1) == -1) {
|
||||
if(PopupLocked(++_tries, true, path()) == false) {
|
||||
if(PopupLocked(++_tries, true, real_path()) == false) {
|
||||
WideLog->ErrLock();
|
||||
raw_close();
|
||||
WideLog->printf("! A Squish msgbase file could not be locked.");
|
||||
WideLog->printf(": %s.SQD.", path());
|
||||
WideLog->printf(": %s.sqd.", real_path());
|
||||
WideLog->ErrOSInfo();
|
||||
LockErrorExit();
|
||||
}
|
||||
|
@ -154,6 +154,12 @@ void WCatArea::open() {
|
||||
TestErrorExit();
|
||||
}
|
||||
if(isopen == 1) {
|
||||
if(ispacked()) {
|
||||
isopen--;
|
||||
const char* newpath = Unpack(path());
|
||||
set_real_path(newpath ? newpath : path());
|
||||
isopen++;
|
||||
}
|
||||
data_open();
|
||||
raw_open();
|
||||
refresh();
|
||||
@ -195,6 +201,9 @@ void WCatArea::close() {
|
||||
Msgn->Reset();
|
||||
throw_release(data->idx);
|
||||
data_close();
|
||||
if(ispacked()) {
|
||||
CleanUnpacked(real_path());
|
||||
}
|
||||
}
|
||||
isopen--;
|
||||
}
|
||||
|
@ -198,6 +198,12 @@ void XbbsArea::open() {
|
||||
TestErrorExit();
|
||||
}
|
||||
if(isopen == 1) {
|
||||
if(ispacked()) {
|
||||
isopen--;
|
||||
const char* newpath = Unpack(path());
|
||||
set_real_path(newpath ? newpath : path());
|
||||
isopen++;
|
||||
}
|
||||
data_open();
|
||||
raw_open();
|
||||
refresh();
|
||||
@ -239,6 +245,9 @@ void XbbsArea::close() {
|
||||
Msgn->Reset();
|
||||
throw_release(data->idx);
|
||||
data_close();
|
||||
if(ispacked()) {
|
||||
CleanUnpacked(real_path());
|
||||
}
|
||||
}
|
||||
isopen--;
|
||||
}
|
||||
|
@ -2782,7 +2782,12 @@ AREA:<OriginalEchoID></eg>
|
||||
the optional default origin makes it simpler to create a common
|
||||
<ref target=INCLUDE><kw/INCLUDE/</ref>'able area configuration
|
||||
for several setups with different addresses, for example two people
|
||||
sharing the same msgbase.
|
||||
sharing the same msgbase.<lb>
|
||||
If you wish to read packed area (f.e. from CD archive) <name/GoldED+/
|
||||
allows you that. You need to specify pathname <b/with/ extension
|
||||
in the <ident>path/board</ident> field, set <gi/PKD/ attribute and
|
||||
define packer with <ref target=UNPACKER><kw/UNPACKER/</ref> keyword.
|
||||
This feature is not supported for Hudson and GoldBase messagebases.
|
||||
</item>
|
||||
<label>
|
||||
Processed by:
|
||||
@ -9648,6 +9653,33 @@ AREASEP !C "Group C" C Local]]></eg>
|
||||
random system group.
|
||||
</p>
|
||||
</div2>
|
||||
<div2 id=UNPACKER>
|
||||
<head>
|
||||
UNPACKER
|
||||
</head>
|
||||
<p>
|
||||
Added ability to READ packed messagebases. You need to add PKD
|
||||
attribute to such echo definition and specify UNPACKER for the
|
||||
extension defined. You should pack all files from the single
|
||||
messagebase to the archive with the same name. For *.msg areas you
|
||||
should add the directory as well. When entering to the archived area
|
||||
UNPACKER will be executed to unpack files to TEMPPATH. On exit, all
|
||||
files will be deleted.
|
||||
|
||||
New UNPACKER keyword have the following syntax:
|
||||
|
||||
UNPACKER >extension< ><q/commandline/<
|
||||
|
||||
The commandline should provide the ability to extract all files from
|
||||
@file.<extension> to the current directory. F.e.:
|
||||
|
||||
UNPACKER zip <q/unzip @file/
|
||||
|
||||
Note that all changes to the messagebase will be discarded.
|
||||
|
||||
This feature is not supported for Hudson and GoldBase messagebases.
|
||||
</p>
|
||||
</div2>
|
||||
<div2>
|
||||
<head>
|
||||
USECHARSET <yes/no>
|
||||
@ -10308,6 +10340,7 @@ LET Fax letterhead.
|
||||
LOC Local. Message was written on your system.
|
||||
LOK Lock. Prevents send/delete/purge/editing.
|
||||
ORP Orphan. Could not be sent because destination node is unknown.
|
||||
PKD Packed. Used in area definitions to unpack before using.
|
||||
PRN Msg has been printed. Specific for Squish (bitvalue 00040000h).
|
||||
PVT Private. Message may only be read by the addressee and author.
|
||||
R/O Read only. Used in area definitions to prevent writing.
|
||||
|
Reference in New Issue
Block a user