package com.planet_ink.coffee_mud.Libraries;
import com.planet_ink.coffee_mud.core.interfaces.*;
import com.planet_ink.coffee_mud.core.*;
import com.planet_ink.coffee_mud.core.CMSecurity.DbgFlag;
import com.planet_ink.coffee_mud.core.collections.*;
import com.planet_ink.coffee_mud.Abilities.interfaces.*;
import com.planet_ink.coffee_mud.Areas.interfaces.*;
import com.planet_ink.coffee_mud.Behaviors.interfaces.*;
import com.planet_ink.coffee_mud.CharClasses.interfaces.*;
import com.planet_ink.coffee_mud.Commands.interfaces.*;
import com.planet_ink.coffee_mud.Common.interfaces.*;
import com.planet_ink.coffee_mud.Exits.interfaces.*;
import com.planet_ink.coffee_mud.Items.interfaces.*;
import com.planet_ink.coffee_mud.Libraries.interfaces.*;
import com.planet_ink.coffee_mud.Libraries.interfaces.JournalsLibrary.CommandJournalFlags;
import com.planet_ink.coffee_mud.Libraries.interfaces.JournalsLibrary.ForumJournal;
import com.planet_ink.coffee_mud.Libraries.interfaces.JournalsLibrary.ForumJournalFlags;
import com.planet_ink.coffee_mud.Locales.interfaces.*;
import com.planet_ink.coffee_mud.MOBS.interfaces.*;
import com.planet_ink.coffee_mud.Races.interfaces.*;
import java.io.IOException;
import java.util.*;
/*
Copyright 2005-2016 Bo Zimmerman
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
public class CMJournals extends StdLibrary implements JournalsLibrary
{
@Override public String ID(){return "CMJournals";}
public final int QUEUE_SIZE=100;
protected final SHashtable<String,CommandJournal> commandJournals = new SHashtable<String,CommandJournal>();
protected final SHashtable<String,ForumJournal> forumJournals = new SHashtable<String,ForumJournal>();
protected final SHashtable<String,List<ForumJournal>>clanForums = new SHashtable<String,List<ForumJournal>>();
protected final static List<ForumJournal> emptyForums = new ReadOnlyVector<ForumJournal>(0);
@SuppressWarnings("unchecked")
protected Hashtable<String,JournalSummaryStats> getSummaryStats()
{
Hashtable<String,JournalSummaryStats> journalSummaryStats;
journalSummaryStats= (Hashtable<String,JournalSummaryStats>)Resources.getResource("FORUM_JOURNAL_STATS");
if(journalSummaryStats == null)
{
synchronized("FORUM_JOURNAL_STATS".intern())
{
journalSummaryStats= (Hashtable<String,JournalSummaryStats>)Resources.getResource("FORUM_JOURNAL_STATS");
if(journalSummaryStats==null)
{
journalSummaryStats=new Hashtable<String,JournalSummaryStats>();
Resources.submitResource("FORUM_JOURNAL_STATS", journalSummaryStats);
}
}
}
return journalSummaryStats;
}
@Override
public JournalSummaryStats getJournalStats(ForumJournal journal)
{
if(journal == null)
return null;
final Hashtable<String,JournalSummaryStats> journalSummaryStats=getSummaryStats();
JournalSummaryStats stats = journalSummaryStats.get(journal.NAME().toUpperCase().trim());
if(stats == null)
{
synchronized(journal.NAME().intern())
{
stats = journalSummaryStats.get(journal.NAME().toUpperCase().trim());
if(stats == null)
{
stats = new JournalSummaryStats()
{
private String name = "";
private int threads = 0;
private int posts = 0;
private String imagePath = "";
private String shortIntro = "";
private String longIntro = "";
private String introKey = "";
private String latestKey = "";
private List<String> stuckyKeys = null;
@Override
public String name()
{
return name;
}
@Override
public JournalSummaryStats name(String intro)
{
name = intro;
return this;
}
@Override
public int threads()
{
return threads;
}
@Override
public JournalSummaryStats threads(int num)
{
this.threads = num;
return this;
}
@Override
public int posts()
{
return posts;
}
@Override
public JournalSummaryStats posts(int num)
{
this.posts = num;
return this;
}
@Override
public String imagePath()
{
return imagePath;
}
@Override
public JournalSummaryStats imagePath(String intro)
{
imagePath = intro;
return this;
}
@Override
public String shortIntro()
{
return shortIntro;
}
@Override
public JournalSummaryStats shortIntro(String intro)
{
shortIntro = intro;
return this;
}
@Override
public String longIntro()
{
return longIntro;
}
@Override
public JournalSummaryStats longIntro(String intro)
{
longIntro = intro;
return this;
}
@Override
public String introKey()
{
return introKey;
}
@Override
public JournalSummaryStats introKey(String key)
{
introKey = key;
return this;
}
@Override
public String latestKey()
{
return latestKey;
}
@Override
public JournalSummaryStats latestKey(String key)
{
latestKey = key;
return this;
}
@Override
public List<String> stuckyKeys()
{
return stuckyKeys;
}
@Override
public JournalSummaryStats stuckyKeys(List<String> keys)
{
stuckyKeys = keys;
return this;
}
};
stats.name( journal.NAME() );
CMLib.database().DBReadJournalSummaryStats(stats);
journalSummaryStats.put(journal.NAME().toUpperCase().trim(), stats);
}
}
}
return stats;
}
@Override
public void clearJournalSummaryStats(ForumJournal journal)
{
if(journal == null)
return;
final Hashtable<String,JournalSummaryStats> journalSummaryStats=getSummaryStats();
synchronized(journal.NAME().intern())
{
journalSummaryStats.remove(journal.NAME().toUpperCase().trim());
}
}
@Override
public int loadCommandJournals(String list)
{
clearCommandJournals();
while(list.length()>0)
{
int x=list.indexOf(',');
String item=null;
if(x<0)
{
item=list.trim();
list="";
}
else
{
item=list.substring(0,x).trim();
list=list.substring(x+1);
}
x=item.indexOf(' ');
final Hashtable<CommandJournalFlags,String> flags=new Hashtable<CommandJournalFlags,String>();
String mask="";
if(x>0)
{
mask=item.substring(x+1).trim();
for(int pf=0;pf<CommandJournalFlags.values().length;pf++)
{
final String flag = CommandJournalFlags.values()[pf].toString();
final int keyx=mask.toUpperCase().indexOf(flag);
if(keyx>=0)
{
int keyy=mask.indexOf(' ',keyx+1);
if(keyy<0)
keyy=mask.length();
if((keyx==0)||(Character.isWhitespace(mask.charAt(keyx-1))))
{
String parm=mask.substring(keyx+flag.length(),keyy).trim();
if((parm.length()==0)||(parm.startsWith("=")))
{
if(parm.startsWith("="))
parm=parm.substring(1);
flags.put(CommandJournalFlags.values()[pf],parm);
mask=mask.substring(0,keyx).trim()+" "+mask.substring(keyy).trim();
}
}
}
}
item=item.substring(0,x);
}
final String name=item.toUpperCase().trim();
CMSecurity.registerJournal(name);
final String journalAdminMask = mask;
commandJournals.put(name,new CommandJournal()
{
@Override
public String NAME()
{
return name;
}
@Override
public String mask()
{
return journalAdminMask;
}
@Override
public String JOURNAL_NAME()
{
return "SYSTEM_" + NAME().toUpperCase().trim() + "S";
}
@Override
public String getFlag(CommandJournalFlags flag)
{
return flags.get(flag);
}
@Override
public String getScriptFilename()
{
return flags.get(CommandJournalFlags.SCRIPT);
}
});
}
return commandJournals.size();
}
@Override
public boolean canReadMessage(JournalEntry entry, String srchMatch, MOB readerM, boolean ignorePrivileges)
{
if(entry==null)
return false;
final String to=entry.to();
if((srchMatch!=null)
&&(srchMatch.length()>0)
&&((to.toLowerCase().indexOf(srchMatch)<0)
&&(entry.from().toLowerCase().indexOf(srchMatch)<0)
&&(entry.subj().toLowerCase().indexOf(srchMatch)<0)
&&(entry.msg().toLowerCase().indexOf(srchMatch)<0)))
return false;
boolean priviledged=false;
if(readerM!=null)
priviledged=CMSecurity.isAllowedAnywhere(readerM,CMSecurity.SecFlag.JOURNALS)&&(!ignorePrivileges);
if(to.equalsIgnoreCase("all")
||((readerM!=null)
&&(priviledged
||to.equalsIgnoreCase(readerM.Name())
||(to.toUpperCase().trim().startsWith("MASK=")&&(CMLib.masking().maskCheck(to.trim().substring(5),readerM,true))))))
return true;
return false;
}
@Override
public int loadForumJournals(String list)
{
clearForumJournals();
final List<ForumJournal> journals = parseForumJournals(list);
for(final ForumJournal F : journals)
{
forumJournals.put(F.NAME().toUpperCase().trim(), F);
CMSecurity.registerJournal(F.NAME().toUpperCase().trim());
}
return forumJournals.size();
}
@Override
public List<ForumJournal> getClanForums(Clan clan)
{
if(clan == null)
return null;
return this.clanForums.get(clan.clanID());
}
@Override
public void registerClanForum(Clan clan, String allClanForumDefs)
{
if(clan==null)
return;
this.clanForums.remove(clan.clanID());
if(allClanForumDefs==null)
return;
final List<String> set=CMParms.parseCommas(allClanForumDefs,true);
final StringBuilder myForumList=new StringBuilder("");
for(String s : set)
{
s=s.trim();
if(s.startsWith("["))
{
final int x=s.indexOf(']');
final String cat=s.substring(1,x).trim();
if(clan.getGovernment().getCategory().equalsIgnoreCase(cat))
{
s=s.substring(x+1).trim();
s=CMStrings.replaceAll(s, "<CLANTYPE>", clan.getGovernmentName());
s=CMStrings.replaceAll(s, "<CLANNAME>", clan.getName());
s=CMStrings.replaceAll(s, ",", ".");
if(myForumList.length()>0)
myForumList.append(',');
myForumList.append(s);
}
}
}
final List<ForumJournal> journals = parseForumJournals(myForumList.toString());
if((journals!=null)&&(journals.size()>0))
this.clanForums.put(clan.clanID(), journals);
}
public List<ForumJournal> parseForumJournals(String list)
{
final List<ForumJournal> journals = new Vector<ForumJournal>(1);
while(list.length()>0)
{
int x=list.indexOf(',');
String item;
if(x<0)
{
item=list.trim();
list="";
}
else
{
item=list.substring(0,x).trim();
list=list.substring(x+1);
}
final Hashtable<ForumJournalFlags,String> flags=new Hashtable<ForumJournalFlags,String>();
x=item.indexOf('=');
if(x > 0)
{
int y=x;
while((y>0)&&(!Character.isWhitespace(item.charAt(y))))
y--;
final String rest = item.toUpperCase().substring(y+1).trim();
item=item.substring(0,y);
final Vector<Integer> flagDexes = new Vector<Integer>();
x=rest.indexOf('=');
while(x > 0)
{
y=x;
while((y>0)&&(!Character.isWhitespace(rest.charAt(y))))
y--;
if(y>0)
{
try
{
ForumJournalFlags.valueOf(rest.substring(y,x).toUpperCase().trim());
flagDexes.addElement(Integer.valueOf(y));
}
catch(final Exception e){}
}
x=rest.indexOf('=',x+1);
}
flagDexes.addElement(Integer.valueOf(rest.length()));
int lastStart=0;
for(final Integer flagDex : flagDexes)
{
final String piece = rest.substring(lastStart,flagDex.intValue());
lastStart=flagDex.intValue();
x=piece.indexOf('=');
try
{
final ForumJournalFlags flagVar = ForumJournalFlags.valueOf(piece.substring(0,x).toUpperCase().trim());
final String flagVal = piece.substring(x+1);
flags.put(flagVar, flagVal);
}
catch(final Exception e){}
}
}
String mask;
mask=flags.remove(ForumJournalFlags.READ);
final String readMask=(mask != null)?mask.trim():"";
mask=flags.remove(ForumJournalFlags.POST);
final String postMask=(mask != null)?mask.trim():"";
mask=flags.remove(ForumJournalFlags.REPLY);
final String replyMask=(mask != null)?mask.trim():"";
mask=flags.remove(ForumJournalFlags.ADMIN);
final String adminMask=(mask != null)?mask.trim():"";
final String name = item.trim();
journals.add(new ForumJournal()
{
@Override
public String NAME()
{
return name;
}
@Override
public String readMask()
{
return readMask;
}
@Override
public String postMask()
{
return postMask;
}
@Override
public String replyMask()
{
return replyMask;
}
@Override
public String adminMask()
{
return adminMask;
}
@Override
public String getFlag(CommandJournalFlags flag)
{
return flags.get(flag);
}
@Override
public boolean maskCheck(MOB M, String mask)
{
if(mask.length()>0)
{
if(M==null)
return false;
return CMLib.masking().maskCheck(mask, M, true);
}
return true;
}
@Override
public boolean authorizationCheck(MOB M, ForumJournalFlags fl)
{
if(!maskCheck(M,readMask))
return false;
if(fl==ForumJournalFlags.READ)
return true;
if(fl==ForumJournalFlags.POST)
return maskCheck(M,postMask);
else
if(fl==ForumJournalFlags.REPLY)
return maskCheck(M,replyMask);
else
if(fl==ForumJournalFlags.ADMIN)
return maskCheck(M,adminMask);
return false;
}
});
}
return journals;
}
@Override
@SuppressWarnings("unchecked")
public Set<String> getArchonJournalNames()
{
HashSet<String> H = (HashSet<String>)Resources.getResource("ARCHON_ONLY_JOURNALS");
if(H == null)
{
Item I=null;
H=new HashSet<String>();
for(final Enumeration<Item> e=CMClass.basicItems();e.hasMoreElements();)
{
I=e.nextElement();
if((I instanceof ArchonOnly)
&&(!I.isGeneric()))
H.add(I.Name().toUpperCase().trim());
}
Resources.submitResource("ARCHON_ONLY_JOURNALS", H);
}
return H;
}
@Override
public boolean isArchonJournalName(String journal)
{
if(getArchonJournalNames().contains(journal.toUpperCase().trim()))
return true;
return false;
}
@Override
public String getScriptValue(MOB mob, String journal, String oldValue)
{
final CommandJournal CMJ=getCommandJournal(journal);
if(CMJ==null)
return oldValue;
final String scriptFilename=CMJ.getScriptFilename();
if((scriptFilename==null)||(scriptFilename.trim().length()==0))
return oldValue;
final ScriptingEngine S=(ScriptingEngine)CMClass.getCommon("DefaultScriptingEngine");
S.setSavable(false);
S.setVarScope("*");
S.setScript("LOAD="+scriptFilename);
S.setVar(mob.Name(),"VALUE", oldValue);
final CMMsg msg2=CMClass.getMsg(mob,mob,null,CMMsg.MSG_OK_VISUAL,null,null,L("COMMANDJOURNAL_@x1",CMJ.NAME()));
S.executeMsg(mob, msg2);
S.dequeResponses();
S.tick(mob,Tickable.TICKID_MOB);
final String response=S.getVar("*","VALUE");
if(response!=null)
return response;
return oldValue;
}
@Override
public int getNumCommandJournals()
{
return commandJournals.size();
}
@Override
public Enumeration<CommandJournal> commandJournals()
{
return commandJournals.elements();
}
@Override
public CommandJournal getCommandJournal(String named)
{
return commandJournals.get(named.toUpperCase().trim());
}
public void expirationJournalSweep()
{
setThreadStatus(serviceClient,"expiration journal sweeping");
try
{
for(final Enumeration<CommandJournal> e=commandJournals();e.hasMoreElements();)
{
final CommandJournal CMJ=e.nextElement();
final String num=CMJ.getFlag(CommandJournalFlags.EXPIRE);
if((num!=null)&&(CMath.isNumber(num))&&(CMath.s_double(num)>0.0))
{
setThreadStatus(serviceClient,"updating journal "+CMJ.NAME());
final long expirationDate = System.currentTimeMillis() - Math.round(CMath.mul(TimeManager.MILI_DAY,CMath.s_double(num)));
final List<JournalEntry> items=CMLib.database().DBReadJournalMsgsOlderThan(CMJ.JOURNAL_NAME(),null,expirationDate);
for(int i=items.size()-1;i>=0;i--)
{
final JournalEntry entry=items.get(i);
final String from=entry.from();
final String message=entry.msg();
Log.sysOut(Thread.currentThread().getName(),"Expired "+CMJ.NAME()+" from "+from+": "+message);
CMLib.database().DBDeleteJournal(CMJ.JOURNAL_NAME(),entry.key());
}
setThreadStatus(serviceClient,"command journal sweeping");
}
}
}catch(final NoSuchElementException nse){}
try
{
for(final Enumeration<ForumJournal> e=forumJournals();e.hasMoreElements();)
{
final ForumJournal FMJ=e.nextElement();
final String num=FMJ.getFlag(CommandJournalFlags.EXPIRE);
if((num!=null)&&(CMath.isNumber(num))&&(CMath.s_double(num)>0.0))
{
setThreadStatus(serviceClient,"updating journal "+FMJ.NAME());
final long expirationDate = System.currentTimeMillis() - Math.round(CMath.mul(TimeManager.MILI_DAY,CMath.s_double(num)));
final List<JournalEntry> items=CMLib.database().DBReadJournalMsgsOlderThan(FMJ.NAME(),null,expirationDate);
for(int i=items.size()-1;i>=0;i--)
{
final JournalEntry entry=items.get(i);
if(!CMath.bset(entry.attributes(), JournalEntry.ATTRIBUTE_PROTECTED))
{
final String from=entry.from();
final String message=entry.msg();
Log.debugOut(Thread.currentThread().getName(),"Expired "+FMJ.NAME()+" from "+from+": "+message);
CMLib.database().DBDeleteJournal(FMJ.NAME(),entry.key());
}
}
setThreadStatus(serviceClient,"forum journal sweeping");
}
}
}catch(final NoSuchElementException nse){}
}
@Override
public boolean activate()
{
if(serviceClient==null)
{
name="THJournals"+Thread.currentThread().getThreadGroup().getName().charAt(0);
serviceClient=CMLib.threads().startTickDown(this, Tickable.TICKID_SUPPORT|Tickable.TICKID_SOLITARYMASK, MudHost.TIME_SAVETHREAD_SLEEP, 1);
}
return true;
}
@Override public boolean tick(Tickable ticking, int tickID)
{
tickStatus=Tickable.STATUS_ALIVE;
try
{
if((!CMSecurity.isDisabled(CMSecurity.DisFlag.SAVETHREAD))
&&(!CMSecurity.isDisabled(CMSecurity.DisFlag.JOURNALTHREAD)))
{
isDebugging=CMSecurity.isDebugging(DbgFlag.JOURNALTHREAD);
tickStatus=Tickable.STATUS_ALIVE;
expirationJournalSweep();
setThreadStatus(serviceClient,"sleeping");
}
}
finally
{
tickStatus=Tickable.STATUS_NOT;
}
return true;
}
private void clearCommandJournals()
{
commandJournals.clear();
}
@Override public int getNumForumJournals() { return forumJournals.size(); }
@Override public Enumeration<ForumJournal> forumJournals(){ return forumJournals.elements();}
@Override
public ForumJournal getForumJournal(String named)
{
return forumJournals.get(named.toUpperCase().trim());
}
@Override
public ForumJournal getForumJournal(String named, Clan clan)
{
if(named==null)
return null;
named=named.toUpperCase().trim();
if(forumJournals.containsKey(named))
return forumJournals.get(named);
if(clan!=null)
{
final List<ForumJournal> clanJournals=this.clanForums.get(clan.clanID());
if(clanJournals!=null)
{
for (final ForumJournal CJ : clanJournals)
{
if(CJ.NAME().equalsIgnoreCase(named))
return CJ;
}
}
}
return null;
}
private void clearForumJournals()
{
forumJournals.clear();
Resources.removeResource("FORUM_JOURNAL_STATS");
}
@Override
public boolean shutdown()
{
clearCommandJournals();
clearForumJournals();
if(CMLib.threads().isTicking(this, TICKID_SUPPORT|Tickable.TICKID_SOLITARYMASK))
{
CMLib.threads().deleteTick(this, TICKID_SUPPORT|Tickable.TICKID_SOLITARYMASK);
serviceClient=null;
}
return true;
}
private String unsafePrompt(Session sess, String prompt, String defaultMsg) throws IOException
{
sess.promptPrint(prompt);
String line=sess.blockingIn(-1, false);
if(line == null)
return defaultMsg;
return line;
}
@Override
public MsgMkrResolution makeMessage(final MOB mob, final String messageTitle, final List<String> vbuf, boolean autoAdd) throws IOException
{
final Session sess=mob.session();
if((sess == null )||(sess.isStopped()))
return MsgMkrResolution.CANCELFILE;
final boolean canExtEdit=((mob.session()!=null)&&(mob.session().getClientTelnetMode(Session.TELNET_GMCP)));
final String help=
L("^HCoffeeMud Message Maker Options:^N\n\r"+
"^XA)^.^Wdd new lines (go into ADD mode)\n\r"+
"^XD)^.^Welete one or more lines\n\r"+
"^XL)^.^Wist the entire text file\n\r"+
"^XI)^.^Wnsert a line\n\r"+
"^XE)^.^Wdit a line\n\r"+
"^XR)^.^Weplace text in the file\n\r"+
"^XS)^.^Wave the file\n\r"+
(canExtEdit?"^XW)^.^Write over using GMCP\n\r":"")+
"^XQ)^.^Wuit without saving");
final String addModeMessage=L("^ZYou are now in Add Text mode.\n\r^ZEnter . on a blank line to exit.^.^N");
mob.tell(L("^HCoffeeMud Message Maker^N"));
boolean menuMode=!autoAdd;
if(autoAdd)
sess.println(addModeMessage);
while((mob.session()!=null)&&(!sess.isStopped()))
{
sess.setAfkFlag(false);
if(!menuMode)
{
final String line =unsafePrompt(sess,"^X"+CMStrings.padRight(""+vbuf.size(),3)+")^.^N ",".");
if(line.trim().equals("."))
menuMode=true;
else
vbuf.add(line);
}
else
{
final LinkedList<String> paramsOut=new LinkedList<String>();
final String option=sess.choose(L("^HMenu ^N(?/A/D/L/I/E/R/S/Q@x1)^H: ^N",(canExtEdit?"/W":"")),L("ADLIERSQ?@x1",(canExtEdit?"W":"")),"?",-1,paramsOut);
final String paramAll=(paramsOut.size()>0)?CMParms.combine(paramsOut,0):null;
final String param1=(paramsOut.size()>0)?paramsOut.getFirst():null;
final String param2=(paramsOut.size()>1)?CMParms.combine(paramsOut,1):null;
switch(option.charAt(0))
{
case 'S':
if(((paramAll!=null)&&(paramAll.equalsIgnoreCase("Y")))
||(sess.confirm(L("Save and exit, are you sure (N/y)? "),"N")))
{
return MsgMkrResolution.SAVEFILE;
}
break;
case 'Q':
if(((paramAll!=null)&&(paramAll.equalsIgnoreCase("Y")))
||(sess.confirm(L("Quit without saving (N/y)? "),"N")))
return MsgMkrResolution.CANCELFILE;
break;
case 'R':
{
if(vbuf.size()==0)
mob.tell(L("The file is empty!"));
else
{
String line=param1;
if(line==null)
line=unsafePrompt(sess,L("Text to search for (case sensitive): "),"");
if(line.length()>0)
{
String str=param2;
if(str==null)
str=unsafePrompt(sess,L("Text to replace it with: "),"");
for(int i=0;i<vbuf.size();i++)
vbuf.set(i,CMStrings.replaceAll(vbuf.get(i),line,str));
}
else
mob.tell(L("(aborted)"));
}
break;
}
case 'E':
{
if(vbuf.size()==0)
mob.tell(L("The file is empty!"));
else
{
String line=param1;
if(line==null)
line=sess.prompt(L("Line to edit (0-@x1): ",""+(vbuf.size()-1)),"");
if((CMath.isInteger(line))&&(CMath.s_int(line)>=0)&&(CMath.s_int(line)<(vbuf.size())))
{
final int ln=CMath.s_int(line);
mob.tell(L("Current: \n\r@x1) @x2",CMStrings.padRight(""+ln,3),vbuf.get(ln)));
String str=param2;
if(str==null)
str=unsafePrompt(sess,L("Rewrite: \n\r"),"");
if(str.length()==0)
mob.tell(L("(no change)"));
else
vbuf.set(ln,str);
}
else
mob.tell(L("'@x1' is not a valid line number.",line));
}
break;
}
case 'D':
{
if(vbuf.size()==0)
mob.tell(L("The file is empty!"));
else
{
String line=paramAll;
if(line==null)
line=sess.prompt(L("Line to delete (0-@x1): ",""+(vbuf.size()-1)),"");
if((CMath.isInteger(line))&&(CMath.s_int(line)>=0)&&(CMath.s_int(line)<(vbuf.size())))
{
final int ln=CMath.s_int(line);
vbuf.remove(ln);
mob.tell(L("Line @x1 deleted.",""+ln));
}
else
mob.tell(L("'@x1' is not a valid line number.",""+line));
}
break;
}
case '?': mob.tell(help); break;
case 'A': mob.tell(addModeMessage);
menuMode=false;
break;
case 'W':
{
if(mob.session()!=null)
{
StringBuilder oldDoc=new StringBuilder();
for(final String s : vbuf)
oldDoc.append(s).append("\n");
vbuf.clear();
mob.session().sendGMCPEvent("IRE.Composer.Edit", "{\"title\":\""+MiniJSON.toJSONString(messageTitle)+"\",\"text\":\""+MiniJSON.toJSONString(oldDoc.toString())+"\"}");
oldDoc=null;
String newText=unsafePrompt(sess,L("Re-Enter the whole doc using your GMCP editor.\n\rIf the editor has not popped up, just hit enter and QUIT Without Saving immediately.\n\rProceed: "),"");
if((newText.length()>0)&&(newText.charAt(newText.length()-1)=='\\'))
newText = newText.substring(0,newText.length()-1);
final String[] newDoc=newText.split("\\\\n");
for(final String s : newDoc)
vbuf.add(s);
if(newDoc.length>1)
{
mob.tell(L("\n\r^HNew text successfully imported.^N"));
}
}
break;
}
case 'L':
{
final StringBuffer list=new StringBuffer(messageTitle+"\n\r");
for(int v=0;v<vbuf.size();v++)
list.append(CMLib.coffeeFilter().colorOnlyFilter("^X"+CMStrings.padRight(""+v,3)+")^.^N ",sess)+vbuf.get(v)+"\n\r");
sess.rawPrint(list.toString());
break;
}
case 'I':
{
if(vbuf.size()==0)
mob.tell(L("The file is empty!"));
else
{
String line=param1;
if(line==null)
line=unsafePrompt(sess,L("Line to insert before (0-@x1): ",""+(vbuf.size()-1)),"");
if((CMath.isInteger(line))&&(CMath.s_int(line)>=0)&&(CMath.s_int(line)<(vbuf.size())))
{
final int ln=CMath.s_int(line);
String str=param2;
if(str==null)
str=unsafePrompt(sess,L("Enter text to insert here.\n\r: "),"");
vbuf.add(ln,str);
}
else
mob.tell(L("'@x1' is not a valid line number.",""+line));
}
break;
}
}
}
}
return MsgMkrResolution.CANCELFILE;
}
@Override
public boolean subscribeToJournal(String journalName, String userName, boolean saveMailingList)
{
boolean updateMailingLists=false;
if((CMProps.getVar(CMProps.Str.MAILBOX).length()>0)
&&(CMLib.players().playerExists(userName)||CMLib.players().accountExists(userName)))
{
final Map<String, List<String>> lists=Resources.getCachedMultiLists("mailinglists.txt",true);
List<String> mylist=lists.get(journalName);
if(mylist==null)
{
mylist=new Vector<String>();
lists.put(journalName,mylist);
}
boolean found=false;
for(int l=0;l<mylist.size();l++)
if(mylist.get(l).equalsIgnoreCase(userName))
found=true;
if(!found)
{
mylist.add(userName);
updateMailingLists=true;
if(CMProps.getBoolVar(CMProps.Bool.EMAILFORWARDING))
{
String subscribeTitle="Subscribed";
String subscribedMsg="You are now subscribed to "+journalName+". To unsubscribe, send an email with a subject of unsubscribe.";
final String[] msgs =CMProps.getListVar(CMProps.StrList.SUBSCRIPTION_STRS);
if((msgs!=null)&&(msgs.length>0))
{
if(msgs[0].length()>0)
subscribeTitle = CMLib.coffeeFilter().fullInFilter(CMStrings.replaceAll(msgs[0],"<NAME>",journalName));
if((msgs.length>0) && (msgs[1].length()>0))
subscribedMsg = CMLib.coffeeFilter().fullInFilter(CMStrings.replaceAll(msgs[1],"<NAME>",journalName));
}
CMLib.database().DBWriteJournalEmail(CMProps.getVar(CMProps.Str.MAILBOX),journalName,journalName,userName,subscribeTitle,subscribedMsg);
}
}
}
if(updateMailingLists && saveMailingList)
{
Resources.updateCachedMultiLists("mailinglists.txt");
}
return updateMailingLists;
}
@Override
public boolean unsubscribeFromJournal(String journalName, String userName, boolean saveMailingList)
{
boolean updateMailingLists = false;
if(CMProps.getVar(CMProps.Str.MAILBOX).length()==0)
return false;
final Map<String, List<String>> lists=Resources.getCachedMultiLists("mailinglists.txt",true);
final List<String> mylist=lists.get(journalName);
if(mylist==null)
return false;
for(int l=mylist.size()-1;l>=0;l--)
if(mylist.get(l).equalsIgnoreCase(userName))
{
mylist.remove(l);
updateMailingLists=true;
if(CMProps.getBoolVar(CMProps.Bool.EMAILFORWARDING))
{
String unsubscribeTitle="Un-Subscribed";
String unsubscribedMsg="You are no longer subscribed to "+journalName+". To subscribe again, send an email with a subject of subscribe.";
final String[] msgs =CMProps.getListVar(CMProps.StrList.SUBSCRIPTION_STRS);
if((msgs!=null)&&(msgs.length>2))
{
if(msgs[2].length()>0)
unsubscribeTitle = CMLib.coffeeFilter().fullInFilter(CMStrings.replaceAll(msgs[2],"<NAME>",journalName));
if((msgs.length>3) && (msgs[1].length()>0))
unsubscribedMsg = CMLib.coffeeFilter().fullInFilter(CMStrings.replaceAll(msgs[3],"<NAME>",journalName));
}
CMLib.database().DBWriteJournalEmail(CMProps.getVar(CMProps.Str.MAILBOX),journalName,journalName,userName,unsubscribeTitle,unsubscribedMsg);
}
}
if(updateMailingLists && saveMailingList)
{
Resources.updateCachedMultiLists("mailinglists.txt");
}
return updateMailingLists;
}
}