I noticed that some of the slowest cases in Joel's regex test corpus
had issues with back-reference matching, and along the way to fixing
that discovered what seems to me to be a bug in the engine's handling
of back-references.  To wit, what should happen if a back-reference
is to a subexpression that contains constraints?  A simple example is

        SELECT regexp_match('foof', '(^f)o*\1');

To my mind, the back reference is only chartered to match the literal
characters matched by the referenced subexpression.  Here, since that
expression matches "f", the backref should too, and thus we should get
a match to "foof".  Perl gives that answer, anyway; but our existing
code says there's no match.  That's because it effectively copies the
constraints within the referenced subexpression, in addition to making
the data comparison.  The "^" can't match where the second "f" is, so
we lose.

0001 attached fixes this by stripping constraint arcs out of the NFA
that's applied to the backref subre tree node.

Now, as to the performance issue ... if you load up the data in
"trouble.sql" attached, and do

        SELECT regexp_matches(subject, pattern, 'g') FROM trouble;

you'll be waiting a good long time, even with our recent improvements.
(Up to now I hadn't tried the 'g' flag with Joel's test cases, so
I hadn't noticed what a problem this particular example has got.)
The reason for the issue is that the pattern is

        (["'`])(?:\\\1|.)*?\1

and the subject string has a mix of " and ' quote characters.  As
currently implemented, our engine tries to resolve the match at
any substring ending in either " or ', since the NFA created for
the backref can match either.  That leads to O(N^2) time wasted
trying to verify wrong matches.

I realized that this could be improved by replacing the NFA/DFA
match step for a backref node with a string literal match, if the
backreference match string is already known at the time we try
to apply the NFA/DFA.  That's not a panacea, but it helps in most
simple cases including this one.  The way to visualize what is
happening is that we have a tree of binary concatenation nodes:

                  concat
                 /      \
          capture        concat
                        /      \
             other stuff        backref

Each concat node performs fast NFA/DFA checks on both its children
before recursing to the children to make slow exact checks.  When we
recurse to the capture node, it records the actual match substring,
so now we know whether the capture is " or '.  Then, when we recurse
to the lower concat node, the capture is available while it makes
NFA/DFA checks for its two children; so it will never mistakenly
guess that its second child matches a substring it doesn't, and
thus it won't try to do exact checking of the "other stuff" on a
match that's bound to fail later.

So this works as long as the tree of concat nodes is right-deep,
which fortunately is the normal case.  It won't help if we have
a left-deep tree:

                       concat
                      /      \
                concat        backref
               /      \
        capture        other stuff

because the upper concat node will do its NFA/DFA check on the backref
node before recursing to its left child, where the capture will occur.
But to get that tree, you have to have written extra parentheses:

        ((capture)otherstuff)\2

I don't see a way to improve that situation, unless perhaps with
massive rejiggering of the regex execution engine.  But 0002 attached
does help a lot in the simple case.

(BTW, the connection between 0001 and 0002 is that if we want to keep
the existing semantics that a backref enforces constraints, 0002
doesn't work, since it won't do that.)

                        regards, tom lane

diff --git a/doc/src/sgml/func.sgml b/doc/src/sgml/func.sgml
index 08f08322ca..6c189bfed2 100644
--- a/doc/src/sgml/func.sgml
+++ b/doc/src/sgml/func.sgml
@@ -6166,6 +6166,9 @@ SELECT foo FROM regexp_split_to_table('the quick brown fox', '\s*') AS foo;
     The subexpression must entirely precede the back reference in the RE.
     Subexpressions are numbered in the order of their leading parentheses.
     Non-capturing parentheses do not define subexpressions.
+    The back reference considers only the string characters matched by the
+    referenced subexpression, not any constraints contained in it.  For
+    example, <literal>(^\d)\1</literal> will match <literal>22</literal>.
    </para>
 
    <table id="posix-character-entry-escapes-table">
diff --git a/src/backend/regex/regc_nfa.c b/src/backend/regex/regc_nfa.c
index a10a346e8f..77b860cb0f 100644
--- a/src/backend/regex/regc_nfa.c
+++ b/src/backend/regex/regc_nfa.c
@@ -1382,6 +1382,77 @@ duptraverse(struct nfa *nfa,
 	}
 }
 
+/*
+ * removeconstraints - remove any constraints in an NFA
+ *
+ * Constraint arcs are replaced by empty arcs, essentially treating all
+ * constraints as automatically satisfied.
+ */
+static void
+removeconstraints(struct nfa *nfa,
+				  struct state *start,	/* process subNFA starting here */
+				  struct state *stop)	/* and stopping here */
+{
+	if (start == stop)
+		return;
+
+	stop->tmp = stop;
+	removetraverse(nfa, start);
+	/* done, except for clearing out the tmp pointers */
+
+	stop->tmp = NULL;
+	cleartraverse(nfa, start);
+}
+
+/*
+ * removetraverse - recursive heart of removeconstraints
+ */
+static void
+removetraverse(struct nfa *nfa,
+			   struct state *s)
+{
+	struct arc *a;
+	struct arc *oa;
+
+	/* Since this is recursive, it could be driven to stack overflow */
+	if (STACK_TOO_DEEP(nfa->v->re))
+	{
+		NERR(REG_ETOOBIG);
+		return;
+	}
+
+	if (s->tmp != NULL)
+		return;					/* already done */
+
+	s->tmp = s;
+	for (a = s->outs; a != NULL && !NISERR(); a = oa)
+	{
+		removetraverse(nfa, a->to);
+		if (NISERR())
+			break;
+		oa = a->outchain;
+		switch (a->type)
+		{
+			case PLAIN:
+			case EMPTY:
+				/* nothing to do */
+				break;
+			case AHEAD:
+			case BEHIND:
+			case '^':
+			case '$':
+			case LACON:
+				/* replace it */
+				newarc(nfa, EMPTY, 0, s, a->to);
+				freearc(nfa, a);
+				break;
+			default:
+				NERR(REG_ASSERT);
+				break;
+		}
+	}
+}
+
 /*
  * cleartraverse - recursive cleanup for algorithms that leave tmp ptrs set
  */
diff --git a/src/backend/regex/regcomp.c b/src/backend/regex/regcomp.c
index 1f7fa513b2..3c7627a955 100644
--- a/src/backend/regex/regcomp.c
+++ b/src/backend/regex/regcomp.c
@@ -150,6 +150,8 @@ static void delsub(struct nfa *, struct state *, struct state *);
 static void deltraverse(struct nfa *, struct state *, struct state *);
 static void dupnfa(struct nfa *, struct state *, struct state *, struct state *, struct state *);
 static void duptraverse(struct nfa *, struct state *, struct state *);
+static void removeconstraints(struct nfa *, struct state *, struct state *);
+static void removetraverse(struct nfa *, struct state *);
 static void cleartraverse(struct nfa *, struct state *);
 static struct state *single_color_transition(struct state *, struct state *);
 static void specialcolors(struct nfa *);
@@ -1182,6 +1184,10 @@ parseqatom(struct vars *v,
 		dupnfa(v->nfa, v->subs[subno]->begin, v->subs[subno]->end,
 			   atom->begin, atom->end);
 		NOERR();
+
+		/* The backref node's NFA should not enforce any constraints */
+		removeconstraints(v->nfa, atom->begin, atom->end);
+		NOERR();
 	}
 
 	/*
diff --git a/src/test/modules/test_regex/expected/test_regex.out b/src/test/modules/test_regex/expected/test_regex.out
index 5d993f40c2..01d50ec1e3 100644
--- a/src/test/modules/test_regex/expected/test_regex.out
+++ b/src/test/modules/test_regex/expected/test_regex.out
@@ -2636,6 +2636,28 @@ select * from test_regex('^(.+)( \1)+$', 'abc abc abd', 'RP');
  {2,REG_UBACKREF,REG_UNONPOSIX}
 (1 row)
 
+-- back reference only matches the string, not any constraints
+select * from test_regex('(^\w+).*\1', 'abc abc abc', 'LRP');
+                 test_regex                 
+--------------------------------------------
+ {1,REG_UBACKREF,REG_UNONPOSIX,REG_ULOCALE}
+ {"abc abc abc",abc}
+(2 rows)
+
+select * from test_regex('(^\w+\M).*\1', 'abc abcd abd', 'LRP');
+                 test_regex                 
+--------------------------------------------
+ {1,REG_UBACKREF,REG_UNONPOSIX,REG_ULOCALE}
+ {"abc abc",abc}
+(2 rows)
+
+select * from test_regex('(\w+(?= )).*\1', 'abc abcd abd', 'HLRP');
+                         test_regex                         
+------------------------------------------------------------
+ {1,REG_UBACKREF,REG_ULOOKAROUND,REG_UNONPOSIX,REG_ULOCALE}
+ {"abc abc",abc}
+(2 rows)
+
 -- doing 15 "octal escapes vs back references"
 -- # initial zero is always octal
 -- expectMatch	15.1  MP	"a\\010b"	"a\bb"	"a\bb"
diff --git a/src/test/modules/test_regex/sql/test_regex.sql b/src/test/modules/test_regex/sql/test_regex.sql
index b99329391e..7f5bc6e418 100644
--- a/src/test/modules/test_regex/sql/test_regex.sql
+++ b/src/test/modules/test_regex/sql/test_regex.sql
@@ -770,6 +770,11 @@ select * from test_regex('^(.+)( \1)+$', 'abc abd abc', 'RP');
 -- expectNomatch	14.29 RP	{^(.+)( \1)+$}	{abc abc abd}
 select * from test_regex('^(.+)( \1)+$', 'abc abc abd', 'RP');
 
+-- back reference only matches the string, not any constraints
+select * from test_regex('(^\w+).*\1', 'abc abc abc', 'LRP');
+select * from test_regex('(^\w+\M).*\1', 'abc abcd abd', 'LRP');
+select * from test_regex('(\w+(?= )).*\1', 'abc abcd abd', 'HLRP');
+
 -- doing 15 "octal escapes vs back references"
 
 -- # initial zero is always octal
diff --git a/src/backend/regex/rege_dfa.c b/src/backend/regex/rege_dfa.c
index 1db52d1005..18f87c69d4 100644
--- a/src/backend/regex/rege_dfa.c
+++ b/src/backend/regex/rege_dfa.c
@@ -58,6 +58,19 @@ longest(struct vars *v,
 	if (hitstopp != NULL)
 		*hitstopp = 0;
 
+	/* if this is a backref to a known string, just match against that */
+	if (d->backno >= 0)
+	{
+		assert((size_t) d->backno < v->nmatch);
+		if (v->pmatch[d->backno].rm_so >= 0)
+		{
+			cp = dfa_backref(v, d, start, start, stop, false);
+			if (cp == v->stop && stop == v->stop && hitstopp != NULL)
+				*hitstopp = 1;
+			return cp;
+		}
+	}
+
 	/* fast path for matchall NFAs */
 	if (d->cnfa->flags & MATCHALL)
 	{
@@ -210,6 +223,20 @@ shortest(struct vars *v,
 	if (hitstopp != NULL)
 		*hitstopp = 0;
 
+	/* if this is a backref to a known string, just match against that */
+	if (d->backno >= 0)
+	{
+		assert((size_t) d->backno < v->nmatch);
+		if (v->pmatch[d->backno].rm_so >= 0)
+		{
+			cp = dfa_backref(v, d, start, min, max, true);
+			if (cp != NULL && coldp != NULL)
+				*coldp = start;
+			/* there is no case where we should set *hitstopp */
+			return cp;
+		}
+	}
+
 	/* fast path for matchall NFAs */
 	if (d->cnfa->flags & MATCHALL)
 	{
@@ -467,6 +494,94 @@ matchuntil(struct vars *v,
 	return 1;
 }
 
+/*
+ * dfa_backref - find best match length for a known backref string
+ *
+ * When the backref's referent is already available, we can deliver an exact
+ * answer with considerably less work than running the backref node's NFA.
+ *
+ * Return match endpoint for longest or shortest valid repeated match,
+ * or NULL if there is no valid match.
+ *
+ * Should be in sync with cbrdissect(), although that has the different task
+ * of checking a match to a predetermined section of the string.
+ */
+static chr *
+dfa_backref(struct vars *v,
+			struct dfa *d,
+			chr *start,			/* where the match should start */
+			chr *min,			/* match must end at or after here */
+			chr *max,			/* match must end at or before here */
+			bool shortest)
+{
+	int			n = d->backno;
+	int			backmin = d->backmin;
+	int			backmax = d->backmax;
+	size_t		numreps;
+	size_t		minreps;
+	size_t		maxreps;
+	size_t		brlen;
+	chr		   *brstring;
+	chr		   *p;
+
+	/* get the backreferenced string (caller should have checked this) */
+	if (v->pmatch[n].rm_so == -1)
+		return NULL;
+	brstring = v->start + v->pmatch[n].rm_so;
+	brlen = v->pmatch[n].rm_eo - v->pmatch[n].rm_so;
+
+	/* special-case zero-length backreference to avoid divide by zero */
+	if (brlen == 0)
+	{
+		/*
+		 * matches only a zero-length string, but any number of repetitions
+		 * can be considered to be present
+		 */
+		if (min == start && backmin <= backmax)
+			return start;
+		return NULL;
+	}
+
+	/*
+	 * convert min and max into numbers of possible repetitions of the backref
+	 * string, rounding appropriately
+	 */
+	if (min <= start)
+		minreps = 0;
+	else
+		minreps = (min - start - 1) / brlen + 1;
+	maxreps = (max - start) / brlen;
+
+	/* apply bounds, then see if there is any allowed match length */
+	if (minreps < backmin)
+		minreps = backmin;
+	if (backmax != DUPINF && maxreps > backmax)
+		maxreps = backmax;
+	if (maxreps < minreps)
+		return NULL;
+
+	/* quick exit if zero-repetitions match is valid and preferred */
+	if (shortest && minreps == 0)
+		return start;
+
+	/* okay, compare the actual string contents */
+	p = start;
+	numreps = 0;
+	while (numreps < maxreps)
+	{
+		if ((*v->g->compare) (brstring, p, brlen) != 0)
+			break;
+		p += brlen;
+		numreps++;
+		if (shortest && numreps >= minreps)
+			break;
+	}
+
+	if (numreps >= minreps)
+		return p;
+	return NULL;
+}
+
 /*
  * lastcold - determine last point at which no progress had been made
  */
@@ -563,6 +678,8 @@ newdfa(struct vars *v,
 	d->lastpost = NULL;
 	d->lastnopr = NULL;
 	d->search = d->ssets;
+	d->backno = -1;				/* may be set by caller */
+	d->backmin = d->backmax = 0;
 
 	/* initialization of sset fields is done as needed */
 
diff --git a/src/backend/regex/regexec.c b/src/backend/regex/regexec.c
index cf95989948..8d7777f8c6 100644
--- a/src/backend/regex/regexec.c
+++ b/src/backend/regex/regexec.c
@@ -77,6 +77,9 @@ struct dfa
 	chr		   *lastpost;		/* location of last cache-flushed success */
 	chr		   *lastnopr;		/* location of last cache-flushed NOPROGRESS */
 	struct sset *search;		/* replacement-search-pointer memory */
+	int			backno;			/* if DFA for a backref, subno it refers to */
+	short		backmin;		/* min repetitions for backref */
+	short		backmax;		/* max repetitions for backref */
 	bool		ismalloced;		/* should this struct dfa be freed? */
 	bool		arraysmalloced; /* should its subsidiary arrays be freed? */
 };
@@ -154,6 +157,7 @@ static int	creviterdissect(struct vars *, struct subre *, chr *, chr *);
 static chr *longest(struct vars *, struct dfa *, chr *, chr *, int *);
 static chr *shortest(struct vars *, struct dfa *, chr *, chr *, chr *, chr **, int *);
 static int	matchuntil(struct vars *, struct dfa *, chr *, struct sset **, chr **);
+static chr *dfa_backref(struct vars *, struct dfa *, chr *, chr *, chr *, bool);
 static chr *lastcold(struct vars *, struct dfa *);
 static struct dfa *newdfa(struct vars *, struct cnfa *, struct colormap *, struct smalldfa *);
 static void freedfa(struct dfa *);
@@ -342,13 +346,23 @@ static struct dfa *
 getsubdfa(struct vars *v,
 		  struct subre *t)
 {
-	if (v->subdfas[t->id] == NULL)
+	struct dfa *d = v->subdfas[t->id];
+
+	if (d == NULL)
 	{
-		v->subdfas[t->id] = newdfa(v, &t->cnfa, &v->g->cmap, DOMALLOC);
+		d = newdfa(v, &t->cnfa, &v->g->cmap, DOMALLOC);
 		if (ISERR())
 			return NULL;
+		/* set up additional info if this is a backref node */
+		if (t->op == 'b')
+		{
+			d->backno = t->backno;
+			d->backmin = t->min;
+			d->backmax = t->max;
+		}
+		v->subdfas[t->id] = d;
 	}
-	return v->subdfas[t->id];
+	return d;
 }
 
 /*
@@ -369,6 +383,7 @@ getladfa(struct vars *v,
 		v->ladfas[n] = newdfa(v, &sub->cnfa, &v->g->cmap, DOMALLOC);
 		if (ISERR())
 			return NULL;
+		/* a LACON can't contain a backref, so nothing else to do */
 	}
 	return v->ladfas[n];
 }
@@ -927,6 +942,9 @@ crevcondissect(struct vars *v,
 
 /*
  * cbrdissect - dissect match for backref node
+ *
+ * The backref match might already have been verified by dfa_backref(),
+ * but we don't know that for sure so must check it here.
  */
 static int						/* regexec return code */
 cbrdissect(struct vars *v,
--
-- PostgreSQL database dump
--

-- Dumped from database version 14devel
-- Dumped by pg_dump version 14devel

SET statement_timeout = 0;
SET lock_timeout = 0;
SET idle_in_transaction_session_timeout = 0;
SET client_encoding = 'UTF8';
SET standard_conforming_strings = on;
SELECT pg_catalog.set_config('search_path', '', false);
SET check_function_bodies = false;
SET xmloption = content;
SET client_min_messages = warning;
SET row_security = off;

SET default_tablespace = '';

SET default_table_access_method = heap;

--
-- Name: trouble; Type: TABLE; Schema: public; Owner: postgres
--

CREATE TABLE public.trouble (
    pattern text,
    subject text
);


ALTER TABLE public.trouble OWNER TO postgres;

--
-- Data for Name: trouble; Type: TABLE DATA; Schema: public; Owner: postgres
--

COPY public.trouble (pattern, subject) FROM stdin;
(["'`])(?:\\\\\\1|.)*?\\1       /*  */\nvar macegallery = 
"{\\"i18n\\":{\\"of\\":\\"of\\"},\\"html\\":\\"\\\\n<div 
class=\\\\\\"g1-gallery-wrapper g1-gallery-dark\\\\\\">\\\\n\\\\t<div 
class=\\\\\\"g1-gallery\\\\\\">\\\\n\\\\t\\\\t<div 
class=\\\\\\"g1-gallery-header\\\\\\">\\\\n\\\\t\\\\t\\\\t<div 
class=\\\\\\"g1-gallery-header-left\\\\\\">\\\\n\\\\t\\\\t\\\\t\\\\t<div 
class=\\\\\\"g1-gallery-logo\\\\\\">\\\\n\\\\t\\\\t\\\\t\\\\t\\\\t\\\\t\\\\t\\\\t<\\\\\\/div>\\\\n\\\\t\\\\t\\\\t\\\\t<div
 class=\\\\\\"g1-gallery-title g1-gamma 
g1-gamma-1st\\\\\\">{title}<\\\\\\/div>\\\\n\\\\t\\\\t\\\\t<\\\\\\/div>\\\\n\\\\t\\\\t\\\\t<div
 class=\\\\\\"g1-gallery-header-right\\\\\\">\\\\n\\\\t\\\\t\\\\t\\\\t<div 
class=\\\\\\"g1-gallery-back-to-slideshow\\\\\\">Back to 
slideshow<\\\\\\/div>\\\\n\\\\t\\\\t\\\\t\\\\t<div 
class=\\\\\\"g1-gallery-thumbs-button\\\\\\"><\\\\\\/div>\\\\n\\\\t\\\\t\\\\t\\\\t<div
 
class=\\\\\\"g1-gallery-numerator\\\\\\">{numerator}<\\\\\\/div>\\\\n\\\\t\\\\t\\\\t\\\\t<div
 
class=\\\\\\"g1-gallery-close-button\\\\\\"><\\\\\\/div>\\\\n\\\\t\\\\t\\\\t<\\\\\\/div>\\\\n\\\\t\\\\t<\\\\\\/div>\\\\n\\\\t\\\\t<div
 class=\\\\\\"g1-gallery-body\\\\\\">\\\\n\\\\t\\\\t\\\\t<div 
class=\\\\\\"g1-gallery-frames\\\\\\">\\\\n\\\\t\\\\t\\\\t\\\\t{frames}\\\\n\\\\t\\\\t\\\\t<\\\\\\/div>\\\\n\\\\t\\\\t\\\\t<div
 class=\\\\\\"g1-gallery-thumbnails32\\\\\\">\\\\n\\\\t\\\\t\\\\t\\\\t<div 
class=\\\\\\"g1-gallery-thumbnails-collection\\\\\\">\\\\n\\\\t\\\\t\\\\t\\\\t\\\\t{thumbnails32}\\\\n\\\\t\\\\t\\\\t\\\\t<\\\\\\/div>\\\\n\\\\t\\\\t\\\\t<\\\\\\/div>\\\\n\\\\t\\\\t\\\\t<div
 class=\\\\\\"g1-gallery-sidebar\\\\\\">\\\\n\\\\t\\\\t\\\\t\\\\t\\\\t<div 
class=\\\\\\"g1-gallery-shares\\\\\\">\\\\n\\\\t\\\\t\\\\t\\\\t\\\\t<\\\\\\/div>\\\\n\\\\t\\\\t\\\\t\\\\t\\\\t<div
 
class=\\\\\\"g1-gallery-ad\\\\\\"><\\\\\\/div>\\\\n\\\\t\\\\t\\\\t\\\\t\\\\t\\\\t\\\\t\\\\t\\\\t\\\\t\\\\t<div
 
class=\\\\\\"g1-gallery-thumbnails\\\\\\">\\\\n\\\\t\\\\t\\\\t\\\\t\\\\t\\\\t\\\\t<div
 
class=\\\\\\"g1-gallery-thumbnails-up\\\\\\"><\\\\\\/div>\\\\n\\\\t\\\\t\\\\t\\\\t\\\\t\\\\t\\\\t<div
 
class=\\\\\\"g1-gallery-thumbnails-collection\\\\\\">{thumbnails}<\\\\\\/div>\\\\n\\\\t\\\\t\\\\t\\\\t\\\\t\\\\t\\\\t<div
 
class=\\\\\\"g1-gallery-thumbnails-down\\\\\\"><\\\\\\/div>\\\\n\\\\t\\\\t\\\\t\\\\t\\\\t\\\\t<\\\\\\/div>\\\\n\\\\t\\\\t\\\\t\\\\t\\\\t\\\\t\\\\t\\\\t<\\\\\\/div>\\\\n\\\\t\\\\t<\\\\\\/div>\\\\n\\\\t<\\\\\\/div>\\\\n<\\\\\\/div>\\\\n\\",\\"shares\\":\\"<script
 type=\\\\\\"text\\\\\\/javascript\\\\\\">\\\\n\\\\t\\\\t\\\\t(function () 
{\\\\n\\\\t\\\\t\\\\t\\\\tvar triggerOnLoad = 
false;\\\\n\\\\n\\\\t\\\\t\\\\t\\\\twindow.apiShareOnFB = function() 
{\\\\n\\\\t\\\\t\\\\t\\\\t\\\\tjQuery('body').trigger('snaxFbNotLoaded');\\\\n\\\\t\\\\t\\\\t\\\\t\\\\ttriggerOnLoad
 = true;\\\\n\\\\t\\\\t\\\\t\\\\t};\\\\n\\\\n\\\\t\\\\t\\\\t\\\\tvar 
_fbAsyncInitGallery = 
window.fbAsyncInitGallery;\\\\n\\\\n\\\\t\\\\t\\\\t\\\\twindow.fbAsyncInitGallery
 = function() 
{\\\\n\\\\t\\\\t\\\\t\\\\t\\\\tFB.init({\\\\n\\\\t\\\\t\\\\t\\\\t\\\\t\\\\tappId
      : '',\\\\n\\\\t\\\\t\\\\t\\\\t\\\\t\\\\txfbml      : 
true,\\\\n\\\\t\\\\t\\\\t\\\\t\\\\t\\\\tversion    : 
'v3.0'\\\\n\\\\t\\\\t\\\\t\\\\t\\\\t});\\\\n\\\\t\\\\t\\\\t\\\\t\\\\twindow.apiShareOnFB_mace_replace_unique
 = function() {\\\\n\\\\t\\\\t\\\\t\\\\t\\\\t\\\\tvar shareTitle \\\\t\\\\t    
= \\\\\\"mace_replace_noesc_title\\\\\\"; \\\\\\/\\\\\\/ Double quotes to allow 
' chars.\\\\n\\\\t\\\\t\\\\t\\\\t\\\\t\\\\tvar shareDescription\\\\t= 
'';\\\\n\\\\t\\\\t\\\\t\\\\t\\\\t\\\\tvar shareImage\\\\t        = 
'mace_replace_noesc_image_url';\\\\n\\\\n\\\\t\\\\t\\\\t\\\\t\\\\t\\\\tFB.login(function(response)
 {\\\\n\\\\t\\\\t\\\\t\\\\t\\\\t\\\\t\\\\tif (response.status === 'connected') 
{\\\\n\\\\t\\\\t\\\\t\\\\t\\\\t\\\\t\\\\t\\\\tvar objectToShare = 
{\\\\n\\\\t\\\\t\\\\t\\\\t\\\\t\\\\t\\\\t\\\\t\\\\t'og:url':           
'mace_replace_noesc_shortlink', \\\\\\/\\\\\\/ Url to 
share.\\\\n\\\\t\\\\t\\\\t\\\\t\\\\t\\\\t\\\\t\\\\t\\\\t'og:title':         
shareTitle,\\\\n\\\\t\\\\t\\\\t\\\\t\\\\t\\\\t\\\\t\\\\t\\\\t'og:description':  
 
shareDescription\\\\n\\\\t\\\\t\\\\t\\\\t\\\\t\\\\t\\\\t\\\\t};\\\\n\\\\n\\\\t\\\\t\\\\t\\\\t\\\\t\\\\t\\\\t\\\\t\\\\\\/\\\\\\/
 Add image only if set. FB fails 
otherwise.\\\\n\\\\t\\\\t\\\\t\\\\t\\\\t\\\\t\\\\t\\\\tif (shareImage) 
{\\\\n\\\\t\\\\t\\\\t\\\\t\\\\t\\\\t\\\\t\\\\t\\\\tobjectToShare['og:image'] = 
shareImage;\\\\n\\\\t\\\\t\\\\t\\\\t\\\\t\\\\t\\\\t\\\\t}\\\\n\\\\n\\\\t\\\\t\\\\t\\\\t\\\\t\\\\t\\\\t\\\\tFB.ui({\\\\n\\\\t\\\\t\\\\t\\\\t\\\\t\\\\t\\\\t\\\\t\\\\t\\\\tmethod:
 
'share_open_graph',\\\\n\\\\t\\\\t\\\\t\\\\t\\\\t\\\\t\\\\t\\\\t\\\\t\\\\taction_type:
 
'og.shares',\\\\n\\\\t\\\\t\\\\t\\\\t\\\\t\\\\t\\\\t\\\\t\\\\t\\\\taction_properties:
 
JSON.stringify({\\\\n\\\\t\\\\t\\\\t\\\\t\\\\t\\\\t\\\\t\\\\t\\\\t\\\\t\\\\tobject
 : 
objectToShare\\\\n\\\\t\\\\t\\\\t\\\\t\\\\t\\\\t\\\\t\\\\t\\\\t\\\\t})\\\\n\\\\t\\\\t\\\\t\\\\t\\\\t\\\\t\\\\t\\\\t\\\\t},\\\\n\\\\t\\\\t\\\\t\\\\t\\\\t\\\\t\\\\t\\\\t\\\\t\\\\\\/\\\\\\/
 callback\\\\n\\\\t\\\\t\\\\t\\\\t\\\\t\\\\t\\\\t\\\\t\\\\tfunction(response) 
{\\\\n\\\\t\\\\t\\\\t\\\\t\\\\t\\\\t\\\\t\\\\t\\\\t});\\\\n\\\\t\\\\t\\\\t\\\\t\\\\t\\\\t\\\\t}\\\\n\\\\t\\\\t\\\\t\\\\t\\\\t\\\\t});\\\\n\\\\t\\\\t\\\\t\\\\t\\\\t};\\\\n\\\\n\\\\t\\\\t\\\\t\\\\t\\\\t\\\\\\/\\\\\\/
 Fire original callback.\\\\n\\\\t\\\\t\\\\t\\\\t\\\\tif (typeof 
_fbAsyncInitGallery === 'function') 
{\\\\n\\\\t\\\\t\\\\t\\\\t\\\\t\\\\t_fbAsyncInitGallery();\\\\n\\\\t\\\\t\\\\t\\\\t\\\\t}\\\\n\\\\n\\\\t\\\\t\\\\t\\\\t\\\\t\\\\\\/\\\\\\/
 Open share popup as soon as possible, after loading FB 
SDK.`\\\\n\\\\t\\\\t\\\\t\\\\t\\\\tif (triggerOnLoad) 
{\\\\n\\\\t\\\\t\\\\t\\\\t\\\\t\\\\tsetTimeout(function() 
{\\\\n\\\\t\\\\t\\\\t\\\\t\\\\t\\\\t\\\\tapiShareOnFB();\\\\n\\\\t\\\\t\\\\t\\\\t\\\\t\\\\t},
 
1000);\\\\n\\\\t\\\\t\\\\t\\\\t\\\\t}\\\\n\\\\t\\\\t\\\\t\\\\t};\\\\n\\\\n\\\\t\\\\t\\\\t\\\\t\\\\\\/\\\\\\/
 JS SDK loaded before we hook into it. Trigger callback 
now.\\\\n\\\\t\\\\t\\\\t\\\\tif (typeof window.FB !== 'undefined') 
{\\\\n\\\\t\\\\t\\\\t\\\\t\\\\twindow.fbAsyncInitGallery();\\\\n\\\\t\\\\t\\\\t\\\\t}\\\\n\\\\t\\\\t\\\\t\\\\tjQuery('body').on('maceGalleryItemChanged',
 
function(){\\\\n\\\\t\\\\t\\\\t\\\\t\\\\twindow.fbAsyncInitGallery();\\\\n\\\\t\\\\t\\\\t\\\\t});\\\\n\\\\t\\\\t\\\\t})();\\\\n\\\\t\\\\t<\\\\\\/script>\\\\n\\\\n<a
 class=\\\\\\"g1-gallery-share g1-gallery-share-fb\\\\\\" href=\\\\\\"#\\\\\\" 
title=\\\\\\"Share on Facebook\\\\\\" 
onclick=\\\\\\"apiShareOnFB_mace_replace_unique(); return false;\\\\\\" 
target=\\\\\\"_blank\\\\\\" rel=\\\\\\"nofollow\\\\\\">Share on 
Facebook<\\\\\\/a><a class=\\\\\\"g1-gallery-share 
g1-gallery-share-twitter\\\\\\" 
href=\\\\\\"https:\\\\\\/\\\\\\/twitter.com\\\\\\/intent\\\\\\/tweet?text=mace_replace_title&url=mace_replace_shortlink\\\\\\"
 title=\\\\\\"Share on Twitter\\\\\\" target=\\\\\\"_blank\\\\\\" 
rel=\\\\\\"nofollow\\\\\\">Share on Twitter<\\\\\\/a><a 
class=\\\\\\"g1-gallery-share g1-gallery-share-pinterest\\\\\\" 
href=\\\\\\"https:\\\\\\/\\\\\\/pinterest.com\\\\\\/pin\\\\\\/create\\\\\\/button\\\\\\/?url=mace_replace_shortlink&amp;description=mace_replace_title&amp;media=mace_replace_image_url\\\\\\"
 title=\\\\\\"Share on Pinterest\\\\\\" target=\\\\\\"_blank\\\\\\" 
rel=\\\\\\"nofollow\\\\\\">Share on Pinterest<\\\\\\/a>\\"}";\n/*  */
\.


--
-- PostgreSQL database dump complete
--

Reply via email to