/* ************************************************************************
#
# DivConq
#
# http://divconq.com/
#
# Copyright:
# Copyright 2014 eTimeline, LLC. All rights reserved.
#
# License:
# See the license.txt file in the project's top-level directory for details.
#
# Authors:
# * Andy White
#
************************************************************************ */
package divconq.web;
import groovy.lang.GroovyObject;
import io.netty.buffer.ByteBuf;
import io.netty.handler.codec.http.cookie.Cookie;
import io.netty.handler.codec.http.HttpContent;
import io.netty.handler.stream.ChunkedInput;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import divconq.cms.feed.FeedAdapter;
import divconq.hub.DomainInfo;
import divconq.io.CacheFile;
import divconq.lang.op.OperationContext;
import divconq.locale.Tr;
import divconq.struct.CompositeStruct;
import divconq.struct.RecordStruct;
import divconq.struct.Struct;
import divconq.util.StringUtil;
import divconq.web.dcui.GalleryImageConsumer;
import divconq.web.dcui.Node;
import divconq.web.md.Configuration;
import divconq.web.md.ProcessContext;
import divconq.web.md.plugin.PairedMediaSection;
import divconq.web.md.plugin.StandardSection;
import divconq.xml.XElement;
public class WebContext {
protected IInnerContext innerctx = null;
protected boolean preview = false;
protected Map<String, String> innerparams = new HashMap<String, String>();
protected GroovyObject serverScript = null;
public GroovyObject getServerScript() {
return this.serverScript;
}
public void setServerScript(GroovyObject v) {
this.serverScript = v;
}
public String getExternalParam(String name) {
return this.getExternalParam(name, null);
}
public String getExternalParam(String name, String defaultvalue) {
try {
String ret = this.getRequest().getParameter(name);
if (ret == null)
ret = defaultvalue;
return ret;
}
catch (Exception x) {
}
return null;
}
public void putInternalParam(String name, String value) {
this.innerparams.put(name, value);
}
public boolean hasInternalParam(String name) {
return this.innerparams.containsKey(name);
}
public String getInternalParam(String name) {
return this.innerparams.get(name);
}
public IInnerContext getInnerContext() {
return this.innerctx;
}
public String expandMacros(String value) {
if (StringUtil.isEmpty(value))
return null;
boolean checkmatches = true;
while (checkmatches) {
checkmatches = false;
Matcher m = Node.macropatten.matcher(value);
while (m.find()) {
String grp = m.group();
String macro = grp.substring(1, grp.length() - 1);
String val = this.expandMacro(macro);
// if any of these, then replace and check (expand) again
if (val != null) {
value = value.replace(grp, val);
checkmatches = true;
}
}
}
return value;
}
public String expandMacro(String macro) {
String[] parts = macro.split("\\|");
String val = null;
// params on this tree
if ("param".equals(parts[0]) && (parts.length > 1)) {
val = this.getExternalParam(parts[1]);
}
else if ("ctx".equals(parts[0]) && (parts.length > 1)) {
String vname = parts[1];
val = this.getInternalParam(vname);
// TODO review and remove paths, excessive
if ((val == null) && (vname.equals("SignInPath") || vname.equals("HomePath") || vname.equals("PortalPath")
|| vname.equals("SiteTitle") || vname.equals("SiteAuthor") || vname.equals("SiteCopyright")))
{
DomainInfo domain = this.getDomain().getDomainInfo();
XElement domconfig = domain.getSettings();
if (domconfig != null) {
XElement web = domconfig.selectFirst("Web");
if ((web != null) && (web.hasAttribute(vname)))
val = web.getRawAttribute(vname);
}
}
// if not a web setting, perhaps a user field?
if ((val == null) && (vname.equals("dcUserFullname"))) {
val = OperationContext.get().getUserContext().getFullName();
}
}
// definitions in the dictionary
else if ("tr".equals(parts[0])) {
if ((parts.length > 1) && (StringUtil.isDataInteger(parts[1])))
parts[1] = "_code_" + parts[1];
if (parts.length > 2) {
String[] params = Arrays.copyOfRange(parts, 2, parts.length - 2);
val = Tr.tr(parts[1], (Object) params); // TODO test this
}
else if (parts.length > 1) {
val = Tr.tr(parts[1]);
}
}
else if (this.innerctx != null) {
IWebMacro macroproc = this.innerctx.getMacro(parts[0]);
if (macroproc != null)
val = macroproc.process(this, parts);
}
if (val == null)
return "";
return val;
}
public WebDomain getDomain() {
return this.innerctx.getDomain();
}
public WebContext(IInnerContext httpctx) {
this.innerctx = httpctx;
Cookie ck = this.innerctx.getRequest().getCookie("dcPreview");
if (ck != null)
this.preview = "true".equals(ck.value().toLowerCase());
}
public Response getResponse() {
return this.innerctx.getResponse();
}
public Request getRequest() {
return this.innerctx.getRequest();
}
public Map<String, List<String>> getParameters() {
return this.getRequest().getParameters();
}
public String getHost() {
return WebSiteManager.resolveHost(this.innerctx.getRequest());
}
public void send() {
this.innerctx.send();
}
public void sendStart(int contentLength) {
this.innerctx.sendStart(contentLength);
}
public void send(ByteBuf content) {
this.innerctx.send(content);
}
public void send(ChunkedInput<HttpContent> content) {
this.innerctx.send(content);
}
public void sendEnd() {
this.innerctx.sendEnd();
}
public void closeChannel() {
this.innerctx.close();
}
public boolean isPreview() {
return this.preview;
}
/*
public Path findPath(String path) {
return this.innerctx.getDomain().findFilePath(this.isPreview(), new CommonPath(path), null);
}
public Path findSectionPath(String section, String path) {
return this.innerctx.getDomain().findSectionFile(this.isPreview(), section, path);
}
*/
// string path is relative to dcw/[alias]/[path]
public XElement getXmlResource(String section, String path) {
CacheFile fpath = this.getSite().findSectionFile(section, path, this.isPreview());
if (fpath == null)
return null;
return fpath.asXml();
}
// string path is relative to dcw/[alias]/[path]
public CompositeStruct getJsonResource(String section, String path) {
CacheFile fpath = this.getSite().findSectionFile(section, path, this.isPreview());
if (fpath == null)
return null;
return fpath.asJson();
}
// string path is relative to dcw/[alias]/[path]
public String getTextResource(String section, String path) {
CacheFile fpath = this.getSite().findSectionFile(section, path, this.isPreview());
if (fpath == null)
return null;
return fpath.asString();
}
public FeedAdapter getFeedAdapter(String alias, String path) {
XElement feed = OperationContext.get().getDomain().getSettings().find("Feed");
if (feed == null)
return null;
// there are two special channels - Pages and Blocks
for (XElement chan : feed.selectAll("Channel")) {
String calias = chan.getAttribute("Alias");
if (calias == null)
calias = chan.getAttribute("Name");
if (calias == null)
continue;
if (calias.equals(alias)) {
path = chan.getAttribute("Path", chan.getAttribute("InnerPath", "")) + path + ".dcf.xml";
CacheFile fpath = this.getSite().findSectionFile("feed", path, this.isPreview());
if (fpath != null) {
FeedAdapter adapt = new FeedAdapter();
adapt.init(path, fpath);
return adapt;
}
return null;
}
}
return null;
}
public CompositeStruct getGalleryMeta(String path) {
return this.getJsonResource("galleries", path + "/meta.json");
}
public void forEachGalleryShowImage(String path, String show, GalleryImageConsumer consumer) {
RecordStruct gallery = (RecordStruct) this.getGalleryMeta(path);
if ((gallery != null) && (gallery.hasField("Shows"))) {
for (Struct s : gallery.getFieldAsList("Shows").getItems()) {
RecordStruct showrec = (RecordStruct) s;
if (!show.equals(showrec.getFieldAsString("Alias")))
continue;
for (Struct i : showrec.getFieldAsList("Images").getItems()) {
consumer.accept(gallery, showrec, i);
}
}
}
}
public WebSite getSite() {
return this.innerctx.getSite();
}
// TODO enhance how plugins are loaded
public ProcessContext getMarkdownContext() {
Configuration cfg = new Configuration()
.setSafeMode(false)
.registerPlugins(new PairedMediaSection(), new StandardSection());
return new ProcessContext(cfg, this);
}
public ProcessContext getSafeMarkdownContext() {
Configuration cfg = new Configuration();
return new ProcessContext(cfg, this);
}
}