diff --git a/about.php b/about.php new file mode 100644 index 0000000..18886a0 --- /dev/null +++ b/about.php @@ -0,0 +1,65 @@ + + + + + Elgg - Open Source Social Networking Engine. + + + + + + + + + +
+
+ +
+

About

+

Elgg is an award-winning open source social networking engine that provides a robust framework on which to build all kinds of social environments, from a campus wide social network for your university, school or college or an internal collaborative platform for your organization through to a brand-building communications tool for your company and its clients.

+

+ Bossie award + Elgg was voted best open source social networking platform in 2008.

+
+
+
+
+
+ +
+ + + + \ No newline at end of file diff --git a/css/main-old.css b/css/main-old.css new file mode 100644 index 0000000..2de072e --- /dev/null +++ b/css/main-old.css @@ -0,0 +1,432 @@ +/* + + elgg.org + v0.1 + + dark blue #00487d + light blue #e5eff6 + +*/ + + +body { + padding: 0; + margin: 0; + font-size:80%; + color:#555; + font-family: Arial, Helvetica, Verdana, sans-serif; + line-height:1.8em; + text-align:center; + background: url(../images/page_background.gif) repeat-x top left; +} + +a { + color: #00487d; + text-decoration:none; + font-weight: bold; +} + +a:hover { + text-decoration:underline; +} + +ul li { + +} + +#header { + height:72px; + padding:0; + margin:0; +} + +#header-inner { + width:940px; + margin:auto; + text-align:left; + padding:0; +} + +#header-inner h1 { + color:#fff; + margin:0 0 0 0; + padding:0; + display:none; +} + +#header-inner #logo { + margin:0; + padding:0; + background: url(../images/elgg_org_logo.gif) no-repeat top left; + width:121px; + height:72px; +} + +#menu { + padding:0; + margin:0 auto; + text-align:left; + height:30px; +} + +#menu-inner { + width:940px; + text-align:right; + margin:0 auto; + padding:0; +} + +#menu a:active { outline: none; } +#menu a:focus { -moz-outline-style: none; } + +#menu a { + float:right; + margin:0; + padding:0 0 0 10px; + text-decoration:none; + font-weight: bold; + font-size: 110%; +} +#menu a span { + float:left; + display:block; + padding:3px 14px 0px 3px; + height:27px; + margin:0; + color:#547faa; +} + +/* IE 6 & 7 fix */ +* html #menu a span { + height:30px; +} + +#menu a:hover span { + color:#547faa; +} +#menu a:hover { + color:#547faa; +} + +#menu a.selected { + background:transparent url(../images/tab_left_selected.gif) no-repeat left top; +} +#menu a.selected span { + background:transparent url(../images/tab_right_selected.gif) no-repeat right top; + color:#00487d; +} + + +#spotlight { + min-height: 206px; + /*height:auto;*/ + margin:0; + padding:0; + background: #e5eff6 url(../images/spotlightback.jpg) no-repeat bottom center; +} + +/* IE 6 & 7 fix */ +* html #spotlight { + height:206px; +} + +#spotlight-inner { + margin:auto; + width:940px; + text-align:left; + +} + +#spotlight #description { + width:520px; + float:left; + font-size:1.5em; + line-height: 1.3em; + font-weight: bold; + font-family: Helvetica, sans-serif; + color:#666666; +} + +/* IE6&7 fix */ +* html #spotlight #description { + padding-top:17px; +} + +#spotlight #description span { + color:#00487d; +} + + +#whiterow { + min-height: 207px; + height:auto; + margin:0 auto; + padding:0; + background: #ffffff; + text-align: left; + clear:both; +} + +#footerrow { + min-height: 207px; + height:auto; + margin:0 auto; + padding:10px 0 0 0; + background: #e5eff6 url(../images/bottomback.png) repeat-x top left; + text-align: left; + clear:both; +} + +#page-contents { + width:940px; + margin:auto; + padding:20px 0 0 0; + text-align:left; + background:#fff; +} + +#page-contents p { + font-size:0.9em; +} + +#page-contents h1 { + border-bottom:1px solid #666666; + font-size:20px; + padding-left:4px; + margin:0; +} + +#page-contents h2 { + margin:10px 0 10px 0; + padding:5px; + font-size:20px; + border-bottom:1px solid #666666; + background:#d8dfea; +} + +#page-contents #developers, +#page-contents #categories { + border-left:0px solid #ccc; + font-size:0.9em; + width:200px; + padding-left:4px; + margin:0 20px 0 0; +} + +#page-contents #developers h3, +#page-contents #categories h3 { + font-size:14px; + color:#433c2a; +} + +#page-contents #developers li, +#page-contents #categories li { + font-size:0.9em; + list-style:none; +} + +#page-contents #developers ul, +#page-contents #categories ul { + margin:4px 0 0 0; + padding:0; +} + +#spotlight #page-options { + font-size:0.9em; + width:200px; + padding:10px; + margin:0 20px 0 0; + +} + +#spotlight #page-options li { + font-size:0.9em; + list-style:none; + margin:5px 0 5px 0; + border-bottom:1px solid #cccccc; +} + +#spotlight #page-options ul { + margin:4px 0 0 0; + padding:0; +} + +#spotlight h2 { + margin:0 0 10px 0; + padding:10px 0 0 0; + font-size:20px; +} + +#page-contents #actual-contents, +#page-contents #spotlight { + width:630px; +} + +#spotlight #actual-contents p { + margin:10px 20px 10px 0; +} + +#page-contents #actual-contents p { + font-size:0.8em; + margin:10px 20px 10px 0; + line-height:1.8em; +} + +#page-contents #actual-contents h3 { + font-size:0.9em; +} + +#page-contents #actual-contents .coloured { + padding:0 5px 0 5px; + background:#e5f1f4; + border:1px solid #ddd; +} + +#page-contents .plugin-box h3 { + font-size:12px; + border-bottom:1px solid #ccc; +} + +#forum-quickstart { + float:right; + width:200px; + padding:10px; + border:1px solid #ccc; + background:#efefef; +} + +#forum-quickstart p, ul { + padding:0; + margin:0; +} + +#forum-quickstart li { + list-style:none; +} + + +#contents { + background:#3BB1BA; + margin-bottom:20px; +} + +.products { + text-align:left; +} + +.blurb { + padding:10px; + color:#fff; + font-size: 20px; + text-align: left; + text-align:justify; + width:790px; + margin:auto; + font-weight:bold; +} + +.front-products { + margin:0 0 20px 0; + padding:0px; + border:0px solid #ccc; + width:330px; + /*height:100px;*/ +} + +.front-products ul { + margin:0 0 5px 15px; + padding:0; + list-style: square; + font-size:13px; +} + +.front-products li { + padding:3px 0 3px 0; +} + +.front-products h3 { + font-size:20px; + letter-spacing: -0.05em; + color:#00487d; + margin:20px 20px 10px 30px; + padding:0 0 5px 0; + border-bottom:1px dashed #00487d; +} + +.front-products p { + font-size:13px; + line-height: 18px; +} + +.front-products .leftpad { + padding-left:30px; + padding-right:20px; +} + +.front-products p.hiring { + background:#555; + color:#fff; + padding:2px; +} + +#footer { + text-align:center; + margin: auto; + height:60px; + background: #00487d url(../images/footerback.png) repeat-x top left; + clear:both; + border-top: 1px solid #e5eff6; + color:#e5eff6; + padding-top: 24px; +} +#footer p { + color:#e5eff6; + font-size: 12px; + font-weight: normal; +} + +#footer a { + color:#e5eff6; +} +#footer a:hover { + text-decoration: underline; + color:#ffffff; +} + +form { + margin:0 0 0 30px; + padding:0; +} + +input { + border:1px solid #BBBBBB; + color:#666666; + font-size:15px; + font-weight:bold; + font-family:inherit; + margin:0; + padding:4px; + width:270px; + height:30px; +} + +input.submitbutton { + color:#00487d; + border:1px solid #BBBBBB; + background: #ffffff url(../images/button_grad.png) repeat-x bottom left; + font-size:15px; + font-weight:bold; + margin:10px 0 0 0; + padding:4px 10px 5px 10px; + cursor:pointer; + width:auto; +} +input.submitbutton:hover { + color:#ffffff; + background: #00487d; +} + + + + + diff --git a/css/main.css b/css/main.css new file mode 100644 index 0000000..a7bc0dd --- /dev/null +++ b/css/main.css @@ -0,0 +1,616 @@ +/* + elgg.org + v1.0 + + dark blue #00487d + light blue #e5eff6 +*/ + +html, body, div, span, applet, object, iframe, +h1, h2, h3, h4, h5, h6, p, blockquote, pre, +a, abbr, acronym, address, big, cite, code, +del, dfn, em, font, img, ins, kbd, q, s, samp, +small, strike, strong, sub, sup, tt, var, +dl, dt, dd, ol, ul, li, +fieldset, form, label, legend, +table, caption, tbody, tfoot, thead, tr, th, td { + margin: 0; + padding: 0; + border: 0; + outline: 0; + font-weight: inherit; + font-style: inherit; + font-size: 100%; + font-family: inherit; + vertical-align: top; +} + +body { + text-align:center; + margin:0 auto; + padding:0; + font: 0.9em/1.3 "Lucida Grande", "Lucida Sans Unicode", Verdana, Arial, sans-serif; + color:#474747; + background:#e5eff6 url(../images/page_background.gif) repeat-x top left; +} + +a { + /* color: #00487d; */ + color: #599ac6; + text-decoration:none; + font-weight: bold; + -moz-outline-style: none; + outline: none; +} + +a:hover { color: #00487d; text-decoration:underline; } + +p { padding:4px 0 4px 0; } + +small {font-size: 85%;} + +h1, h2, h3, h4, h5, h6 { font-weight: bold; line-height: normal; color:#00487d; } + +h1 { font-size: 1.8em; } +h2 { font-size: 1.5em; } +h3 { font-size: 1.2em; } +h4 { font-size: 1.0em; } +h5 { font-size: 0.9em; } +h6 { font-size: 0.8em; } + +ul, ol { list-style-position: inside; } + +.clearfloat { clear:both;height:0;font-size: 1px;line-height: 0px; } + +/* *************************************** + PAGE STRUCTURE +*************************************** */ +#header { + height:72px; + padding:0; + margin:0; +} +#header-inner { + width:940px; + margin:auto; + text-align:left; + padding:0; +} +#header-inner h1 { + color:#fff; + margin:0 0 0 0; + padding:0; + display:none; +} +#header-inner #logo { + margin:0; + padding:0; + background: url(../images/elgg_org_logo.gif) no-repeat top left; + width:121px; + height:72px; +} +#footer { + text-align:center; + height:60px; + margin-top:40px; + background: #00487d url(../images/footerback.png) repeat-x top left; + border-top: 1px solid #e5eff6; + color:#e5eff6; + padding-top: 24px; +} +#spotlight { + text-align:left; + background:white; + margin: 24px auto 0 auto; + padding:10px 0 0 0; + min-height:100px; + width:940px; + border-top:1px solid #eeeeee; + border-left:1px solid #eeeeee; + border-bottom:1px solid #cccccc; + border-right:1px solid #cccccc; + -webkit-border-radius: 12px; + -moz-border-radius: 12px; +} +#spotlight #description { + width:436px; + padding:10px 0 10px 20px; + float:left; +} +#spotlight #slides { + width:484px; + height:241px; + float:right; +} +#spotlight #introduction { + padding:0 20px 10px 0; +} +/* IE 6 & 7 fix */ +* html #spotlight { + /* height:206px; */ +} +/* IE6&7 fix */ +* html #spotlight #description { + /* padding-top:17px; */ +} +#readmore { display:hidden; margin-top: 10px; } + + +/* *************************************** + page contents styles +*************************************** */ +.roundedbox_pagewidth { + text-align:left; + background:white; + padding:10px 0 10px 0; + margin: 24px auto 0 auto; + width:940px; + min-height:100px; + border-top:1px solid #eeeeee; + border-left:1px solid #eeeeee; + border-bottom:1px solid #cccccc; + border-right:1px solid #cccccc; + -webkit-border-radius: 12px; + -moz-border-radius: 12px; +} +.roundedbox_container { + padding:0; + margin: 24px auto 0 auto; + width:940px; + text-align:left; +} +.roundedbox_halfpagewidth { + float:left; + text-align:left; + background:white; + padding:10px; + min-height:100px; + width:436px; + border-top:1px solid #eeeeee; + border-left:1px solid #eeeeee; + border-bottom:1px solid #cccccc; + border-right:1px solid #cccccc; + -webkit-border-radius: 12px; + -moz-border-radius: 12px; +} +.leftbox { + margin-right:24px; +} +.innerbox_quarterpagewidth { + border-right:1px solid #dedede; + width:204px; + float:left; + padding:0 15px 0 15px; + text-align:left; + + min-height:135px; +} +.noborder { + border:none; +} +.innerbox_quarterpagewidth h3 { + text-align: left; + margin-bottom:10px; +} +.innerbox_quarterpagewidth li { + list-style:none; + padding:0 0 4px 0; +} +.innerbox_thirdpagewidth { + border-right:1px solid #dedede; + padding:0 20px 0 20px; +} +.innerbox_thirdpagewidth_endbox { + padding:0 20px 0 20px; +} + +.dividerline { margin:10px 0 10px 0; border-bottom:1px solid #cccccc;height:1px; } + +/* hosting page */ +.hosting_company { + margin:10px 20px 20px 0px; + padding:4px 50px 1px 10px; + background: #e5eff6; + -webkit-border-radius: 8px; + -moz-border-radius: 8px; +} + .hosting_company p { + margin:0; + padding:4px 0 4px 0; + line-height: 1.1em; +} + +#footer p { + color:#e5eff6; + font-size: 12px; + font-weight: normal; + padding-top:18px; +} + +#footer a { + color:#e5eff6; +} +#footer a:hover { + text-decoration: underline; + color:#ffffff; +} + +/* *************************************** + home page +*************************************** */ +#homepage #spotlight { + background: #00487d url(../images/background.gif) no-repeat 20px top; + border-top:1px solid #00487d; + border-left:1px solid #00487d; + border-bottom:1px solid #00487d; + border-right:1px solid #00487d; + /* fff065 ffc855 d2e6f1 55d2ff */ +} +#homepage #spotlight #description h2 { + color: white; +} +#homepage #spotlight #description h3 { + color: #599ac6; +} +#homepage .roundedbox_halfpagewidth { + min-height:166px; +} +#homepage .innerbox_quarterpagewidth p { + text-align: justify; + font-size: 85%; +} +#homepage .elgg_sites { + margin:6px 10px 4px 0; +} +/* IE 6 & 7 fix */ +* html #homepage .elgg_sites { margin:6px 4px 4px 0; } +*:first-child+html #homepage .elgg_sites { margin:6px 4px 4px 0; } + +/* *************************************** + about page +*************************************** */ +.shortcutmenu { margin-bottom:20px;padding-bottom:8px; border-bottom:1px solid #cccccc; } +.shortcutmenu a { margin-right:15px;margin-bottom:20px; } +#about #spotlight h2 { margin:0 0 0 20px; } +#about .roundedbox_halfpagewidth { margin:20px; width:407px; } +#about .teaminfo { min-height:20px; } +#about .teaminfo .readmorelink { padding-left:20px; } +#about .tour { width:900px; padding-left:20px; padding-right:20px; } +#about .morefeatures { width:900px; padding:20px; } +#about .tour table td.rightcolumn {width:380px; text-align: right;} +#about .morefeatures .more_content { margin:0 0 10px 0;padding:0 0 10px 0; border-bottom:1px solid #cccccc; } +#about a.screencast { + margin-top:20px; + border:1px solid #ccc; + background: white; + padding:2px 10px 2px 10px; + -webkit-border-radius: 6px; + -moz-border-radius: 6px; +} +#about a.screencast:hover { + background:#00487d; + border:1px solid #00487d; + color:white; + text-decoration: none; +} +a.curveriderLink { + text-decoration: none; + margin: 0; + background:#e5eff6; + color:#00487d; + padding:2px 6px 2px 6px; + font-weight: bold; + -webkit-border-radius: 10px; + -moz-border-radius: 10px; +} +a.curveriderLink:hover { + text-decoration: none; + background:#00487d; + color:white; +} + +/* *************************************** + download page +*************************************** */ +.gpl_license { + margin:20px 0 10px 0px; + padding:2px 8px 2px 8px; + background: #e5eff6; + -webkit-border-radius: 8px; + -moz-border-radius: 8px; +} +/* *************************************** + plugins page +*************************************** */ +#plugins_table ul { + list-style-position: outside; + list-style: none; + padding: 4px 0 0 0; + margin: 0; +} +#plugins_table ul li { + padding: 0 0 10px 0; +} + +/* *************************************** + spotlight menu +*************************************** */ +#spotlight #page-options { + width:180px; + padding:0 0 10px 20px; + margin:0 125px 0 0; +} +#spotlight #page-options ul { + list-style-position: outside; + list-style: none; + padding: 0; + margin: 0; +} +#spotlight #page-options ul li.menuselected a { + background: #00487d; + color:white; +} +#spotlight #page-options ul li.menuselected a:hover { + background: #00487d; + color:white; +} +#spotlight #page-options ul li a { + text-decoration: none; + display: block; + margin: 2px 0 0 0; + color:#00487d; + padding:4px 6px 4px 10px; + font-weight: bold; + line-height: 1.1em; + -webkit-border-radius: 10px; + -moz-border-radius: 10px; +} +#spotlight #page-options ul li a:hover { + color:white; + background: #00487d; +} + +/* *************************************** + elgg.org tabbed menu +*************************************** */ +#menu { + padding:0; + margin:0 auto; + text-align:left; + height:30px; +} +#menu-inner { + width:940px; + text-align:right; + margin:0 auto; + padding:0; +} +#menu-inner a span { cursor: pointer; } +#menu a:active { outline: none; } +#menu a:focus { -moz-outline-style: none; } +#menu a { + float:right; + margin:0; + padding:0 0 0 10px; + text-decoration:none; + font-weight: bold; + font-size: 100%; +} +#menu a span { + float:left; + display:block; + padding:5px 14px 0px 3px; + height:25px; + margin:0; + color:#ffffff; + /* color:#547faa;*/ +} +#menu a.disabled span { + color:#547faa; +} +#menu a.disabled { + color:#547faa; +} +#menu a.disabled:hover { + color:#547faa; +} +#menu a.disabled:hover span { + color:#547faa; +} +/* IE 6 */ +* html #menu a span { + height:22px; +} +#menu a:hover span { + color:#00487d; +} +#menu a:hover { + color:#00487d; +} +#menu a.selected { + background:transparent url(../images/tab_left_selected.gif) no-repeat left top; +} +#menu a.selected span { + background:transparent url(../images/tab_right_selected.gif) no-repeat right top; + color:#00487d; +} + +/* *************************************** + form elements +*************************************** */ +input { + border:1px solid #BBBBBB; + color:#666666; + font-size:15px; + font-weight:bold; + font-family:inherit; + margin:0; + padding:4px; + width:270px; + height:30px; +} + +input.submitbutton { + color:#00487d; + border:1px solid #BBBBBB; + background: #ffffff url(../images/button_grad.png) repeat-x bottom left; + font-size:15px; + font-weight:bold; + margin:10px 0 0 0; + padding:4px 10px 5px 10px; + cursor:pointer; + width:auto; +} +input.submitbutton:hover { + color:#ffffff; + background: #00487d; +} + +#paypal input { + width:160px; + height:47px; +} + +/* GOOGLE SEARCH */ +#cse-search-box { + float:right; + width:auto; + height:auto; + top:20px; + right:36px; + position: absolute; +} +#cse-search-box input[type="text"] { + height:25px; + background-image: none !important; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border:3px solid white; + padding:0; + margin:3px; +} +#cse-search-box input[type="submit"] { + font: 13px/100% Arial, Helvetica, sans-serif; + font-weight: bold; + color: white; + background:#547faa; + border: 3px solid #547faa; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + width: auto; + height: 25px; + padding: 1px; + margin:3px; + cursor: pointer; +} +#cse-search-box input[type="submit"]:hover { + color: #00487D; + background:white; + border: 3px solid white; + cursor: pointer; +} + +/* PC IE 6&7 google search rules */ +* html #cse-search-box { + +} +* html #cse-search-box input { + height:25px; + background-image: none !important; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border:3px solid white; + padding:0; + margin:3px; +} +* html #cse-search-box input.gsearchsubmit { + font: 13px/100% Arial, Helvetica, sans-serif; + font-weight: bold; + color: white; + background:#547faa; + border: 3px solid #547faa; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + width: auto; + height: 25px; + padding: 1px; + margin:3px; + cursor: pointer; +} +/* end PC IE google search rules */ + +/* Dave's new edits */ + +#usecases { + margin:0 10px 10px 10px; +} + +#usecases li { + line-height:1.3em; + color:#666666; + padding:5px 0 0px 15px; + margin:0; + background:transparent url(http://elgg.com/images/bullet_arrow_sml.gif) no-repeat scroll left 9px; + list-style: none; +} + +.rhs_content_column .sidebar_box { + padding: 0 0 5px 0; + width:297px; + background: url(http://elgg.com/images/sidebar_bottom_back.gif) no-repeat left bottom; +} +.rhs_content_column .sidebar_box h1 { + background: url(http://elgg.com/images/sidebar_header_back.gif) no-repeat left 30px; + font-size: 1.4em; + padding:40px 0 5px 10px; +} +.rhs_content_column .sidebar_box_content { + background: url(http://elgg.com/images/sidebar_middle_back.gif) no-repeat left top; + padding:0 10px 10px 10px; + font-size: 85%; +} + +.main_content_table .icon { + float:left; + padding: 20px 30px 10px 0; +} +#usecases h2.solutions_intro { + padding: 20px 0 0 0; + line-height:1.3em; + font-size: 1.8em; + color:#6699cc; +} + +#usecases h2.bullethead { + padding:30px 0 0px 0; + font-size:1.3em; + margin:10px 0 0 0; +} + +.thirdpagewidth_standalonebox { + background:white; + width:268px; + float:left; + margin:0 20px 0 0; + padding:10px 10px 10px 20px; + min-height:120px; + border-top:1px solid #eeeeee; + border-left:1px solid #eeeeee; + border-bottom:1px solid #cccccc; + border-right:1px solid #cccccc; + -webkit-border-radius: 12px; + -moz-border-radius: 12px; +} +.thirdpagewidth_standalonebox.endbox { + margin-right:0; +} +.thirdpagewidth_standalonebox h2 a { + color: #00487d; +} +.thirdpagewidth_standalonebox h2 a:hover { + color: #00487d; + text-decoration: none; +} + + + diff --git a/css/main_v12.css b/css/main_v12.css new file mode 100644 index 0000000..eeeffff --- /dev/null +++ b/css/main_v12.css @@ -0,0 +1,652 @@ +/* + + elgg.org + v0.2 + + dark blue #00487d + light blue #e5eff6 + +*/ + + +body { + padding: 0; + margin: 0; + font-size:80%; + color:#555; + font-family: Arial, Helvetica, Verdana, sans-serif; + line-height:1.8em; + text-align:center; + background: url(../images/page_background.gif) repeat-x top left; +} + +a { + color: #00487d; + text-decoration:none; + font-weight: bold; +} + +a:hover { + text-decoration:underline; +} + +ul li { + +} + +#header { + height:72px; + padding:0; + margin:0; +} + +#header-inner { + width:940px; + margin:auto; + text-align:left; + padding:0; +} + +#header-inner h1 { + color:#fff; + margin:0 0 0 0; + padding:0; + display:none; +} + +#header-inner #logo { + margin:0; + padding:0; + background: url(/images/elgg_org_logo.gif) no-repeat top left; + width:121px; + height:72px; +} + +#menu { + padding:0; + margin:0 auto; + text-align:left; + height:30px; +} + +#menu-inner { + width:940px; + text-align:right; + margin:0 auto; + padding:0; +} +#menu-inner a span { cursor: pointer; } +#menu a:active { outline: none; } +#menu a:focus { -moz-outline-style: none; } + +#menu a { + float:right; + margin:0; + padding:0 0 0 10px; + text-decoration:none; + font-weight: bold; + font-size: 110%; +} +#menu a span { + float:left; + display:block; + padding:3px 14px 0px 3px; + height:27px; + margin:0; + color:#ffffff; + /* color:#547faa;*/ +} +#menu a.disabled span { + color:#547faa; +} +#menu a.disabled { + color:#547faa; +} +#menu a.disabled:hover { + color:#547faa; +} +#menu a.disabled:hover span { + color:#547faa; +} + +/* IE 6 & 7 fix */ +* html #menu a span { + height:30px; +} + +#menu a:hover span { + color:#00487d; +} +#menu a:hover { + color:#00487d; +} + +#menu a.selected { + background:transparent url(../images/tab_left_selected.gif) no-repeat left top; +} +#menu a.selected span { + background:transparent url(../images/tab_right_selected.gif) no-repeat right top; + color:#00487d; +} + + +#spotlight { + min-height: 206px; + margin:0; + padding:0; + background: #e5eff6 url(../images/spotlightback_plain.jpg) no-repeat bottom center; +} + +#homepage #spotlight { + background: #e5eff6 url(../images/spotlightback_homepage.jpg) no-repeat bottom center; +} + +#themes #spotlight { + background:#E5EFF6 url(../images/spotlightthemesback.jpg) no-repeat center bottom; +} + +#themes #spotlight #actual-contents { + width:500px; +} + +/* IE 6 & 7 fix */ +* html #spotlight { + height:206px; +} + +#spotlight-inner { + margin:auto; + width:940px; + text-align:left; + +} + +#spotlight #description { + width:520px; + float:left; + font-size:1.5em; + line-height: 1.3em; + font-weight: bold; + font-family: Helvetica, sans-serif; + color:#666666; +} + +/* IE6&7 fix */ +* html #spotlight #description { + padding-top:17px; +} + +#spotlight #description span { + color:#00487d; +} + +.spotlightbold { + font-weight: bold; + color:#00487d; +} +.blue { + color:#00487d; +} +.readmorelink { + color:#333333; +} +.screenshot { + float:left; + margin:0 10px 20px 0; +} + +#whiterow { + min-height: 207px; + height:auto; + margin:0 auto; + padding:0; + background: #ffffff; + text-align: left; + clear:both; +} + +#footerrow { + min-height: 207px; + height:auto; + margin:0 auto; + padding:10px 0 0 0; + background: #e5eff6 url(../images/bottomback.png) repeat-x top left; + text-align: left; + clear:both; +} + +#page-contents { + width:940px; + margin:auto; + padding:20px 0 0 0; + text-align:left; + background:#fff; +} + +#page-contents p { + font-size:0.9em; +} + +#page-contents h1 { + border-bottom:1px solid #666666; + font-size:20px; + padding-left:4px; + margin:0; +} + +#page-contents h2 { + margin:10px 0 10px 0; + padding:5px; + font-size:20px; + border-bottom:1px solid #666666; + background:#d8dfea; +} + +#developers, +#categories { + border-left:0px solid #ccc; + font-size:0.9em; + width:276px; + padding-left:4px; + margin:0 20px 0 0; +} + +#developers h3, +#categories h3 { + font-size:14px; + color:#433c2a; +} + +#developers h4 { + font-size:18px; + margin:15px 0 5px 0; + padding:0; + border-bottom: 1px solid #999999; +} +#developers img { + margin:0 10px 15px 0; + padding:0; +} +#developers li { + margin-bottom:20px; +} + +#developers li, +#categories li { + font-size:1.0em; + list-style:none; +} + +#developers ul, +#categories ul { + margin:4px 0 0 0; + padding:0; +} + +.leftmargin { + margin:0 20px 0 30px !important; +} + +#spotlight #page-options { + width:200px; + padding:10px 0 10px 0; + margin:0 20px 0 0; + +} +#spotlight #page-options .menuselected { + color:black; + +} + +#spotlight #page-options li { + list-style:none; + margin:8px 20px 8px 0; + border-bottom:1px solid #cccccc; +} + +#spotlight #page-options ul { + margin:0px 0 0 0; + padding:0; +} + +#spotlight h2 { + margin:0 0 10px 0; + padding:10px 0 0 0; + font-size:20px; +} + +#page-contents #actual-contents, +#page-contents #spotlight { + width:630px; +} + +#spotlight #actual-contents p { + margin:10px 20px 10px 0; + line-height:1.4em; +} + +#page-contents #actual-contents p { + font-size:0.8em; + margin:10px 20px 10px 0; + line-height:1.8em; +} + +#page-contents #actual-contents h3 { + font-size:0.9em; +} + +#page-contents #actual-contents .coloured { + padding:0 5px 0 5px; + background:#e5f1f4; + border:1px solid #ddd; +} + +#page-contents .plugin-box h3 { + font-size:12px; + border-bottom:1px solid #ccc; +} +/* TEMP RULE */ +.more_content p { + line-height:1.3em; + font-size: 130%; + margin:0 0 10px 0; +} +.more_content h3 { + margin:0 0 0 0; +} + +#forum-quickstart { + float:right; + width:200px; + padding:10px; + border:1px solid #ccc; + background:#efefef; +} + +#forum-quickstart p, ul { + padding:0; + margin:0; +} + +#forum-quickstart li { + list-style:none; +} + + +#contents { + background:#3BB1BA; + margin-bottom:20px; +} + +.products { + text-align:left; +} + +.blurb { + padding:10px; + color:#fff; + font-size: 20px; + text-align: left; + text-align:justify; + width:790px; + margin:auto; + font-weight:bold; +} + +.front-products { + margin:0 0 20px 0; + padding:0px; + border:0px solid #ccc; + width:330px; + /*height:100px;*/ +} + +.front-products ul { + margin:0 0 5px 15px; + padding:0; + list-style: square; + font-size:13px; +} + +.front-products ol { + margin:0 0 5px 15px; + padding:0 0 0 3px; + font-size:13px; +} + +#whiterow .front-products ul { + list-style: square; + font-size:13px; +} +#whiterow .front-products ol { + font-size:13px; +} + +.front-products li { + padding:3px 0 3px 0; +} + +.front-products h3 { + font-size:20px; + letter-spacing: -0.05em; + color:#00487d; + margin:20px 20px 10px 30px; + padding:0 0 5px 0; + border-bottom:1px dashed #00487d; +} + +.front-products p { + font-size:13px; + line-height: 18px; +} + +.leftpad { + padding-left:30px; + padding-right:20px; +} + + +.front-products p.hiring { + background:#555; + color:#fff; + padding:2px; +} + +#footer { + text-align:center; + margin: auto; + height:60px; + background: #00487d url(../images/footerback.png) repeat-x top left; + clear:both; + border-top: 1px solid #e5eff6; + color:#e5eff6; + padding-top: 24px; +} +#footer p { + color:#e5eff6; + font-size: 12px; + font-weight: normal; +} + +#footer a { + color:#e5eff6; +} +#footer a:hover { + text-decoration: underline; + color:#ffffff; +} + +form { + margin:0 0 0 30px; + padding:0; +} + +input { + border:1px solid #BBBBBB; + color:#666666; + font-size:15px; + font-weight:bold; + font-family:inherit; + margin:0; + padding:4px; + width:270px; + height:30px; +} + +input.submitbutton { + color:#00487d; + border:1px solid #BBBBBB; + background: #ffffff url(../images/button_grad.png) repeat-x bottom left; + font-size:15px; + font-weight:bold; + margin:10px 0 0 0; + padding:4px 10px 5px 10px; + cursor:pointer; + width:auto; +} +input.submitbutton:hover { + color:#ffffff; + background: #00487d; +} + +.blog_dateblock { + background:#00487d; + float:right; + height:29px; + margin:3px 10px 15px 0; + width:29px; +} +.blog_month { + color:white; + font-size:12px; + font-weight:bold; + line-height:1.3em; + margin:0pt; + padding:0pt; + text-align:center; +} +.blog_day { + color:white; + font-size:11px; + line-height:0.9em; + margin:0pt; + padding:0pt; + text-align:center; +} + + +/* GOOGLE SEARCH RESULTS */ +#cse-search-box { + float:right; + width:auto; + height:auto; + top:20px; + right:36px; + position: absolute; +} +#cse-search-box input[type="text"] { + height:25px; + background-image: none !important; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border:3px solid white; + padding:0; + margin:3px; +} +#cse-search-box input[type="submit"] { + font: 13px/100% Arial, Helvetica, sans-serif; + font-weight: bold; + color: white; + background:#547faa; + border: 3px solid #547faa; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + width: auto; + height: 25px; + padding: 1px; + margin:3px; + cursor: pointer; +} +#cse-search-box input[type="submit"]:hover { + color: #00487D; + background:white; + border: 3px solid white; + cursor: pointer; +} + +/* PC IE 6&7 */ +* html #cse-search-box { + +} +* html #cse-search-box input { + height:25px; + background-image: none !important; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border:3px solid white; + padding:0; + margin:3px; +} +* html #cse-search-box input.gsearchsubmit { + font: 13px/100% Arial, Helvetica, sans-serif; + font-weight: bold; + color: white; + background:#547faa; + border: 3px solid #547faa; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + width: auto; + height: 25px; + padding: 1px; + margin:3px; + cursor: pointer; +} +/* end PC IE rules */ + +.dividerline { + border-bottom:1px solid #cccccc; +} + +/* hosting page */ +.hosting_company { + margin:0 20px 20px 30px; + padding:4px 50px 1px 10px; + background: #efefef; + border:2px solid #efefef; + -webkit-border-radius: 8px; + -moz-border-radius: 8px; +} +.hosting_company h3 { + margin:0; + border:none; + font-size:1.1em; +} + .hosting_company p { + margin:0; + padding:4px 0 4px 0; + line-height: 1.1em; +} + +/* rc1 temp styles */ +.rc1buttons { + font: 12px/100% Arial, Helvetica, sans-serif; + font-weight: bold; + color: #ffffff; + background:#00487d; + border: 1px solid #00487d; + text-decoration: none; + -webkit-border-radius: 5px; + -moz-border-radius: 5px; + width: auto; + height:auto; + padding: 4px 6px 4px 6px; + margin:16px 0 2px 0; + cursor: pointer; +} +.rc1buttons:hover { + background: black; + border-color: black; + text-decoration: none; +} + + diff --git a/css/theme_gallery.css b/css/theme_gallery.css new file mode 100644 index 0000000..3f0dc28 --- /dev/null +++ b/css/theme_gallery.css @@ -0,0 +1,221 @@ +#spotlight-inner {font-size: 1.25em;} +#spotlight #page-options li {line-height: 1.15em;} + +.themes-documentation ul { + margin:0 0 5px 40px; + padding:0; + list-style: square; +} +.themes-documentation li { + padding:3px 0 3px 0; + font-size: 14px; +} +h3.themes-documentation { + font-size:20px; + letter-spacing: -0.05em; + color:#00487d; + margin:0px 20px 0px 30px; + padding:0 0 5px 0; + border-bottom:1px dashed #00487d; +} +#themes #whiterow { + min-height: 120px; +} + +#placeholder { + margin:20px auto 0 auto; + clear:both; + height:auto; +} +div.skin-elgg { + width:990px; + margin: 0 auto; +} + +div.photo a {text-decoration: none; outline: none;} +div#zoom {z-index: 99999;} +a#zoom_close {outline: none;} + +#themegallery li { + background: url(../images/theme_thumb_background.gif) no-repeat left top; +} +#themegallery li:hover { + background: url(../images/theme_thumb_background_hover.gif) no-repeat left top; +} + +div.phototitle { + color:#333333; + font-family: Arial, sans-serif; + font-weight: bold; + font-size: 14px; + height:0; + position:relative; + left:9px; + top:190px; +} +div.themeinfo { + display: none; + font-family: Arial, sans-serif; + font-weight: normal; + font-size: 13px; + line-height: 1.6em; + padding:27px 0 6px 9px; + background: url(../images/theme_thumb_background_hover.gif) no-repeat left bottom; +} +/* IE 6 fixes */ +* html div.themeinfo { + background: url(../images/theme_thumb_background.gif) no-repeat left bottom; +} +div.themeinfo a { + color:#666666; + padding:0 0 4px 22px; + font-weight: normal; +} +div.themeinfo a:hover { + color:#333333; +} +div.themeinfo a.zoomthisimage { + background: url(../images/icon_preview.gif) no-repeat left top; +} +div.themeinfo a.themeinfomore { + background: url(../images/icon_moreinfo.gif) no-repeat left top; +} +div.themeinfo a.themeinfodownload { + background: url(../images/icon_download.gif) no-repeat left top; +} +div.photo { + text-align: left; +} +div.photo a img { + border:none; + padding:10px 0 0 10px; +} + +div#preloadimages { + width: 0px; + height: 0px; + overflow: hidden; +} + +.container { + position: relative; +} + +.clip { + z-index: 2; + padding: 0; + margin: 0; + overflow: hidden; + position: relative; +} + +.list { + z-index: 1; + overflow: hidden; + position: relative; + top: 0; + left: 0; + margin: 0; + padding: 0; +} + +.list li, +.item { + float: left; + list-style: none; + width: 195px; + height: 214px; +} + +.next { + z-index: 3; + display: none; +} + +.prev { + z-index: 3; + display: none; +} + +.skin-elgg .container { + background: #ffffff; +} + +.skin-elgg .container-horizontal { + width: 872px; + padding: 0px 58px; +} + +.skin-elgg .clip-horizontal { + width: 869px; + height: 300px; +} + +.skin-elgg .item { + width: 195px; + height: 314px; + border: 1px solid #fff; +} + +.skin-elgg .item:hover { + /* border-color: #cccccc; */ +} + +.skin-elgg .item-horizontal { + /* fix - might have to remove for ie */ + margin-left: 8px; + margin-right: 15px; +} + +.skin-elgg .item-placeholder { +} + +.skin-elgg .next-horizontal { + position: absolute; + top: 80px; + right: 0px; + width: 58px; + height: 64px; + cursor: pointer; + background: transparent url(../images/next_button.gif) no-repeat -2px 0px; +} + +.skin-elgg .next-horizontal:hover { + background-position: -62px 0; +} + +.skin-elgg .next-horizontal:active { + background-position: -62px 0; +} + +.skin-elgg .next-disabled-horizontal, +.skin-elgg .next-disabled-horizontal:hover, +.skin-elgg .next-disabled-horizontal:active { + cursor: default; + background-position: -122px 0; +} + +.skin-elgg .prev-horizontal { + position: absolute; + top: 80px; + left: 0px; + width: 58px; + height: 64px; + cursor: pointer; + background: transparent url(../images/prev_button.gif) no-repeat 0 0; +} + +.skin-elgg .prev-horizontal:hover { + background-position: -60px 0; +} + +.skin-elgg .prev-horizontal:active { + background-position: -60px 0; +} + +.skin-elgg .prev-disabled-horizontal, +.skin-elgg .prev-disabled-horizontal:hover, +.skin-elgg .prev-disabled-horizontal:active { + cursor: default; + background-position: -120px 0; +} \ No newline at end of file diff --git a/dbgumph.php b/dbgumph.php new file mode 100644 index 0000000..fe4a762 --- /dev/null +++ b/dbgumph.php @@ -0,0 +1,24 @@ + + alert("Thank you. Your email address has been registered, and we'll let you know when Elgg 1.0 has been released."); + + +END; + + } + +?> \ No newline at end of file diff --git a/developers.php b/developers.php new file mode 100644 index 0000000..6302baf --- /dev/null +++ b/developers.php @@ -0,0 +1,75 @@ + + + + + Elgg - Open Source Social Networking Engine. + + + + + + + + + +
+
+ +
+

Developer Center

+

Welcome to the elgg.org developer center. If you are interested in developing on the Elgg engine, then this page will point you to all the resources you might need.

+

As always, if you like what you see with Elgg then please consider getting involved in its development.

+

+ Documentation + Documentation
Here you will find information about Elgg's architecture, approach and features.

+
+
+

+ Documentation + Bug Tracker
This is Elgg's bug tracker, if you find bugs or have patches for existing bugs then head on over and get involved.

+
+
+

+ Documentation + Developer mailing list
This mailing list is aimed at experienced developers, not end users.

+
+
+

+ Documentation + API Reference
This is a handy resource to search and find out what functions exist within Elgg.

+
+
+
+
+
+ +
+ + + + \ No newline at end of file diff --git a/domain.php b/domain.php new file mode 100644 index 0000000..d43c930 --- /dev/null +++ b/domain.php @@ -0,0 +1,61 @@ + + + + + Elgg - Open Source Social Networking Platform. + + + + + + + + + +
+
+ +
+

Domain policy

+

We're delighted when people start a site or service powered by Elgg. However, please note that the Elgg name is a registered trademark, so please do not use "Elgg" in your domain name. "Elgg" in sub-domains is fine (like elgg.mysite.com), we're just concerned about top-level domains.

+

Thanks in advance for your co-operation.

+
+
+
+ +
+ + + + \ No newline at end of file diff --git a/download.php b/download.php new file mode 100644 index 0000000..b90bfe8 --- /dev/null +++ b/download.php @@ -0,0 +1,98 @@ + + + + + Elgg - Open Source Social Networking Platform. + + + + + + + + + +
+
+ + +
+

Latest release - October 14, 2010

+
+

Elgg is available under a dual license, GPL Version 2 and the MIT license. However, there are certain third party components that Elgg uses which can't be + distributed under an MIT license as they are GPL only. Those components have been removed from the MIT release so make sure you read the readme.txt file!

+

Download: MIT version

+
+

Elgg v1.7.4 includes important bugfixes.
+ It is the recommended release.

+

+ +
+ +
+

Hosting

+

If you are looking for somewhere to host your Elgg powered network, we are putting together a list of providers who have added Elgg hosting to their services.

+

+ Arvixe graphic

+

+ A2 graphic

+
+
+

Subversion Access

+

If you're a developer and want the latest code, using Subversion, you can grab the latest work in progress:

+

svn://code.elgg.org/elgg/trunk

+
+

Nightly build

+

Alternatively, you can grab a nightly build (please do not use this on production sites!):

+

http://elgg.org/download/nightly/

+
+
+
+
+ +
+ + + + diff --git a/error.php b/error.php new file mode 100644 index 0000000..44953ff --- /dev/null +++ b/error.php @@ -0,0 +1,5 @@ + \ No newline at end of file diff --git a/events/action.php b/events/action.php new file mode 100644 index 0000000..99b5a60 --- /dev/null +++ b/events/action.php @@ -0,0 +1,36 @@ + \ No newline at end of file diff --git a/events/images/background.gif b/events/images/background.gif new file mode 100644 index 0000000..f74bdb9 Binary files /dev/null and b/events/images/background.gif differ diff --git a/events/images/elggcamp1.jpg b/events/images/elggcamp1.jpg new file mode 100644 index 0000000..b3d8cab Binary files /dev/null and b/events/images/elggcamp1.jpg differ diff --git a/events/images/elggcamp2.jpg b/events/images/elggcamp2.jpg new file mode 100644 index 0000000..70b67d8 Binary files /dev/null and b/events/images/elggcamp2.jpg differ diff --git a/events/images/elggcamp3.jpg b/events/images/elggcamp3.jpg new file mode 100644 index 0000000..ede1487 Binary files /dev/null and b/events/images/elggcamp3.jpg differ diff --git a/events/images/elggcamp4.jpg b/events/images/elggcamp4.jpg new file mode 100644 index 0000000..61d9d95 Binary files /dev/null and b/events/images/elggcamp4.jpg differ diff --git a/events/images/elggcamp5.jpg b/events/images/elggcamp5.jpg new file mode 100644 index 0000000..6f8ae3f Binary files /dev/null and b/events/images/elggcamp5.jpg differ diff --git a/events/images/elggcamp6.jpg b/events/images/elggcamp6.jpg new file mode 100644 index 0000000..0e29af1 Binary files /dev/null and b/events/images/elggcamp6.jpg differ diff --git a/events/images/elggcamp7.jpg b/events/images/elggcamp7.jpg new file mode 100644 index 0000000..0d9d467 Binary files /dev/null and b/events/images/elggcamp7.jpg differ diff --git a/events/index.php b/events/index.php new file mode 100644 index 0000000..2954897 --- /dev/null +++ b/events/index.php @@ -0,0 +1,316 @@ + + + + + + + + +Elgg.org - events + + + + + + + + + + +
+ +
+
+ + ElggCamp image +
+
+

ElggCamp

+

ElggCamps are informal gatherings organised by members of the Elgg community to discuss and share ideas about Elgg.

+ +
+
+ +
+
+

ElggCamp on Flickr

+ +
+
+ + +
+
+ +

Upcoming

+ +
+

None currently scheduled

+
+ +

Previous

+
+

ElggCamp Buenos Aires 2009

+

Date: Nov 19th, 2009

+

Web: http://www.elggcampba.com/

+
+ +
+

ElggCamp Boston

+

Date: August 15th, 2009

+

Venue: Harvard Science Center

+

Location: Harvard, Boston

+
+ +
+

ElggCamp Paris

+

Date: June 13th, 2009

+

Location: La Cantine, Paris

+

Web: http://elgg.elgg.fr/pg/groups/623/projet-elggcamp/

+
+ +
+

ElggCamp Brighton

+

Date: December 1st, 2008

+

Location: University of Brighton

+
+ +
+ +
+ +

Arranging an ElggCamp?

+

If you are arranging an ElggCamp and would like us to promote it here, then send us some information about your event.

+ +
+

Thank you for submitting your information about your ElggCamp, we will review and add it to the list.

+
+ +
+

There has been a problem submitting your information. Please try again.

+
+ +
+

You need to make sure you fill in all the required fields.

+
+ +
+

(* required fields)

+


+


+


+


+


+ + +
+
+
+
+ + + + + + diff --git a/events/index_old.php b/events/index_old.php new file mode 100644 index 0000000..d360d66 --- /dev/null +++ b/events/index_old.php @@ -0,0 +1,187 @@ + + + + + Elgg.org - events + + + + + + + +
+
+

ElggCamp Boston, August 15th

+

This event page has now moved over here.

+
+
+
+ + + + \ No newline at end of file diff --git a/events/phpFlickr/ChangeLog.txt b/events/phpFlickr/ChangeLog.txt new file mode 100644 index 0000000..1abb1a8 --- /dev/null +++ b/events/phpFlickr/ChangeLog.txt @@ -0,0 +1,314 @@ +--------------------- +phpFlickr - Changelog +--------------------- + +Version 2.3.0.1 +------------- + +2008-12-17 Dan Coulter + * Changed some links in the documentation to remove + references to SourceForge and link to Google Code + +Version 2.3.0 +------------- + +2008-12-17 Dan Coulter + * Note: The following methods have had either their input + parameters or their output (or both) changed because + of changes in the Flickr API. If you use any of them + in your app, be sure to check for compatibility. + favorites_getList + favorites_getPublicList + groups_getInfo + people_getPublicPhotos + photos_getNotInSet + photos_getUntagged + photos_recentlyUpdated + photos_setSafetyLevel + photos_comments_getList + photos_geo_setPerms + photosets_getPhotos + tags_getListUserRaw + * phpFlickr.php: Modified existing methods to match the + Flickr API documentation. This WILL break compatibility + on certain methods. Also added new methods since the + last update. +2008-11-26 Dan Coulter + * phpFlickr.php: Added new methods to keep up to date + with the API. + + +Version 2.2.0 +------------- + +2008-01-17 Dan Coulter + * phpFlickr.php: Added the preference, safety, content + and "places" methods. + * other files: Updated PEAR and HTTP_Request. + + +Version 2.1.0 +------------- + +2006-11-21 Dan Coulter + * phpFlickr.php: Updated the buildPhotoURL method to + reflect recent changes in the Flickr API. Also added the + photos_getFavorites method and added pagination arguments + to photosets_getPhotos.. + +2006-11-21 Dan Coulter + * phpFlickr.php: Added the activity methods. + +2006-10-18 Dan Coulter + * phpFlickr.php: Added the tags_getHotList method. + + +Version 2.0.0 +------------- + +2006-09-29 Dan Coulter + IMPORTANT: This version will not be 100% backwards compatible. + It may very well break older apps if you try to copy it over + an older version of phpFlickr. Be sure you test thoroughly. + + * phpFlickr.php: Updated class to use Flickr's Serialized PHP + format. Also, I revamped the error handling and caching. + Fixed a bug in file uploading. + * xml.php: Deleted. + * xml_SAXY_parser.php: Deleted. + + +Version 1.6.1 +------------- + +2006-09-01 Dan Coulter + * phpFlickr.php: Changed the license to the LGPL and + implemented my friendly geodata service. + + +Version 1.6 +----------- + +2006-08-29 Dan Coulter + * phpFlickr.php: Implemented the new comment and geocoding + API methods. + +2006-08-04 Dan Coulter + * phpFlickr.php: added support for new API methods. Also, + added useSAXY method to switch to the SAXY parser. + * xml.php: Changed parser so that it uses PHP's XML functions + by default, but you can choose to use SAXY if you may run + into unusual characters. Using SAXY requires alot more + memory for your scripts. + + +Version 1.6-beta +---------------- + +2006-06-19 Dan Coulter + * xml.php: Replaced PHP's XML functions with the SAXY_Parser + class to remove the problems with unusual characters that + PHP's functions created. + +2006-06-15 Dan Coulter + * phpFlickr.php: Added support for the new photo replacement API. + +Version 1.5.2 +------------- + +2006-05-07 Dan Coulter + * phpFlickr.php: Added privacy_filter parameter to + photosets_getPhotos(). + + +2006-03-13 Dan Coulter + * phpFlickr.php: Fixed bugs in contacts_getList and + contacts_getPublicList when they are returned with one + result. + +Version 1.5.1 +------------- + +2006-03-13 Dan Coulter + * phpFlickr.php: Added support for flickr.photos.comments.getList + +2006-03-11 Dan Coulter + * phpFlickr.php: Fixed a bug in photos_licenses_setLicense() + +Version 1.5 +----------- + +2006-02-15 Dan Coulter + * phpFlickr.php: Implemented support for 23's compatible API. + Implemented flickr.groups.search method. Fixed bug in + filesystem caching for PHP versions older than 4.3.0. + Stopped caching from changing the working directory. + Included support for HTTP proxy servers. + + +Version 1.4.3 +------------- + +2006-01-05 Dan Coulter + * phpFlickr.php: Added interestingness_getList() method. + Fixed a bug in favorites_getPublicList() that made it + return less data than it should have. Note: This + means that you need to adjust any calls to this function. + * xml.php: Added Escape character to replacements so that the + XML parser will not barf. + +2005-12-16 Dan Coulter + * phpFlickr.php: Fixed a bug in photosets_getPhotos() + definition. + + +Version 1.4.2 +------------- + +2005-12-13 Dan Coulter + * phpFlickr.php: Removed extra useless code from + favorites_remove(). + Added photo deletion method: photos_delete(). + Removed old authentication function login(). Flickr + has removed the old auth style from the API. The only + way to authenticate now is through the auth() function. + + +2005-12-12 Dan Coulter + * phpFlickr.php: Fixed a bug setting the PEAR include path + in Windows. + +2005-12-10 Dan Coulter + * phpFlickr.php: Fixed a bug that would cause database + caching to fail in Windows. + + +Version 1.4.1 +------------- + +2005-12-02 Dan Coulter + * phpFlickr.php: Added "user_id" parameter to the + groups_pools_getPhotos() method. Note, because of the + placement in the Flickr API documentation, this make break + some older applications. The third parameter must be + the user_id. + * phpFlickr.php: Changed buildPhotoURL() to use the new URL + scheme for photo files. + * xml.php: Fixed the bug that was causing an "undefined + index" notice. + +2005-11-15 Dan Coulter + * phpFlickr.php: fixed a session bug and added the "extras" + parameter to photosets_getPhotos. + +Version 1.4 +------------- + +2005-09-19 Dan Coulter + * phpFlickr.php: Fixed a bug in getCached() to remove an extra + database call that was being made. Avast! + +2005-09-18 Dan Coulter + * phpFlickr.php: Added support for uploading. Both synchronous + and asynchronous uploading have been implemented. + +Version 1.3.3 +------------- + +2005-09-18 Dan Coulter + * phpFlickr.php: Added support for flickr.photos.getAllContexts. + Adjusted behavior of certain methods to make results more consistant. + Added callMethod() function for generic access to methods. Made sure + that methods that set data do not cache the results. + +2005-09-14 Dan Coulter + * phpFlickr.php: Added support for flickr.photos.licenses.setLicense. + +2005-09-08 Dan Coulter + * phpFlickr.php: Changed variable definition from $error_num + to $error_code. + +2005-09-07 Dan Coulter + * phpFlickr.php: Fixed bug in photos_getNotInSet(). + +2005-08-23 Dan Coulter + * phpFlickr.php: Fixed file system detection. + +Version 1.3.2 +------------- + +2005-08-17 Dan Coulter + * phpFlickr.php: Fixed a bug in the include paths and a bug + that was causing the cache not to work. + +2005-08-16 Dan Coulter + * phpFlickr.php: Added filter parameter to contacts_getList(). + +2005-08-10 Dan Coulter + * phpFlickr.php: Added support for flickr.people.getUploadStatus + +2005-08-11 Dan Coulter + * xml.php: Fixed a bug that removed all newline characters from the + XML returned from Flickr. + +Version 1.3.1 +------------- + +2005-08-05 Dan Coulter + * auth.php: Updated to use Flickr's extra callback argument for the + redirect instead of a session variable. + +2005-08-04 Dan Coulter + * phpFlickr.php: Included code to add the packaged PEAR folder + in the include path. + + +Version 1.3 +------------- + +2005-07-22 Dan Coulter + * phpFlickr.php: Added support for the new authentication scheme. + Added the three new auth methods plus the phpFlickr::auth() function + to act as a simple authentication check. + Fixed bugs in the error handling functions. + * README.txt: Fixed several typos relating to photos_search() and to + the PEAR prereqs. + +Version 1.2.1 +------------- + +2005-06-30 Dan Coulter + * phpFlickr.php: Added a comment to the photos_search() method to + help people know how to use it. + * README.txt: Fixed several typos relating to photos_search() and to + the PEAR prereqs. + +2005-06-23 Dan Coulter + * phpFlickr.php: Fixed a bug in the buildPhotoURL method that caused + an invalid URL to be returned. + * phpFlickr.php: removed the login parameters from the constructor + and added "die_on_error" parameter. Added login() and two error + methods. + * README.txt: Edited text about constructor's parameters and included + information on new login method. + +Version 1.2 +----------- + +2005-06-12 Dan Coulter + * phpFlickr.php: Created functions for the new methods: photosets.addPhoto + and photosets.removePhoto. Also fixed some code formatting. + * phpFlickr.php: Changed URLs to reflect the new phpflickr.com site. + * README.txt: Changed URLs to reflect the new phpflickr.com site and added + a few notes about coding. + * example.php: Added an example php script. + +2005-06-11 Dan Coulter + * phpFlickr.php: Fixed a bug in the definition of groups_pools_getPhotos() + that made the fifth parameter not optional. + +Version 1.1 +----------- + +2005-06-09 Dan Coulter + * phpFlickr.php: Added caching functionality diff --git a/events/phpFlickr/PEAR/DB.php b/events/phpFlickr/PEAR/DB.php new file mode 100644 index 0000000..a3eede0 --- /dev/null +++ b/events/phpFlickr/PEAR/DB.php @@ -0,0 +1,1388 @@ + + * @author Tomas V.V.Cox + * @author Daniel Convissor + * @copyright 1997-2005 The PHP Group + * @license http://www.php.net/license/3_0.txt PHP License 3.0 + * @version CVS: $Id: DB.php 32 2005-08-01 06:21:02Z dancoulter $ + * @link http://pear.php.net/package/DB + */ + +/** + * Obtain the PEAR class so it can be extended from + */ +require_once 'PEAR.php'; + + +// {{{ constants +// {{{ error codes + +/**#@+ + * One of PEAR DB's portable error codes. + * @see DB_common::errorCode(), DB::errorMessage() + * + * {@internal If you add an error code here, make sure you also add a textual + * version of it in DB::errorMessage().}} + */ + +/** + * The code returned by many methods upon success + */ +define('DB_OK', 1); + +/** + * Unkown error + */ +define('DB_ERROR', -1); + +/** + * Syntax error + */ +define('DB_ERROR_SYNTAX', -2); + +/** + * Tried to insert a duplicate value into a primary or unique index + */ +define('DB_ERROR_CONSTRAINT', -3); + +/** + * An identifier in the query refers to a non-existant object + */ +define('DB_ERROR_NOT_FOUND', -4); + +/** + * Tried to create a duplicate object + */ +define('DB_ERROR_ALREADY_EXISTS', -5); + +/** + * The current driver does not support the action you attempted + */ +define('DB_ERROR_UNSUPPORTED', -6); + +/** + * The number of parameters does not match the number of placeholders + */ +define('DB_ERROR_MISMATCH', -7); + +/** + * A literal submitted did not match the data type expected + */ +define('DB_ERROR_INVALID', -8); + +/** + * The current DBMS does not support the action you attempted + */ +define('DB_ERROR_NOT_CAPABLE', -9); + +/** + * A literal submitted was too long so the end of it was removed + */ +define('DB_ERROR_TRUNCATED', -10); + +/** + * A literal number submitted did not match the data type expected + */ +define('DB_ERROR_INVALID_NUMBER', -11); + +/** + * A literal date submitted did not match the data type expected + */ +define('DB_ERROR_INVALID_DATE', -12); + +/** + * Attempt to divide something by zero + */ +define('DB_ERROR_DIVZERO', -13); + +/** + * A database needs to be selected + */ +define('DB_ERROR_NODBSELECTED', -14); + +/** + * Could not create the object requested + */ +define('DB_ERROR_CANNOT_CREATE', -15); + +/** + * Could not drop the database requested because it does not exist + */ +define('DB_ERROR_CANNOT_DROP', -17); + +/** + * An identifier in the query refers to a non-existant table + */ +define('DB_ERROR_NOSUCHTABLE', -18); + +/** + * An identifier in the query refers to a non-existant column + */ +define('DB_ERROR_NOSUCHFIELD', -19); + +/** + * The data submitted to the method was inappropriate + */ +define('DB_ERROR_NEED_MORE_DATA', -20); + +/** + * The attempt to lock the table failed + */ +define('DB_ERROR_NOT_LOCKED', -21); + +/** + * The number of columns doesn't match the number of values + */ +define('DB_ERROR_VALUE_COUNT_ON_ROW', -22); + +/** + * The DSN submitted has problems + */ +define('DB_ERROR_INVALID_DSN', -23); + +/** + * Could not connect to the database + */ +define('DB_ERROR_CONNECT_FAILED', -24); + +/** + * The PHP extension needed for this DBMS could not be found + */ +define('DB_ERROR_EXTENSION_NOT_FOUND',-25); + +/** + * The present user has inadequate permissions to perform the task requestd + */ +define('DB_ERROR_ACCESS_VIOLATION', -26); + +/** + * The database requested does not exist + */ +define('DB_ERROR_NOSUCHDB', -27); + +/** + * Tried to insert a null value into a column that doesn't allow nulls + */ +define('DB_ERROR_CONSTRAINT_NOT_NULL',-29); +/**#@-*/ + + +// }}} +// {{{ prepared statement-related + + +/**#@+ + * Identifiers for the placeholders used in prepared statements. + * @see DB_common::prepare() + */ + +/** + * Indicates a scalar (?) placeholder was used + * + * Quote and escape the value as necessary. + */ +define('DB_PARAM_SCALAR', 1); + +/** + * Indicates an opaque (&) placeholder was used + * + * The value presented is a file name. Extract the contents of that file + * and place them in this column. + */ +define('DB_PARAM_OPAQUE', 2); + +/** + * Indicates a misc (!) placeholder was used + * + * The value should not be quoted or escaped. + */ +define('DB_PARAM_MISC', 3); +/**#@-*/ + + +// }}} +// {{{ binary data-related + + +/**#@+ + * The different ways of returning binary data from queries. + */ + +/** + * Sends the fetched data straight through to output + */ +define('DB_BINMODE_PASSTHRU', 1); + +/** + * Lets you return data as usual + */ +define('DB_BINMODE_RETURN', 2); + +/** + * Converts the data to hex format before returning it + * + * For example the string "123" would become "313233". + */ +define('DB_BINMODE_CONVERT', 3); +/**#@-*/ + + +// }}} +// {{{ fetch modes + + +/**#@+ + * Fetch Modes. + * @see DB_common::setFetchMode() + */ + +/** + * Indicates the current default fetch mode should be used + * @see DB_common::$fetchmode + */ +define('DB_FETCHMODE_DEFAULT', 0); + +/** + * Column data indexed by numbers, ordered from 0 and up + */ +define('DB_FETCHMODE_ORDERED', 1); + +/** + * Column data indexed by column names + */ +define('DB_FETCHMODE_ASSOC', 2); + +/** + * Column data as object properties + */ +define('DB_FETCHMODE_OBJECT', 3); + +/** + * For multi-dimensional results, make the column name the first level + * of the array and put the row number in the second level of the array + * + * This is flipped from the normal behavior, which puts the row numbers + * in the first level of the array and the column names in the second level. + */ +define('DB_FETCHMODE_FLIPPED', 4); +/**#@-*/ + +/**#@+ + * Old fetch modes. Left here for compatibility. + */ +define('DB_GETMODE_ORDERED', DB_FETCHMODE_ORDERED); +define('DB_GETMODE_ASSOC', DB_FETCHMODE_ASSOC); +define('DB_GETMODE_FLIPPED', DB_FETCHMODE_FLIPPED); +/**#@-*/ + + +// }}} +// {{{ tableInfo() && autoPrepare()-related + + +/**#@+ + * The type of information to return from the tableInfo() method. + * + * Bitwised constants, so they can be combined using | + * and removed using ^. + * + * @see DB_common::tableInfo() + * + * {@internal Since the TABLEINFO constants are bitwised, if more of them are + * added in the future, make sure to adjust DB_TABLEINFO_FULL accordingly.}} + */ +define('DB_TABLEINFO_ORDER', 1); +define('DB_TABLEINFO_ORDERTABLE', 2); +define('DB_TABLEINFO_FULL', 3); +/**#@-*/ + + +/**#@+ + * The type of query to create with the automatic query building methods. + * @see DB_common::autoPrepare(), DB_common::autoExecute() + */ +define('DB_AUTOQUERY_INSERT', 1); +define('DB_AUTOQUERY_UPDATE', 2); +/**#@-*/ + + +// }}} +// {{{ portability modes + + +/**#@+ + * Portability Modes. + * + * Bitwised constants, so they can be combined using | + * and removed using ^. + * + * @see DB_common::setOption() + * + * {@internal Since the PORTABILITY constants are bitwised, if more of them are + * added in the future, make sure to adjust DB_PORTABILITY_ALL accordingly.}} + */ + +/** + * Turn off all portability features + */ +define('DB_PORTABILITY_NONE', 0); + +/** + * Convert names of tables and fields to lower case + * when using the get*(), fetch*() and tableInfo() methods + */ +define('DB_PORTABILITY_LOWERCASE', 1); + +/** + * Right trim the data output by get*() and fetch*() + */ +define('DB_PORTABILITY_RTRIM', 2); + +/** + * Force reporting the number of rows deleted + */ +define('DB_PORTABILITY_DELETE_COUNT', 4); + +/** + * Enable hack that makes numRows() work in Oracle + */ +define('DB_PORTABILITY_NUMROWS', 8); + +/** + * Makes certain error messages in certain drivers compatible + * with those from other DBMS's + * + * + mysql, mysqli: change unique/primary key constraints + * DB_ERROR_ALREADY_EXISTS -> DB_ERROR_CONSTRAINT + * + * + odbc(access): MS's ODBC driver reports 'no such field' as code + * 07001, which means 'too few parameters.' When this option is on + * that code gets mapped to DB_ERROR_NOSUCHFIELD. + */ +define('DB_PORTABILITY_ERRORS', 16); + +/** + * Convert null values to empty strings in data output by + * get*() and fetch*() + */ +define('DB_PORTABILITY_NULL_TO_EMPTY', 32); + +/** + * Turn on all portability features + */ +define('DB_PORTABILITY_ALL', 63); +/**#@-*/ + +// }}} + + +// }}} +// {{{ class DB + +/** + * Database independent query interface + * + * The main "DB" class is simply a container class with some static + * methods for creating DB objects as well as some utility functions + * common to all parts of DB. + * + * The object model of DB is as follows (indentation means inheritance): + *
+ * DB           The main DB class.  This is simply a utility class
+ *              with some "static" methods for creating DB objects as
+ *              well as common utility functions for other DB classes.
+ *
+ * DB_common    The base for each DB implementation.  Provides default
+ * |            implementations (in OO lingo virtual methods) for
+ * |            the actual DB implementations as well as a bunch of
+ * |            query utility functions.
+ * |
+ * +-DB_mysql   The DB implementation for MySQL.  Inherits DB_common.
+ *              When calling DB::factory or DB::connect for MySQL
+ *              connections, the object returned is an instance of this
+ *              class.
+ * 
+ * + * @category Database + * @package DB + * @author Stig Bakken + * @author Tomas V.V.Cox + * @author Daniel Convissor + * @copyright 1997-2005 The PHP Group + * @license http://www.php.net/license/3_0.txt PHP License 3.0 + * @version Release: @package_version@ + * @link http://pear.php.net/package/DB + */ +class DB +{ + // {{{ &factory() + + /** + * Create a new DB object for the specified database type but don't + * connect to the database + * + * @param string $type the database type (eg "mysql") + * @param array $options an associative array of option names and values + * + * @return object a new DB object. A DB_Error object on failure. + * + * @see DB_common::setOption() + */ + function &factory($type, $options = false) + { + if (!is_array($options)) { + $options = array('persistent' => $options); + } + + if (isset($options['debug']) && $options['debug'] >= 2) { + // expose php errors with sufficient debug level + include_once "DB/{$type}.php"; + } else { + @include_once "DB/{$type}.php"; + } + + $classname = "DB_${type}"; + + if (!class_exists($classname)) { + $tmp = PEAR::raiseError(null, DB_ERROR_NOT_FOUND, null, null, + "Unable to include the DB/{$type}.php" + . " file for '$dsn'", + 'DB_Error', true); + return $tmp; + } + + @$obj =& new $classname; + + foreach ($options as $option => $value) { + $test = $obj->setOption($option, $value); + if (DB::isError($test)) { + return $test; + } + } + + return $obj; + } + + // }}} + // {{{ &connect() + + /** + * Create a new DB object including a connection to the specified database + * + * Example 1. + * + * require_once 'DB.php'; + * + * $dsn = 'pgsql://user:password@host/database'; + * $options = array( + * 'debug' => 2, + * 'portability' => DB_PORTABILITY_ALL, + * ); + * + * $db =& DB::connect($dsn, $options); + * if (PEAR::isError($db)) { + * die($db->getMessage()); + * } + * + * + * @param mixed $dsn the string "data source name" or array in the + * format returned by DB::parseDSN() + * @param array $options an associative array of option names and values + * + * @return object a new DB object. A DB_Error object on failure. + * + * @uses DB_dbase::connect(), DB_fbsql::connect(), DB_ibase::connect(), + * DB_ifx::connect(), DB_msql::connect(), DB_mssql::connect(), + * DB_mysql::connect(), DB_mysqli::connect(), DB_oci8::connect(), + * DB_odbc::connect(), DB_pgsql::connect(), DB_sqlite::connect(), + * DB_sybase::connect() + * + * @uses DB::parseDSN(), DB_common::setOption(), PEAR::isError() + */ + function &connect($dsn, $options = array()) + { + $dsninfo = DB::parseDSN($dsn); + $type = $dsninfo['phptype']; + + if (!is_array($options)) { + /* + * For backwards compatibility. $options used to be boolean, + * indicating whether the connection should be persistent. + */ + $options = array('persistent' => $options); + } + + if (isset($options['debug']) && $options['debug'] >= 2) { + // expose php errors with sufficient debug level + include_once "DB/${type}.php"; + } else { + @include_once "DB/${type}.php"; + } + + $classname = "DB_${type}"; + if (!class_exists($classname)) { + $tmp = PEAR::raiseError(null, DB_ERROR_NOT_FOUND, null, null, + "Unable to include the DB/{$type}.php" + . " file for '$dsn'", + 'DB_Error', true); + return $tmp; + } + + @$obj =& new $classname; + + foreach ($options as $option => $value) { + $test = $obj->setOption($option, $value); + if (DB::isError($test)) { + return $test; + } + } + + $err = $obj->connect($dsninfo, $obj->getOption('persistent')); + if (DB::isError($err)) { + $err->addUserInfo($dsn); + return $err; + } + + return $obj; + } + + // }}} + // {{{ apiVersion() + + /** + * Return the DB API version + * + * @return string the DB API version number + */ + function apiVersion() + { + return '@package_version@'; + } + + // }}} + // {{{ isError() + + /** + * Determines if a variable is a DB_Error object + * + * @param mixed $value the variable to check + * + * @return bool whether $value is DB_Error object + */ + function isError($value) + { + return is_a($value, 'DB_Error'); + } + + // }}} + // {{{ isConnection() + + /** + * Determines if a value is a DB_ object + * + * @param mixed $value the value to test + * + * @return bool whether $value is a DB_ object + */ + function isConnection($value) + { + return (is_object($value) && + is_subclass_of($value, 'db_common') && + method_exists($value, 'simpleQuery')); + } + + // }}} + // {{{ isManip() + + /** + * Tell whether a query is a data manipulation or data definition query + * + * Examples of data manipulation queries are INSERT, UPDATE and DELETE. + * Examples of data definition queries are CREATE, DROP, ALTER, GRANT, + * REVOKE. + * + * @param string $query the query + * + * @return boolean whether $query is a data manipulation query + */ + function isManip($query) + { + $manips = 'INSERT|UPDATE|DELETE|REPLACE|' + . 'CREATE|DROP|' + . 'LOAD DATA|SELECT .* INTO|COPY|' + . 'ALTER|GRANT|REVOKE|' + . 'LOCK|UNLOCK'; + if (preg_match('/^\s*"?(' . $manips . ')\s+/i', $query)) { + return true; + } + return false; + } + + // }}} + // {{{ errorMessage() + + /** + * Return a textual error message for a DB error code + * + * @param integer $value the DB error code + * + * @return string the error message or false if the error code was + * not recognized + */ + function errorMessage($value) + { + static $errorMessages; + if (!isset($errorMessages)) { + $errorMessages = array( + DB_ERROR => 'unknown error', + DB_ERROR_ACCESS_VIOLATION => 'insufficient permissions', + DB_ERROR_ALREADY_EXISTS => 'already exists', + DB_ERROR_CANNOT_CREATE => 'can not create', + DB_ERROR_CANNOT_DROP => 'can not drop', + DB_ERROR_CONNECT_FAILED => 'connect failed', + DB_ERROR_CONSTRAINT => 'constraint violation', + DB_ERROR_CONSTRAINT_NOT_NULL=> 'null value violates not-null constraint', + DB_ERROR_DIVZERO => 'division by zero', + DB_ERROR_EXTENSION_NOT_FOUND=> 'extension not found', + DB_ERROR_INVALID => 'invalid', + DB_ERROR_INVALID_DATE => 'invalid date or time', + DB_ERROR_INVALID_DSN => 'invalid DSN', + DB_ERROR_INVALID_NUMBER => 'invalid number', + DB_ERROR_MISMATCH => 'mismatch', + DB_ERROR_NEED_MORE_DATA => 'insufficient data supplied', + DB_ERROR_NODBSELECTED => 'no database selected', + DB_ERROR_NOSUCHDB => 'no such database', + DB_ERROR_NOSUCHFIELD => 'no such field', + DB_ERROR_NOSUCHTABLE => 'no such table', + DB_ERROR_NOT_CAPABLE => 'DB backend not capable', + DB_ERROR_NOT_FOUND => 'not found', + DB_ERROR_NOT_LOCKED => 'not locked', + DB_ERROR_SYNTAX => 'syntax error', + DB_ERROR_UNSUPPORTED => 'not supported', + DB_ERROR_TRUNCATED => 'truncated', + DB_ERROR_VALUE_COUNT_ON_ROW => 'value count on row', + DB_OK => 'no error', + ); + } + + if (DB::isError($value)) { + $value = $value->getCode(); + } + + return isset($errorMessages[$value]) ? $errorMessages[$value] + : $errorMessages[DB_ERROR]; + } + + // }}} + // {{{ parseDSN() + + /** + * Parse a data source name + * + * Additional keys can be added by appending a URI query string to the + * end of the DSN. + * + * The format of the supplied DSN is in its fullest form: + * + * phptype(dbsyntax)://username:password@protocol+hostspec/database?option=8&another=true + * + * + * Most variations are allowed: + * + * phptype://username:password@protocol+hostspec:110//usr/db_file.db?mode=0644 + * phptype://username:password@hostspec/database_name + * phptype://username:password@hostspec + * phptype://username@hostspec + * phptype://hostspec/database + * phptype://hostspec + * phptype(dbsyntax) + * phptype + * + * + * @param string $dsn Data Source Name to be parsed + * + * @return array an associative array with the following keys: + * + phptype: Database backend used in PHP (mysql, odbc etc.) + * + dbsyntax: Database used with regards to SQL syntax etc. + * + protocol: Communication protocol to use (tcp, unix etc.) + * + hostspec: Host specification (hostname[:port]) + * + database: Database to use on the DBMS server + * + username: User name for login + * + password: Password for login + */ + function parseDSN($dsn) + { + $parsed = array( + 'phptype' => false, + 'dbsyntax' => false, + 'username' => false, + 'password' => false, + 'protocol' => false, + 'hostspec' => false, + 'port' => false, + 'socket' => false, + 'database' => false, + ); + + if (is_array($dsn)) { + $dsn = array_merge($parsed, $dsn); + if (!$dsn['dbsyntax']) { + $dsn['dbsyntax'] = $dsn['phptype']; + } + return $dsn; + } + + // Find phptype and dbsyntax + if (($pos = strpos($dsn, '://')) !== false) { + $str = substr($dsn, 0, $pos); + $dsn = substr($dsn, $pos + 3); + } else { + $str = $dsn; + $dsn = null; + } + + // Get phptype and dbsyntax + // $str => phptype(dbsyntax) + if (preg_match('|^(.+?)\((.*?)\)$|', $str, $arr)) { + $parsed['phptype'] = $arr[1]; + $parsed['dbsyntax'] = !$arr[2] ? $arr[1] : $arr[2]; + } else { + $parsed['phptype'] = $str; + $parsed['dbsyntax'] = $str; + } + + if (!count($dsn)) { + return $parsed; + } + + // Get (if found): username and password + // $dsn => username:password@protocol+hostspec/database + if (($at = strrpos($dsn,'@')) !== false) { + $str = substr($dsn, 0, $at); + $dsn = substr($dsn, $at + 1); + if (($pos = strpos($str, ':')) !== false) { + $parsed['username'] = rawurldecode(substr($str, 0, $pos)); + $parsed['password'] = rawurldecode(substr($str, $pos + 1)); + } else { + $parsed['username'] = rawurldecode($str); + } + } + + // Find protocol and hostspec + + if (preg_match('|^([^(]+)\((.*?)\)/?(.*?)$|', $dsn, $match)) { + // $dsn => proto(proto_opts)/database + $proto = $match[1]; + $proto_opts = $match[2] ? $match[2] : false; + $dsn = $match[3]; + + } else { + // $dsn => protocol+hostspec/database (old format) + if (strpos($dsn, '+') !== false) { + list($proto, $dsn) = explode('+', $dsn, 2); + } + if (strpos($dsn, '/') !== false) { + list($proto_opts, $dsn) = explode('/', $dsn, 2); + } else { + $proto_opts = $dsn; + $dsn = null; + } + } + + // process the different protocol options + $parsed['protocol'] = (!empty($proto)) ? $proto : 'tcp'; + $proto_opts = rawurldecode($proto_opts); + if ($parsed['protocol'] == 'tcp') { + if (strpos($proto_opts, ':') !== false) { + list($parsed['hostspec'], + $parsed['port']) = explode(':', $proto_opts); + } else { + $parsed['hostspec'] = $proto_opts; + } + } elseif ($parsed['protocol'] == 'unix') { + $parsed['socket'] = $proto_opts; + } + + // Get dabase if any + // $dsn => database + if ($dsn) { + if (($pos = strpos($dsn, '?')) === false) { + // /database + $parsed['database'] = rawurldecode($dsn); + } else { + // /database?param1=value1¶m2=value2 + $parsed['database'] = rawurldecode(substr($dsn, 0, $pos)); + $dsn = substr($dsn, $pos + 1); + if (strpos($dsn, '&') !== false) { + $opts = explode('&', $dsn); + } else { // database?param1=value1 + $opts = array($dsn); + } + foreach ($opts as $opt) { + list($key, $value) = explode('=', $opt); + if (!isset($parsed[$key])) { + // don't allow params overwrite + $parsed[$key] = rawurldecode($value); + } + } + } + } + + return $parsed; + } + + // }}} +} + +// }}} +// {{{ class DB_Error + +/** + * DB_Error implements a class for reporting portable database error + * messages + * + * @category Database + * @package DB + * @author Stig Bakken + * @copyright 1997-2005 The PHP Group + * @license http://www.php.net/license/3_0.txt PHP License 3.0 + * @version Release: @package_version@ + * @link http://pear.php.net/package/DB + */ +class DB_Error extends PEAR_Error +{ + // {{{ constructor + + /** + * DB_Error constructor + * + * @param mixed $code DB error code, or string with error message + * @param int $mode what "error mode" to operate in + * @param int $level what error level to use for $mode & + * PEAR_ERROR_TRIGGER + * @param mixed $debuginfo additional debug info, such as the last query + * + * @see PEAR_Error + */ + function DB_Error($code = DB_ERROR, $mode = PEAR_ERROR_RETURN, + $level = E_USER_NOTICE, $debuginfo = null) + { + if (is_int($code)) { + $this->PEAR_Error('DB Error: ' . DB::errorMessage($code), $code, + $mode, $level, $debuginfo); + } else { + $this->PEAR_Error("DB Error: $code", DB_ERROR, + $mode, $level, $debuginfo); + } + } + + // }}} +} + +// }}} +// {{{ class DB_result + +/** + * This class implements a wrapper for a DB result set + * + * A new instance of this class will be returned by the DB implementation + * after processing a query that returns data. + * + * @category Database + * @package DB + * @author Stig Bakken + * @copyright 1997-2005 The PHP Group + * @license http://www.php.net/license/3_0.txt PHP License 3.0 + * @version Release: @package_version@ + * @link http://pear.php.net/package/DB + */ +class DB_result +{ + // {{{ properties + + /** + * Should results be freed automatically when there are no more rows? + * @var boolean + * @see DB_common::$options + */ + var $autofree; + + /** + * A reference to the DB_ object + * @var object + */ + var $dbh; + + /** + * The current default fetch mode + * @var integer + * @see DB_common::$fetchmode + */ + var $fetchmode; + + /** + * The name of the class into which results should be fetched when + * DB_FETCHMODE_OBJECT is in effect + * + * @var string + * @see DB_common::$fetchmode_object_class + */ + var $fetchmode_object_class; + + /** + * The number of rows to fetch from a limit query + * @var integer + */ + var $limit_count = null; + + /** + * The row to start fetching from in limit queries + * @var integer + */ + var $limit_from = null; + + /** + * The execute parameters that created this result + * @var array + * @since Property available since Release 1.7.0 + */ + var $parameters; + + /** + * The query string that created this result + * + * Copied here incase it changes in $dbh, which is referenced + * + * @var string + * @since Property available since Release 1.7.0 + */ + var $query; + + /** + * The query result resource id created by PHP + * @var resource + */ + var $result; + + /** + * The present row being dealt with + * @var integer + */ + var $row_counter = null; + + /** + * The prepared statement resource id created by PHP in $dbh + * + * This resource is only available when the result set was created using + * a driver's native execute() method, not PEAR DB's emulated one. + * + * Copied here incase it changes in $dbh, which is referenced + * + * {@internal Mainly here because the InterBase/Firebird API is only + * able to retrieve data from result sets if the statemnt handle is + * still in scope.}} + * + * @var resource + * @since Property available since Release 1.7.0 + */ + var $statement; + + + // }}} + // {{{ constructor + + /** + * This constructor sets the object's properties + * + * @param object &$dbh the DB object reference + * @param resource $result the result resource id + * @param array $options an associative array with result options + * + * @return void + */ + function DB_result(&$dbh, $result, $options = array()) + { + $this->autofree = $dbh->options['autofree']; + $this->dbh = &$dbh; + $this->fetchmode = $dbh->fetchmode; + $this->fetchmode_object_class = $dbh->fetchmode_object_class; + $this->parameters = $dbh->last_parameters; + $this->query = $dbh->last_query; + $this->result = $result; + $this->statement = empty($dbh->last_stmt) ? null : $dbh->last_stmt; + foreach ($options as $key => $value) { + $this->setOption($key, $value); + } + } + + /** + * Set options for the DB_result object + * + * @param string $key the option to set + * @param mixed $value the value to set the option to + * + * @return void + */ + function setOption($key, $value = null) + { + switch ($key) { + case 'limit_from': + $this->limit_from = $value; + break; + case 'limit_count': + $this->limit_count = $value; + } + } + + // }}} + // {{{ fetchRow() + + /** + * Fetch a row of data and return it by reference into an array + * + * The type of array returned can be controlled either by setting this + * method's $fetchmode parameter or by changing the default + * fetch mode setFetchMode() before calling this method. + * + * There are two options for standardizing the information returned + * from databases, ensuring their values are consistent when changing + * DBMS's. These portability options can be turned on when creating a + * new DB object or by using setOption(). + * + * + DB_PORTABILITY_LOWERCASE + * convert names of fields to lower case + * + * + DB_PORTABILITY_RTRIM + * right trim the data + * + * @param int $fetchmode the constant indicating how to format the data + * @param int $rownum the row number to fetch (index starts at 0) + * + * @return mixed an array or object containing the row's data, + * NULL when the end of the result set is reached + * or a DB_Error object on failure. + * + * @see DB_common::setOption(), DB_common::setFetchMode() + */ + function &fetchRow($fetchmode = DB_FETCHMODE_DEFAULT, $rownum = null) + { + if ($fetchmode === DB_FETCHMODE_DEFAULT) { + $fetchmode = $this->fetchmode; + } + if ($fetchmode === DB_FETCHMODE_OBJECT) { + $fetchmode = DB_FETCHMODE_ASSOC; + $object_class = $this->fetchmode_object_class; + } + if ($this->limit_from !== null) { + if ($this->row_counter === null) { + $this->row_counter = $this->limit_from; + // Skip rows + if ($this->dbh->features['limit'] === false) { + $i = 0; + while ($i++ < $this->limit_from) { + $this->dbh->fetchInto($this->result, $arr, $fetchmode); + } + } + } + if ($this->row_counter >= ($this->limit_from + $this->limit_count)) + { + if ($this->autofree) { + $this->free(); + } + $tmp = null; + return $tmp; + } + if ($this->dbh->features['limit'] === 'emulate') { + $rownum = $this->row_counter; + } + $this->row_counter++; + } + $res = $this->dbh->fetchInto($this->result, $arr, $fetchmode, $rownum); + if ($res === DB_OK) { + if (isset($object_class)) { + // The default mode is specified in the + // DB_common::fetchmode_object_class property + if ($object_class == 'stdClass') { + $arr = (object) $arr; + } else { + $arr = &new $object_class($arr); + } + } + return $arr; + } + if ($res == null && $this->autofree) { + $this->free(); + } + return $res; + } + + // }}} + // {{{ fetchInto() + + /** + * Fetch a row of data into an array which is passed by reference + * + * The type of array returned can be controlled either by setting this + * method's $fetchmode parameter or by changing the default + * fetch mode setFetchMode() before calling this method. + * + * There are two options for standardizing the information returned + * from databases, ensuring their values are consistent when changing + * DBMS's. These portability options can be turned on when creating a + * new DB object or by using setOption(). + * + * + DB_PORTABILITY_LOWERCASE + * convert names of fields to lower case + * + * + DB_PORTABILITY_RTRIM + * right trim the data + * + * @param array &$arr the variable where the data should be placed + * @param int $fetchmode the constant indicating how to format the data + * @param int $rownum the row number to fetch (index starts at 0) + * + * @return mixed DB_OK if a row is processed, NULL when the end of the + * result set is reached or a DB_Error object on failure + * + * @see DB_common::setOption(), DB_common::setFetchMode() + */ + function fetchInto(&$arr, $fetchmode = DB_FETCHMODE_DEFAULT, $rownum = null) + { + if ($fetchmode === DB_FETCHMODE_DEFAULT) { + $fetchmode = $this->fetchmode; + } + if ($fetchmode === DB_FETCHMODE_OBJECT) { + $fetchmode = DB_FETCHMODE_ASSOC; + $object_class = $this->fetchmode_object_class; + } + if ($this->limit_from !== null) { + if ($this->row_counter === null) { + $this->row_counter = $this->limit_from; + // Skip rows + if ($this->dbh->features['limit'] === false) { + $i = 0; + while ($i++ < $this->limit_from) { + $this->dbh->fetchInto($this->result, $arr, $fetchmode); + } + } + } + if ($this->row_counter >= ( + $this->limit_from + $this->limit_count)) + { + if ($this->autofree) { + $this->free(); + } + return null; + } + if ($this->dbh->features['limit'] === 'emulate') { + $rownum = $this->row_counter; + } + + $this->row_counter++; + } + $res = $this->dbh->fetchInto($this->result, $arr, $fetchmode, $rownum); + if ($res === DB_OK) { + if (isset($object_class)) { + // default mode specified in the + // DB_common::fetchmode_object_class property + if ($object_class == 'stdClass') { + $arr = (object) $arr; + } else { + $arr = new $object_class($arr); + } + } + return DB_OK; + } + if ($res == null && $this->autofree) { + $this->free(); + } + return $res; + } + + // }}} + // {{{ numCols() + + /** + * Get the the number of columns in a result set + * + * @return int the number of columns. A DB_Error object on failure. + */ + function numCols() + { + return $this->dbh->numCols($this->result); + } + + // }}} + // {{{ numRows() + + /** + * Get the number of rows in a result set + * + * @return int the number of rows. A DB_Error object on failure. + */ + function numRows() + { + if ($this->dbh->features['numrows'] === 'emulate' + && $this->dbh->options['portability'] & DB_PORTABILITY_NUMROWS) + { + if ($this->dbh->features['prepare']) { + $res = $this->dbh->query($this->query, $this->parameters); + } else { + $res = $this->dbh->query($this->query); + } + if (DB::isError($res)) { + return $res; + } + $i = 0; + while ($res->fetchInto($tmp, DB_FETCHMODE_ORDERED)) { + $i++; + } + return $i; + } else { + return $this->dbh->numRows($this->result); + } + } + + // }}} + // {{{ nextResult() + + /** + * Get the next result if a batch of queries was executed + * + * @return bool true if a new result is available or false if not + */ + function nextResult() + { + return $this->dbh->nextResult($this->result); + } + + // }}} + // {{{ free() + + /** + * Frees the resources allocated for this result set + * + * @return bool true on success. A DB_Error object on failure. + */ + function free() + { + $err = $this->dbh->freeResult($this->result); + if (DB::isError($err)) { + return $err; + } + $this->result = false; + $this->statement = false; + return true; + } + + // }}} + // {{{ tableInfo() + + /** + * @see DB_common::tableInfo() + * @deprecated Method deprecated some time before Release 1.2 + */ + function tableInfo($mode = null) + { + if (is_string($mode)) { + return $this->dbh->raiseError(DB_ERROR_NEED_MORE_DATA); + } + return $this->dbh->tableInfo($this, $mode); + } + + // }}} + // {{{ getQuery() + + /** + * Determine the query string that created this result + * + * @return string the query string + * + * @since Method available since Release 1.7.0 + */ + function getQuery() + { + return $this->query; + } + + // }}} + // {{{ getRowCounter() + + /** + * Tells which row number is currently being processed + * + * @return integer the current row being looked at. Starts at 1. + */ + function getRowCounter() + { + return $this->row_counter; + } + + // }}} +} + +// }}} +// {{{ class DB_row + +/** + * PEAR DB Row Object + * + * The object contains a row of data from a result set. Each column's data + * is placed in a property named for the column. + * + * @category Database + * @package DB + * @author Stig Bakken + * @copyright 1997-2005 The PHP Group + * @license http://www.php.net/license/3_0.txt PHP License 3.0 + * @version Release: @package_version@ + * @link http://pear.php.net/package/DB + * @see DB_common::setFetchMode() + */ +class DB_row +{ + // {{{ constructor + + /** + * The constructor places a row's data into properties of this object + * + * @param array the array containing the row's data + * + * @return void + */ + function DB_row(&$arr) + { + foreach ($arr as $key => $value) { + $this->$key = &$arr[$key]; + } + } + + // }}} +} + +// }}} + +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * End: + */ + +?> diff --git a/events/phpFlickr/PEAR/DB/common.php b/events/phpFlickr/PEAR/DB/common.php new file mode 100644 index 0000000..04e71ff --- /dev/null +++ b/events/phpFlickr/PEAR/DB/common.php @@ -0,0 +1,2157 @@ + + * @author Tomas V.V. Cox + * @author Daniel Convissor + * @copyright 1997-2005 The PHP Group + * @license http://www.php.net/license/3_0.txt PHP License 3.0 + * @version CVS: $Id: common.php 32 2005-08-01 06:21:02Z dancoulter $ + * @link http://pear.php.net/package/DB + */ + +/** + * Obtain the PEAR class so it can be extended from + */ +require_once 'PEAR.php'; + +/** + * DB_common is the base class from which each database driver class extends + * + * All common methods are declared here. If a given DBMS driver contains + * a particular method, that method will overload the one here. + * + * @category Database + * @package DB + * @author Stig Bakken + * @author Tomas V.V. Cox + * @author Daniel Convissor + * @copyright 1997-2005 The PHP Group + * @license http://www.php.net/license/3_0.txt PHP License 3.0 + * @version Release: @package_version@ + * @link http://pear.php.net/package/DB + */ +class DB_common extends PEAR +{ + // {{{ properties + + /** + * The current default fetch mode + * @var integer + */ + var $fetchmode = DB_FETCHMODE_ORDERED; + + /** + * The name of the class into which results should be fetched when + * DB_FETCHMODE_OBJECT is in effect + * + * @var string + */ + var $fetchmode_object_class = 'stdClass'; + + /** + * Was a connection present when the object was serialized()? + * @var bool + * @see DB_common::__sleep(), DB_common::__wake() + */ + var $was_connected = null; + + /** + * The most recently executed query + * @var string + */ + var $last_query = ''; + + /** + * Run-time configuration options + * + * The 'optimize' option has been deprecated. Use the 'portability' + * option instead. + * + * @var array + * @see DB_common::setOption() + */ + var $options = array( + 'result_buffering' => 500, + 'persistent' => false, + 'ssl' => false, + 'debug' => 0, + 'seqname_format' => '%s_seq', + 'autofree' => false, + 'portability' => DB_PORTABILITY_NONE, + 'optimize' => 'performance', // Deprecated. Use 'portability'. + ); + + /** + * The parameters from the most recently executed query + * @var array + * @since Property available since Release 1.7.0 + */ + var $last_parameters = array(); + + /** + * The elements from each prepared statement + * @var array + */ + var $prepare_tokens = array(); + + /** + * The data types of the various elements in each prepared statement + * @var array + */ + var $prepare_types = array(); + + /** + * The prepared queries + * @var array + */ + var $prepared_queries = array(); + + + // }}} + // {{{ DB_common + + /** + * This constructor calls $this->PEAR('DB_Error') + * + * @return void + */ + function DB_common() + { + $this->PEAR('DB_Error'); + } + + // }}} + // {{{ __sleep() + + /** + * Automatically indicates which properties should be saved + * when PHP's serialize() function is called + * + * @return array the array of properties names that should be saved + */ + function __sleep() + { + if ($this->connection) { + // Don't disconnect(), people use serialize() for many reasons + $this->was_connected = true; + } else { + $this->was_connected = false; + } + if (isset($this->autocommit)) { + return array('autocommit', + 'dbsyntax', + 'dsn', + 'features', + 'fetchmode', + 'fetchmode_object_class', + 'options', + 'was_connected', + ); + } else { + return array('dbsyntax', + 'dsn', + 'features', + 'fetchmode', + 'fetchmode_object_class', + 'options', + 'was_connected', + ); + } + } + + // }}} + // {{{ __wakeup() + + /** + * Automatically reconnects to the database when PHP's unserialize() + * function is called + * + * The reconnection attempt is only performed if the object was connected + * at the time PHP's serialize() function was run. + * + * @return void + */ + function __wakeup() + { + if ($this->was_connected) { + $this->connect($this->dsn, $this->options); + } + } + + // }}} + // {{{ __toString() + + /** + * Automatic string conversion for PHP 5 + * + * @return string a string describing the current PEAR DB object + * + * @since Method available since Release 1.7.0 + */ + function __toString() + { + $info = strtolower(get_class($this)); + $info .= ': (phptype=' . $this->phptype . + ', dbsyntax=' . $this->dbsyntax . + ')'; + if ($this->connection) { + $info .= ' [connected]'; + } + return $info; + } + + // }}} + // {{{ toString() + + /** + * DEPRECATED: String conversion method + * + * @return string a string describing the current PEAR DB object + * + * @deprecated Method deprecated in Release 1.7.0 + */ + function toString() + { + return $this->__toString(); + } + + // }}} + // {{{ quoteString() + + /** + * DEPRECATED: Quotes a string so it can be safely used within string + * delimiters in a query + * + * @param string $string the string to be quoted + * + * @return string the quoted string + * + * @see DB_common::quoteSmart(), DB_common::escapeSimple() + * @deprecated Method deprecated some time before Release 1.2 + */ + function quoteString($string) + { + $string = $this->quote($string); + if ($string{0} == "'") { + return substr($string, 1, -1); + } + return $string; + } + + // }}} + // {{{ quote() + + /** + * DEPRECATED: Quotes a string so it can be safely used in a query + * + * @param string $string the string to quote + * + * @return string the quoted string or the string NULL + * if the value submitted is null. + * + * @see DB_common::quoteSmart(), DB_common::escapeSimple() + * @deprecated Deprecated in release 1.6.0 + */ + function quote($string = null) + { + return ($string === null) ? 'NULL' + : "'" . str_replace("'", "''", $string) . "'"; + } + + // }}} + // {{{ quoteIdentifier() + + /** + * Quotes a string so it can be safely used as a table or column name + * + * Delimiting style depends on which database driver is being used. + * + * NOTE: just because you CAN use delimited identifiers doesn't mean + * you SHOULD use them. In general, they end up causing way more + * problems than they solve. + * + * Portability is broken by using the following characters inside + * delimited identifiers: + * + backtick (`) -- due to MySQL + * + double quote (") -- due to Oracle + * + brackets ([ or ]) -- due to Access + * + * Delimited identifiers are known to generally work correctly under + * the following drivers: + * + mssql + * + mysql + * + mysqli + * + oci8 + * + odbc(access) + * + odbc(db2) + * + pgsql + * + sqlite + * + sybase (must execute set quoted_identifier on sometime + * prior to use) + * + * InterBase doesn't seem to be able to use delimited identifiers + * via PHP 4. They work fine under PHP 5. + * + * @param string $str the identifier name to be quoted + * + * @return string the quoted identifier + * + * @since Method available since Release 1.6.0 + */ + function quoteIdentifier($str) + { + return '"' . str_replace('"', '""', $str) . '"'; + } + + // }}} + // {{{ quoteSmart() + + /** + * Formats input so it can be safely used in a query + * + * The output depends on the PHP data type of input and the database + * type being used. + * + * @param mixed $in the data to be formatted + * + * @return mixed the formatted data. The format depends on the input's + * PHP type: + *
    + *
  • + * input -> returns + *
  • + *
  • + * null -> the string NULL + *
  • + *
  • + * integer or double -> the unquoted number + *
  • + *
  • + * bool -> output depends on the driver in use + * Most drivers return integers: 1 if + * true or 0 if + * false. + * Some return strings: TRUE if + * true or FALSE if + * false. + * Finally one returns strings: T if + * true or F if + * false. Here is a list of each DBMS, + * the values returned and the suggested column type: + *
      + *
    • + * dbase -> T/F + * (Logical) + *
    • + *
    • + * fbase -> TRUE/FALSE + * (BOOLEAN) + *
    • + *
    • + * ibase -> 1/0 + * (SMALLINT) [1] + *
    • + *
    • + * ifx -> 1/0 + * (SMALLINT) [1] + *
    • + *
    • + * msql -> 1/0 + * (INTEGER) + *
    • + *
    • + * mssql -> 1/0 + * (BIT) + *
    • + *
    • + * mysql -> 1/0 + * (TINYINT(1)) + *
    • + *
    • + * mysqli -> 1/0 + * (TINYINT(1)) + *
    • + *
    • + * oci8 -> 1/0 + * (NUMBER(1)) + *
    • + *
    • + * odbc -> 1/0 + * (SMALLINT) [1] + *
    • + *
    • + * pgsql -> TRUE/FALSE + * (BOOLEAN) + *
    • + *
    • + * sqlite -> 1/0 + * (INTEGER) + *
    • + *
    • + * sybase -> 1/0 + * (TINYINT(1)) + *
    • + *
    + * [1] Accommodate the lowest common denominator because not all + * versions of have BOOLEAN. + *
  • + *
  • + * other (including strings and numeric strings) -> + * the data with single quotes escaped by preceeding + * single quotes, backslashes are escaped by preceeding + * backslashes, then the whole string is encapsulated + * between single quotes + *
  • + *
+ * + * @see DB_common::escapeSimple() + * @since Method available since Release 1.6.0 + */ + function quoteSmart($in) + { + if (is_int($in) || is_double($in)) { + return $in; + } elseif (is_bool($in)) { + return $in ? 1 : 0; + } elseif (is_null($in)) { + return 'NULL'; + } else { + return "'" . $this->escapeSimple($in) . "'"; + } + } + + // }}} + // {{{ escapeSimple() + + /** + * Escapes a string according to the current DBMS's standards + * + * In SQLite, this makes things safe for inserts/updates, but may + * cause problems when performing text comparisons against columns + * containing binary data. See the + * {@link http://php.net/sqlite_escape_string PHP manual} for more info. + * + * @param string $str the string to be escaped + * + * @return string the escaped string + * + * @see DB_common::quoteSmart() + * @since Method available since Release 1.6.0 + */ + function escapeSimple($str) + { + return str_replace("'", "''", $str); + } + + // }}} + // {{{ provides() + + /** + * Tells whether the present driver supports a given feature + * + * @param string $feature the feature you're curious about + * + * @return bool whether this driver supports $feature + */ + function provides($feature) + { + return $this->features[$feature]; + } + + // }}} + // {{{ setFetchMode() + + /** + * Sets the fetch mode that should be used by default for query results + * + * @param integer $fetchmode DB_FETCHMODE_ORDERED, DB_FETCHMODE_ASSOC + * or DB_FETCHMODE_OBJECT + * @param string $object_class the class name of the object to be returned + * by the fetch methods when the + * DB_FETCHMODE_OBJECT mode is selected. + * If no class is specified by default a cast + * to object from the assoc array row will be + * done. There is also the posibility to use + * and extend the 'DB_row' class. + * + * @see DB_FETCHMODE_ORDERED, DB_FETCHMODE_ASSOC, DB_FETCHMODE_OBJECT + */ + function setFetchMode($fetchmode, $object_class = 'stdClass') + { + switch ($fetchmode) { + case DB_FETCHMODE_OBJECT: + $this->fetchmode_object_class = $object_class; + case DB_FETCHMODE_ORDERED: + case DB_FETCHMODE_ASSOC: + $this->fetchmode = $fetchmode; + break; + default: + return $this->raiseError('invalid fetchmode mode'); + } + } + + // }}} + // {{{ setOption() + + /** + * Sets run-time configuration options for PEAR DB + * + * Options, their data types, default values and description: + *
    + *
  • + * autofree boolean = false + *
    should results be freed automatically when there are no + * more rows? + *
  • + * result_buffering integer = 500 + *
    how many rows of the result set should be buffered? + *
    In mysql: mysql_unbuffered_query() is used instead of + * mysql_query() if this value is 0. (Release 1.7.0) + *
    In oci8: this value is passed to ocisetprefetch(). + * (Release 1.7.0) + *
  • + * debug integer = 0 + *
    debug level + *
  • + * persistent boolean = false + *
    should the connection be persistent? + *
  • + * portability integer = DB_PORTABILITY_NONE + *
    portability mode constant (see below) + *
  • + * seqname_format string = %s_seq + *
    the sprintf() format string used on sequence names. This + * format is applied to sequence names passed to + * createSequence(), nextID() and dropSequence(). + *
  • + * ssl boolean = false + *
    use ssl to connect? + *
  • + *
+ * + * ----------------------------------------- + * + * PORTABILITY MODES + * + * These modes are bitwised, so they can be combined using | + * and removed using ^. See the examples section below on how + * to do this. + * + * DB_PORTABILITY_NONE + * turn off all portability features + * + * This mode gets automatically turned on if the deprecated + * optimize option gets set to performance. + * + * + * DB_PORTABILITY_LOWERCASE + * convert names of tables and fields to lower case when using + * get*(), fetch*() and tableInfo() + * + * This mode gets automatically turned on in the following databases + * if the deprecated option optimize gets set to + * portability: + * + oci8 + * + * + * DB_PORTABILITY_RTRIM + * right trim the data output by get*() fetch*() + * + * + * DB_PORTABILITY_DELETE_COUNT + * force reporting the number of rows deleted + * + * Some DBMS's don't count the number of rows deleted when performing + * simple DELETE FROM tablename queries. This portability + * mode tricks such DBMS's into telling the count by adding + * WHERE 1=1 to the end of DELETE queries. + * + * This mode gets automatically turned on in the following databases + * if the deprecated option optimize gets set to + * portability: + * + fbsql + * + mysql + * + mysqli + * + sqlite + * + * + * DB_PORTABILITY_NUMROWS + * enable hack that makes numRows() work in Oracle + * + * This mode gets automatically turned on in the following databases + * if the deprecated option optimize gets set to + * portability: + * + oci8 + * + * + * DB_PORTABILITY_ERRORS + * makes certain error messages in certain drivers compatible + * with those from other DBMS's + * + * + mysql, mysqli: change unique/primary key constraints + * DB_ERROR_ALREADY_EXISTS -> DB_ERROR_CONSTRAINT + * + * + odbc(access): MS's ODBC driver reports 'no such field' as code + * 07001, which means 'too few parameters.' When this option is on + * that code gets mapped to DB_ERROR_NOSUCHFIELD. + * DB_ERROR_MISMATCH -> DB_ERROR_NOSUCHFIELD + * + * DB_PORTABILITY_NULL_TO_EMPTY + * convert null values to empty strings in data output by get*() and + * fetch*(). Needed because Oracle considers empty strings to be null, + * while most other DBMS's know the difference between empty and null. + * + * + * DB_PORTABILITY_ALL + * turn on all portability features + * + * ----------------------------------------- + * + * Example 1. Simple setOption() example + * + * $db->setOption('autofree', true); + * + * + * Example 2. Portability for lowercasing and trimming + * + * $db->setOption('portability', + * DB_PORTABILITY_LOWERCASE | DB_PORTABILITY_RTRIM); + * + * + * Example 3. All portability options except trimming + * + * $db->setOption('portability', + * DB_PORTABILITY_ALL ^ DB_PORTABILITY_RTRIM); + * + * + * @param string $option option name + * @param mixed $value value for the option + * + * @return int DB_OK on success. A DB_Error object on failure. + * + * @see DB_common::$options + */ + function setOption($option, $value) + { + if (isset($this->options[$option])) { + $this->options[$option] = $value; + + /* + * Backwards compatibility check for the deprecated 'optimize' + * option. Done here in case settings change after connecting. + */ + if ($option == 'optimize') { + if ($value == 'portability') { + switch ($this->phptype) { + case 'oci8': + $this->options['portability'] = + DB_PORTABILITY_LOWERCASE | + DB_PORTABILITY_NUMROWS; + break; + case 'fbsql': + case 'mysql': + case 'mysqli': + case 'sqlite': + $this->options['portability'] = + DB_PORTABILITY_DELETE_COUNT; + break; + } + } else { + $this->options['portability'] = DB_PORTABILITY_NONE; + } + } + + return DB_OK; + } + return $this->raiseError("unknown option $option"); + } + + // }}} + // {{{ getOption() + + /** + * Returns the value of an option + * + * @param string $option the option name you're curious about + * + * @return mixed the option's value + */ + function getOption($option) + { + if (isset($this->options[$option])) { + return $this->options[$option]; + } + return $this->raiseError("unknown option $option"); + } + + // }}} + // {{{ prepare() + + /** + * Prepares a query for multiple execution with execute() + * + * Creates a query that can be run multiple times. Each time it is run, + * the placeholders, if any, will be replaced by the contents of + * execute()'s $data argument. + * + * Three types of placeholders can be used: + * + ? scalar value (i.e. strings, integers). The system + * will automatically quote and escape the data. + * + ! value is inserted 'as is' + * + & requires a file name. The file's contents get + * inserted into the query (i.e. saving binary + * data in a db) + * + * Example 1. + * + * $sth = $db->prepare('INSERT INTO tbl (a, b, c) VALUES (?, !, &)'); + * $data = array( + * "John's text", + * "'it''s good'", + * 'filename.txt' + * ); + * $res = $db->execute($sth, $data); + * + * + * Use backslashes to escape placeholder characters if you don't want + * them to be interpreted as placeholders: + *
+     *    "UPDATE foo SET col=? WHERE col='over \& under'"
+     * 
+ * + * With some database backends, this is emulated. + * + * {@internal ibase and oci8 have their own prepare() methods.}} + * + * @param string $query the query to be prepared + * + * @return mixed DB statement resource on success. A DB_Error object + * on failure. + * + * @see DB_common::execute() + */ + function prepare($query) + { + $tokens = preg_split('/((?prepare_tokens[] = &$newtokens; + end($this->prepare_tokens); + + $k = key($this->prepare_tokens); + $this->prepare_types[$k] = $types; + $this->prepared_queries[$k] = implode(' ', $newtokens); + + return $k; + } + + // }}} + // {{{ autoPrepare() + + /** + * Automaticaly generates an insert or update query and pass it to prepare() + * + * @param string $table the table name + * @param array $table_fields the array of field names + * @param int $mode a type of query to make: + * DB_AUTOQUERY_INSERT or DB_AUTOQUERY_UPDATE + * @param string $where for update queries: the WHERE clause to + * append to the SQL statement. Don't + * include the "WHERE" keyword. + * + * @return resource the query handle + * + * @uses DB_common::prepare(), DB_common::buildManipSQL() + */ + function autoPrepare($table, $table_fields, $mode = DB_AUTOQUERY_INSERT, + $where = false) + { + $query = $this->buildManipSQL($table, $table_fields, $mode, $where); + if (DB::isError($query)) { + return $query; + } + return $this->prepare($query); + } + + // }}} + // {{{ autoExecute() + + /** + * Automaticaly generates an insert or update query and call prepare() + * and execute() with it + * + * @param string $table the table name + * @param array $fields_values the associative array where $key is a + * field name and $value its value + * @param int $mode a type of query to make: + * DB_AUTOQUERY_INSERT or DB_AUTOQUERY_UPDATE + * @param string $where for update queries: the WHERE clause to + * append to the SQL statement. Don't + * include the "WHERE" keyword. + * + * @return mixed a new DB_result object for successful SELECT queries + * or DB_OK for successul data manipulation queries. + * A DB_Error object on failure. + * + * @uses DB_common::autoPrepare(), DB_common::execute() + */ + function autoExecute($table, $fields_values, $mode = DB_AUTOQUERY_INSERT, + $where = false) + { + $sth = $this->autoPrepare($table, array_keys($fields_values), $mode, + $where); + if (DB::isError($sth)) { + return $sth; + } + $ret =& $this->execute($sth, array_values($fields_values)); + $this->freePrepared($sth); + return $ret; + + } + + // }}} + // {{{ buildManipSQL() + + /** + * Produces an SQL query string for autoPrepare() + * + * Example: + *
+     * buildManipSQL('table_sql', array('field1', 'field2', 'field3'),
+     *               DB_AUTOQUERY_INSERT);
+     * 
+ * + * That returns + * + * INSERT INTO table_sql (field1,field2,field3) VALUES (?,?,?) + * + * + * NOTES: + * - This belongs more to a SQL Builder class, but this is a simple + * facility. + * - Be carefull! If you don't give a $where param with an UPDATE + * query, all the records of the table will be updated! + * + * @param string $table the table name + * @param array $table_fields the array of field names + * @param int $mode a type of query to make: + * DB_AUTOQUERY_INSERT or DB_AUTOQUERY_UPDATE + * @param string $where for update queries: the WHERE clause to + * append to the SQL statement. Don't + * include the "WHERE" keyword. + * + * @return string the sql query for autoPrepare() + */ + function buildManipSQL($table, $table_fields, $mode, $where = false) + { + if (count($table_fields) == 0) { + return $this->raiseError(DB_ERROR_NEED_MORE_DATA); + } + $first = true; + switch ($mode) { + case DB_AUTOQUERY_INSERT: + $values = ''; + $names = ''; + foreach ($table_fields as $value) { + if ($first) { + $first = false; + } else { + $names .= ','; + $values .= ','; + } + $names .= $value; + $values .= '?'; + } + return "INSERT INTO $table ($names) VALUES ($values)"; + case DB_AUTOQUERY_UPDATE: + $set = ''; + foreach ($table_fields as $value) { + if ($first) { + $first = false; + } else { + $set .= ','; + } + $set .= "$value = ?"; + } + $sql = "UPDATE $table SET $set"; + if ($where) { + $sql .= " WHERE $where"; + } + return $sql; + default: + return $this->raiseError(DB_ERROR_SYNTAX); + } + } + + // }}} + // {{{ execute() + + /** + * Executes a DB statement prepared with prepare() + * + * Example 1. + * + * $sth = $db->prepare('INSERT INTO tbl (a, b, c) VALUES (?, !, &)'); + * $data = array( + * "John's text", + * "'it''s good'", + * 'filename.txt' + * ); + * $res =& $db->execute($sth, $data); + * + * + * @param resource $stmt a DB statement resource returned from prepare() + * @param mixed $data array, string or numeric data to be used in + * execution of the statement. Quantity of items + * passed must match quantity of placeholders in + * query: meaning 1 placeholder for non-array + * parameters or 1 placeholder per array element. + * + * @return mixed a new DB_result object for successful SELECT queries + * or DB_OK for successul data manipulation queries. + * A DB_Error object on failure. + * + * {@internal ibase and oci8 have their own execute() methods.}} + * + * @see DB_common::prepare() + */ + function &execute($stmt, $data = array()) + { + $realquery = $this->executeEmulateQuery($stmt, $data); + if (DB::isError($realquery)) { + return $realquery; + } + $result = $this->simpleQuery($realquery); + + if ($result === DB_OK || DB::isError($result)) { + return $result; + } else { + $tmp =& new DB_result($this, $result); + return $tmp; + } + } + + // }}} + // {{{ executeEmulateQuery() + + /** + * Emulates executing prepared statements if the DBMS not support them + * + * @param resource $stmt a DB statement resource returned from execute() + * @param mixed $data array, string or numeric data to be used in + * execution of the statement. Quantity of items + * passed must match quantity of placeholders in + * query: meaning 1 placeholder for non-array + * parameters or 1 placeholder per array element. + * + * @return mixed a string containing the real query run when emulating + * prepare/execute. A DB_Error object on failure. + * + * @access protected + * @see DB_common::execute() + */ + function executeEmulateQuery($stmt, $data = array()) + { + $stmt = (int)$stmt; + $data = (array)$data; + $this->last_parameters = $data; + + if (count($this->prepare_types[$stmt]) != count($data)) { + $this->last_query = $this->prepared_queries[$stmt]; + return $this->raiseError(DB_ERROR_MISMATCH); + } + + $realquery = $this->prepare_tokens[$stmt][0]; + + $i = 0; + foreach ($data as $value) { + if ($this->prepare_types[$stmt][$i] == DB_PARAM_SCALAR) { + $realquery .= $this->quoteSmart($value); + } elseif ($this->prepare_types[$stmt][$i] == DB_PARAM_OPAQUE) { + $fp = @fopen($value, 'rb'); + if (!$fp) { + return $this->raiseError(DB_ERROR_ACCESS_VIOLATION); + } + $realquery .= $this->quoteSmart(fread($fp, filesize($value))); + fclose($fp); + } else { + $realquery .= $value; + } + + $realquery .= $this->prepare_tokens[$stmt][++$i]; + } + + return $realquery; + } + + // }}} + // {{{ executeMultiple() + + /** + * Performs several execute() calls on the same statement handle + * + * $data must be an array indexed numerically + * from 0, one execute call is done for every "row" in the array. + * + * If an error occurs during execute(), executeMultiple() does not + * execute the unfinished rows, but rather returns that error. + * + * @param resource $stmt query handle from prepare() + * @param array $data numeric array containing the + * data to insert into the query + * + * @return int DB_OK on success. A DB_Error object on failure. + * + * @see DB_common::prepare(), DB_common::execute() + */ + function executeMultiple($stmt, $data) + { + foreach ($data as $value) { + $res =& $this->execute($stmt, $value); + if (DB::isError($res)) { + return $res; + } + } + return DB_OK; + } + + // }}} + // {{{ freePrepared() + + /** + * Frees the internal resources associated with a prepared query + * + * @param resource $stmt the prepared statement's PHP resource + * @param bool $free_resource should the PHP resource be freed too? + * Use false if you need to get data + * from the result set later. + * + * @return bool TRUE on success, FALSE if $result is invalid + * + * @see DB_common::prepare() + */ + function freePrepared($stmt, $free_resource = true) + { + $stmt = (int)$stmt; + if (isset($this->prepare_tokens[$stmt])) { + unset($this->prepare_tokens[$stmt]); + unset($this->prepare_types[$stmt]); + unset($this->prepared_queries[$stmt]); + return true; + } + return false; + } + + // }}} + // {{{ modifyQuery() + + /** + * Changes a query string for various DBMS specific reasons + * + * It is defined here to ensure all drivers have this method available. + * + * @param string $query the query string to modify + * + * @return string the modified query string + * + * @access protected + * @see DB_mysql::modifyQuery(), DB_oci8::modifyQuery(), + * DB_sqlite::modifyQuery() + */ + function modifyQuery($query) + { + return $query; + } + + // }}} + // {{{ modifyLimitQuery() + + /** + * Adds LIMIT clauses to a query string according to current DBMS standards + * + * It is defined here to assure that all implementations + * have this method defined. + * + * @param string $query the query to modify + * @param int $from the row to start to fetching (0 = the first row) + * @param int $count the numbers of rows to fetch + * @param mixed $params array, string or numeric data to be used in + * execution of the statement. Quantity of items + * passed must match quantity of placeholders in + * query: meaning 1 placeholder for non-array + * parameters or 1 placeholder per array element. + * + * @return string the query string with LIMIT clauses added + * + * @access protected + */ + function modifyLimitQuery($query, $from, $count, $params = array()) + { + return $query; + } + + // }}} + // {{{ query() + + /** + * Sends a query to the database server + * + * The query string can be either a normal statement to be sent directly + * to the server OR if $params are passed the query can have + * placeholders and it will be passed through prepare() and execute(). + * + * @param string $query the SQL query or the statement to prepare + * @param mixed $params array, string or numeric data to be used in + * execution of the statement. Quantity of items + * passed must match quantity of placeholders in + * query: meaning 1 placeholder for non-array + * parameters or 1 placeholder per array element. + * + * @return mixed a new DB_result object for successful SELECT queries + * or DB_OK for successul data manipulation queries. + * A DB_Error object on failure. + * + * @see DB_result, DB_common::prepare(), DB_common::execute() + */ + function &query($query, $params = array()) + { + if (sizeof($params) > 0) { + $sth = $this->prepare($query); + if (DB::isError($sth)) { + return $sth; + } + $ret =& $this->execute($sth, $params); + $this->freePrepared($sth, false); + return $ret; + } else { + $this->last_parameters = array(); + $result = $this->simpleQuery($query); + if ($result === DB_OK || DB::isError($result)) { + return $result; + } else { + $tmp =& new DB_result($this, $result); + return $tmp; + } + } + } + + // }}} + // {{{ limitQuery() + + /** + * Generates and executes a LIMIT query + * + * @param string $query the query + * @param intr $from the row to start to fetching (0 = the first row) + * @param int $count the numbers of rows to fetch + * @param mixed $params array, string or numeric data to be used in + * execution of the statement. Quantity of items + * passed must match quantity of placeholders in + * query: meaning 1 placeholder for non-array + * parameters or 1 placeholder per array element. + * + * @return mixed a new DB_result object for successful SELECT queries + * or DB_OK for successul data manipulation queries. + * A DB_Error object on failure. + */ + function &limitQuery($query, $from, $count, $params = array()) + { + $query = $this->modifyLimitQuery($query, $from, $count, $params); + if (DB::isError($query)){ + return $query; + } + $result =& $this->query($query, $params); + if (is_a($result, 'DB_result')) { + $result->setOption('limit_from', $from); + $result->setOption('limit_count', $count); + } + return $result; + } + + // }}} + // {{{ getOne() + + /** + * Fetches the first column of the first row from a query result + * + * Takes care of doing the query and freeing the results when finished. + * + * @param string $query the SQL query + * @param mixed $params array, string or numeric data to be used in + * execution of the statement. Quantity of items + * passed must match quantity of placeholders in + * query: meaning 1 placeholder for non-array + * parameters or 1 placeholder per array element. + * + * @return mixed the returned value of the query. + * A DB_Error object on failure. + */ + function &getOne($query, $params = array()) + { + $params = (array)$params; + // modifyLimitQuery() would be nice here, but it causes BC issues + if (sizeof($params) > 0) { + $sth = $this->prepare($query); + if (DB::isError($sth)) { + return $sth; + } + $res =& $this->execute($sth, $params); + $this->freePrepared($sth); + } else { + $res =& $this->query($query); + } + + if (DB::isError($res)) { + return $res; + } + + $err = $res->fetchInto($row, DB_FETCHMODE_ORDERED); + $res->free(); + + if ($err !== DB_OK) { + return $err; + } + + return $row[0]; + } + + // }}} + // {{{ getRow() + + /** + * Fetches the first row of data returned from a query result + * + * Takes care of doing the query and freeing the results when finished. + * + * @param string $query the SQL query + * @param mixed $params array, string or numeric data to be used in + * execution of the statement. Quantity of items + * passed must match quantity of placeholders in + * query: meaning 1 placeholder for non-array + * parameters or 1 placeholder per array element. + * @param int $fetchmode the fetch mode to use + * + * @return array the first row of results as an array. + * A DB_Error object on failure. + */ + function &getRow($query, $params = array(), + $fetchmode = DB_FETCHMODE_DEFAULT) + { + // compat check, the params and fetchmode parameters used to + // have the opposite order + if (!is_array($params)) { + if (is_array($fetchmode)) { + if ($params === null) { + $tmp = DB_FETCHMODE_DEFAULT; + } else { + $tmp = $params; + } + $params = $fetchmode; + $fetchmode = $tmp; + } elseif ($params !== null) { + $fetchmode = $params; + $params = array(); + } + } + // modifyLimitQuery() would be nice here, but it causes BC issues + if (sizeof($params) > 0) { + $sth = $this->prepare($query); + if (DB::isError($sth)) { + return $sth; + } + $res =& $this->execute($sth, $params); + $this->freePrepared($sth); + } else { + $res =& $this->query($query); + } + + if (DB::isError($res)) { + return $res; + } + + $err = $res->fetchInto($row, $fetchmode); + + $res->free(); + + if ($err !== DB_OK) { + return $err; + } + + return $row; + } + + // }}} + // {{{ getCol() + + /** + * Fetches a single column from a query result and returns it as an + * indexed array + * + * @param string $query the SQL query + * @param mixed $col which column to return (integer [column number, + * starting at 0] or string [column name]) + * @param mixed $params array, string or numeric data to be used in + * execution of the statement. Quantity of items + * passed must match quantity of placeholders in + * query: meaning 1 placeholder for non-array + * parameters or 1 placeholder per array element. + * + * @return array the results as an array. A DB_Error object on failure. + * + * @see DB_common::query() + */ + function &getCol($query, $col = 0, $params = array()) + { + $params = (array)$params; + if (sizeof($params) > 0) { + $sth = $this->prepare($query); + + if (DB::isError($sth)) { + return $sth; + } + + $res =& $this->execute($sth, $params); + $this->freePrepared($sth); + } else { + $res =& $this->query($query); + } + + if (DB::isError($res)) { + return $res; + } + + $fetchmode = is_int($col) ? DB_FETCHMODE_ORDERED : DB_FETCHMODE_ASSOC; + + if (!is_array($row = $res->fetchRow($fetchmode))) { + $ret = array(); + } else { + if (!array_key_exists($col, $row)) { + $ret =& $this->raiseError(DB_ERROR_NOSUCHFIELD); + } else { + $ret = array($row[$col]); + while (is_array($row = $res->fetchRow($fetchmode))) { + $ret[] = $row[$col]; + } + } + } + + $res->free(); + + if (DB::isError($row)) { + $ret = $row; + } + + return $ret; + } + + // }}} + // {{{ getAssoc() + + /** + * Fetches an entire query result and returns it as an + * associative array using the first column as the key + * + * If the result set contains more than two columns, the value + * will be an array of the values from column 2-n. If the result + * set contains only two columns, the returned value will be a + * scalar with the value of the second column (unless forced to an + * array with the $force_array parameter). A DB error code is + * returned on errors. If the result set contains fewer than two + * columns, a DB_ERROR_TRUNCATED error is returned. + * + * For example, if the table "mytable" contains: + * + *
+     *  ID      TEXT       DATE
+     * --------------------------------
+     *  1       'one'      944679408
+     *  2       'two'      944679408
+     *  3       'three'    944679408
+     * 
+ * + * Then the call getAssoc('SELECT id,text FROM mytable') returns: + *
+     *   array(
+     *     '1' => 'one',
+     *     '2' => 'two',
+     *     '3' => 'three',
+     *   )
+     * 
+ * + * ...while the call getAssoc('SELECT id,text,date FROM mytable') returns: + *
+     *   array(
+     *     '1' => array('one', '944679408'),
+     *     '2' => array('two', '944679408'),
+     *     '3' => array('three', '944679408')
+     *   )
+     * 
+ * + * If the more than one row occurs with the same value in the + * first column, the last row overwrites all previous ones by + * default. Use the $group parameter if you don't want to + * overwrite like this. Example: + * + *
+     * getAssoc('SELECT category,id,name FROM mytable', false, null,
+     *          DB_FETCHMODE_ASSOC, true) returns:
+     *
+     *   array(
+     *     '1' => array(array('id' => '4', 'name' => 'number four'),
+     *                  array('id' => '6', 'name' => 'number six')
+     *            ),
+     *     '9' => array(array('id' => '4', 'name' => 'number four'),
+     *                  array('id' => '6', 'name' => 'number six')
+     *            )
+     *   )
+     * 
+ * + * Keep in mind that database functions in PHP usually return string + * values for results regardless of the database's internal type. + * + * @param string $query the SQL query + * @param bool $force_array used only when the query returns + * exactly two columns. If true, the values + * of the returned array will be one-element + * arrays instead of scalars. + * @param mixed $params array, string or numeric data to be used in + * execution of the statement. Quantity of + * items passed must match quantity of + * placeholders in query: meaning 1 + * placeholder for non-array parameters or + * 1 placeholder per array element. + * @param int $fetchmode the fetch mode to use + * @param bool $group if true, the values of the returned array + * is wrapped in another array. If the same + * key value (in the first column) repeats + * itself, the values will be appended to + * this array instead of overwriting the + * existing values. + * + * @return array the associative array containing the query results. + * A DB_Error object on failure. + */ + function &getAssoc($query, $force_array = false, $params = array(), + $fetchmode = DB_FETCHMODE_DEFAULT, $group = false) + { + $params = (array)$params; + if (sizeof($params) > 0) { + $sth = $this->prepare($query); + + if (DB::isError($sth)) { + return $sth; + } + + $res =& $this->execute($sth, $params); + $this->freePrepared($sth); + } else { + $res =& $this->query($query); + } + + if (DB::isError($res)) { + return $res; + } + if ($fetchmode == DB_FETCHMODE_DEFAULT) { + $fetchmode = $this->fetchmode; + } + $cols = $res->numCols(); + + if ($cols < 2) { + $tmp =& $this->raiseError(DB_ERROR_TRUNCATED); + return $tmp; + } + + $results = array(); + + if ($cols > 2 || $force_array) { + // return array values + // XXX this part can be optimized + if ($fetchmode == DB_FETCHMODE_ASSOC) { + while (is_array($row = $res->fetchRow(DB_FETCHMODE_ASSOC))) { + reset($row); + $key = current($row); + unset($row[key($row)]); + if ($group) { + $results[$key][] = $row; + } else { + $results[$key] = $row; + } + } + } elseif ($fetchmode == DB_FETCHMODE_OBJECT) { + while ($row = $res->fetchRow(DB_FETCHMODE_OBJECT)) { + $arr = get_object_vars($row); + $key = current($arr); + if ($group) { + $results[$key][] = $row; + } else { + $results[$key] = $row; + } + } + } else { + while (is_array($row = $res->fetchRow(DB_FETCHMODE_ORDERED))) { + // we shift away the first element to get + // indices running from 0 again + $key = array_shift($row); + if ($group) { + $results[$key][] = $row; + } else { + $results[$key] = $row; + } + } + } + if (DB::isError($row)) { + $results = $row; + } + } else { + // return scalar values + while (is_array($row = $res->fetchRow(DB_FETCHMODE_ORDERED))) { + if ($group) { + $results[$row[0]][] = $row[1]; + } else { + $results[$row[0]] = $row[1]; + } + } + if (DB::isError($row)) { + $results = $row; + } + } + + $res->free(); + + return $results; + } + + // }}} + // {{{ getAll() + + /** + * Fetches all of the rows from a query result + * + * @param string $query the SQL query + * @param mixed $params array, string or numeric data to be used in + * execution of the statement. Quantity of + * items passed must match quantity of + * placeholders in query: meaning 1 + * placeholder for non-array parameters or + * 1 placeholder per array element. + * @param int $fetchmode the fetch mode to use: + * + DB_FETCHMODE_ORDERED + * + DB_FETCHMODE_ASSOC + * + DB_FETCHMODE_ORDERED | DB_FETCHMODE_FLIPPED + * + DB_FETCHMODE_ASSOC | DB_FETCHMODE_FLIPPED + * + * @return array the nested array. A DB_Error object on failure. + */ + function &getAll($query, $params = array(), + $fetchmode = DB_FETCHMODE_DEFAULT) + { + // compat check, the params and fetchmode parameters used to + // have the opposite order + if (!is_array($params)) { + if (is_array($fetchmode)) { + if ($params === null) { + $tmp = DB_FETCHMODE_DEFAULT; + } else { + $tmp = $params; + } + $params = $fetchmode; + $fetchmode = $tmp; + } elseif ($params !== null) { + $fetchmode = $params; + $params = array(); + } + } + + if (sizeof($params) > 0) { + $sth = $this->prepare($query); + + if (DB::isError($sth)) { + return $sth; + } + + $res =& $this->execute($sth, $params); + $this->freePrepared($sth); + } else { + $res =& $this->query($query); + } + + if ($res === DB_OK || DB::isError($res)) { + return $res; + } + + $results = array(); + while (DB_OK === $res->fetchInto($row, $fetchmode)) { + if ($fetchmode & DB_FETCHMODE_FLIPPED) { + foreach ($row as $key => $val) { + $results[$key][] = $val; + } + } else { + $results[] = $row; + } + } + + $res->free(); + + if (DB::isError($row)) { + $tmp =& $this->raiseError($row); + return $tmp; + } + return $results; + } + + // }}} + // {{{ autoCommit() + + /** + * Enables or disables automatic commits + * + * @param bool $onoff true turns it on, false turns it off + * + * @return int DB_OK on success. A DB_Error object if the driver + * doesn't support auto-committing transactions. + */ + function autoCommit($onoff = false) + { + return $this->raiseError(DB_ERROR_NOT_CAPABLE); + } + + // }}} + // {{{ commit() + + /** + * Commits the current transaction + * + * @return int DB_OK on success. A DB_Error object on failure. + */ + function commit() + { + return $this->raiseError(DB_ERROR_NOT_CAPABLE); + } + + // }}} + // {{{ rollback() + + /** + * Reverts the current transaction + * + * @return int DB_OK on success. A DB_Error object on failure. + */ + function rollback() + { + return $this->raiseError(DB_ERROR_NOT_CAPABLE); + } + + // }}} + // {{{ numRows() + + /** + * Determines the number of rows in a query result + * + * @param resource $result the query result idenifier produced by PHP + * + * @return int the number of rows. A DB_Error object on failure. + */ + function numRows($result) + { + return $this->raiseError(DB_ERROR_NOT_CAPABLE); + } + + // }}} + // {{{ affectedRows() + + /** + * Determines the number of rows affected by a data maniuplation query + * + * 0 is returned for queries that don't manipulate data. + * + * @return int the number of rows. A DB_Error object on failure. + */ + function affectedRows() + { + return $this->raiseError(DB_ERROR_NOT_CAPABLE); + } + + // }}} + // {{{ getSequenceName() + + /** + * Generates the name used inside the database for a sequence + * + * The createSequence() docblock contains notes about storing sequence + * names. + * + * @param string $sqn the sequence's public name + * + * @return string the sequence's name in the backend + * + * @access protected + * @see DB_common::createSequence(), DB_common::dropSequence(), + * DB_common::nextID(), DB_common::setOption() + */ + function getSequenceName($sqn) + { + return sprintf($this->getOption('seqname_format'), + preg_replace('/[^a-z0-9_.]/i', '_', $sqn)); + } + + // }}} + // {{{ nextId() + + /** + * Returns the next free id in a sequence + * + * @param string $seq_name name of the sequence + * @param boolean $ondemand when true, the seqence is automatically + * created if it does not exist + * + * @return int the next id number in the sequence. + * A DB_Error object on failure. + * + * @see DB_common::createSequence(), DB_common::dropSequence(), + * DB_common::getSequenceName() + */ + function nextId($seq_name, $ondemand = true) + { + return $this->raiseError(DB_ERROR_NOT_CAPABLE); + } + + // }}} + // {{{ createSequence() + + /** + * Creates a new sequence + * + * The name of a given sequence is determined by passing the string + * provided in the $seq_name argument through PHP's sprintf() + * function using the value from the seqname_format option as + * the sprintf()'s format argument. + * + * seqname_format is set via setOption(). + * + * @param string $seq_name name of the new sequence + * + * @return int DB_OK on success. A DB_Error object on failure. + * + * @see DB_common::dropSequence(), DB_common::getSequenceName(), + * DB_common::nextID() + */ + function createSequence($seq_name) + { + return $this->raiseError(DB_ERROR_NOT_CAPABLE); + } + + // }}} + // {{{ dropSequence() + + /** + * Deletes a sequence + * + * @param string $seq_name name of the sequence to be deleted + * + * @return int DB_OK on success. A DB_Error object on failure. + * + * @see DB_common::createSequence(), DB_common::getSequenceName(), + * DB_common::nextID() + */ + function dropSequence($seq_name) + { + return $this->raiseError(DB_ERROR_NOT_CAPABLE); + } + + // }}} + // {{{ raiseError() + + /** + * Communicates an error and invoke error callbacks, etc + * + * Basically a wrapper for PEAR::raiseError without the message string. + * + * @param mixed integer error code, or a PEAR error object (all + * other parameters are ignored if this parameter is + * an object + * @param int error mode, see PEAR_Error docs + * @param mixed if error mode is PEAR_ERROR_TRIGGER, this is the + * error level (E_USER_NOTICE etc). If error mode is + * PEAR_ERROR_CALLBACK, this is the callback function, + * either as a function name, or as an array of an + * object and method name. For other error modes this + * parameter is ignored. + * @param string extra debug information. Defaults to the last + * query and native error code. + * @param mixed native error code, integer or string depending the + * backend + * + * @return object the PEAR_Error object + * + * @see PEAR_Error + */ + function &raiseError($code = DB_ERROR, $mode = null, $options = null, + $userinfo = null, $nativecode = null) + { + // The error is yet a DB error object + if (is_object($code)) { + // because we the static PEAR::raiseError, our global + // handler should be used if it is set + if ($mode === null && !empty($this->_default_error_mode)) { + $mode = $this->_default_error_mode; + $options = $this->_default_error_options; + } + $tmp = PEAR::raiseError($code, null, $mode, $options, + null, null, true); + return $tmp; + } + + if ($userinfo === null) { + $userinfo = $this->last_query; + } + + if ($nativecode) { + $userinfo .= ' [nativecode=' . trim($nativecode) . ']'; + } else { + $userinfo .= ' [DB Error: ' . DB::errorMessage($code) . ']'; + } + + $tmp = PEAR::raiseError(null, $code, $mode, $options, $userinfo, + 'DB_Error', true); + return $tmp; + } + + // }}} + // {{{ errorNative() + + /** + * Gets the DBMS' native error code produced by the last query + * + * @return mixed the DBMS' error code. A DB_Error object on failure. + */ + function errorNative() + { + return $this->raiseError(DB_ERROR_NOT_CAPABLE); + } + + // }}} + // {{{ errorCode() + + /** + * Maps native error codes to DB's portable ones + * + * Uses the $errorcode_map property defined in each driver. + * + * @param string|int $nativecode the error code returned by the DBMS + * + * @return int the portable DB error code. Return DB_ERROR if the + * current driver doesn't have a mapping for the + * $nativecode submitted. + */ + function errorCode($nativecode) + { + if (isset($this->errorcode_map[$nativecode])) { + return $this->errorcode_map[$nativecode]; + } + // Fall back to DB_ERROR if there was no mapping. + return DB_ERROR; + } + + // }}} + // {{{ errorMessage() + + /** + * Maps a DB error code to a textual message + * + * @param integer $dbcode the DB error code + * + * @return string the error message corresponding to the error code + * submitted. FALSE if the error code is unknown. + * + * @see DB::errorMessage() + */ + function errorMessage($dbcode) + { + return DB::errorMessage($this->errorcode_map[$dbcode]); + } + + // }}} + // {{{ tableInfo() + + /** + * Returns information about a table or a result set + * + * The format of the resulting array depends on which $mode + * you select. The sample output below is based on this query: + *
+     *    SELECT tblFoo.fldID, tblFoo.fldPhone, tblBar.fldId
+     *    FROM tblFoo
+     *    JOIN tblBar ON tblFoo.fldId = tblBar.fldId
+     * 
+ * + *
    + *
  • + * + * null (default) + *
    +     *   [0] => Array (
    +     *       [table] => tblFoo
    +     *       [name] => fldId
    +     *       [type] => int
    +     *       [len] => 11
    +     *       [flags] => primary_key not_null
    +     *   )
    +     *   [1] => Array (
    +     *       [table] => tblFoo
    +     *       [name] => fldPhone
    +     *       [type] => string
    +     *       [len] => 20
    +     *       [flags] =>
    +     *   )
    +     *   [2] => Array (
    +     *       [table] => tblBar
    +     *       [name] => fldId
    +     *       [type] => int
    +     *       [len] => 11
    +     *       [flags] => primary_key not_null
    +     *   )
    +     *   
    + * + *
  • + * + * DB_TABLEINFO_ORDER + * + *

    In addition to the information found in the default output, + * a notation of the number of columns is provided by the + * num_fields element while the order + * element provides an array with the column names as the keys and + * their location index number (corresponding to the keys in the + * the default output) as the values.

    + * + *

    If a result set has identical field names, the last one is + * used.

    + * + *
    +     *   [num_fields] => 3
    +     *   [order] => Array (
    +     *       [fldId] => 2
    +     *       [fldTrans] => 1
    +     *   )
    +     *   
    + * + *
  • + * + * DB_TABLEINFO_ORDERTABLE + * + *

    Similar to DB_TABLEINFO_ORDER but adds more + * dimensions to the array in which the table names are keys and + * the field names are sub-keys. This is helpful for queries that + * join tables which have identical field names.

    + * + *
    +     *   [num_fields] => 3
    +     *   [ordertable] => Array (
    +     *       [tblFoo] => Array (
    +     *           [fldId] => 0
    +     *           [fldPhone] => 1
    +     *       )
    +     *       [tblBar] => Array (
    +     *           [fldId] => 2
    +     *       )
    +     *   )
    +     *   
    + * + *
  • + *
+ * + * The flags element contains a space separated list + * of extra information about the field. This data is inconsistent + * between DBMS's due to the way each DBMS works. + * + primary_key + * + unique_key + * + multiple_key + * + not_null + * + * Most DBMS's only provide the table and flags + * elements if $result is a table name. The following DBMS's + * provide full information from queries: + * + fbsql + * + mysql + * + * If the 'portability' option has DB_PORTABILITY_LOWERCASE + * turned on, the names of tables and fields will be lowercased. + * + * @param object|string $result DB_result object from a query or a + * string containing the name of a table. + * While this also accepts a query result + * resource identifier, this behavior is + * deprecated. + * @param int $mode either unused or one of the tableInfo modes: + * DB_TABLEINFO_ORDERTABLE, + * DB_TABLEINFO_ORDER or + * DB_TABLEINFO_FULL (which does both). + * These are bitwise, so the first two can be + * combined using |. + * + * @return array an associative array with the information requested. + * A DB_Error object on failure. + * + * @see DB_common::setOption() + */ + function tableInfo($result, $mode = null) + { + /* + * If the DB_ class has a tableInfo() method, that one + * overrides this one. But, if the driver doesn't have one, + * this method runs and tells users about that fact. + */ + return $this->raiseError(DB_ERROR_NOT_CAPABLE); + } + + // }}} + // {{{ getTables() + + /** + * Lists the tables in the current database + * + * @return array the list of tables. A DB_Error object on failure. + * + * @deprecated Method deprecated some time before Release 1.2 + */ + function getTables() + { + return $this->getListOf('tables'); + } + + // }}} + // {{{ getListOf() + + /** + * Lists internal database information + * + * @param string $type type of information being sought. + * Common items being sought are: + * tables, databases, users, views, functions + * Each DBMS's has its own capabilities. + * + * @return array an array listing the items sought. + * A DB DB_Error object on failure. + */ + function getListOf($type) + { + $sql = $this->getSpecialQuery($type); + if ($sql === null) { + $this->last_query = ''; + return $this->raiseError(DB_ERROR_UNSUPPORTED); + } elseif (is_int($sql) || DB::isError($sql)) { + // Previous error + return $this->raiseError($sql); + } elseif (is_array($sql)) { + // Already the result + return $sql; + } + // Launch this query + return $this->getCol($sql); + } + + // }}} + // {{{ getSpecialQuery() + + /** + * Obtains the query string needed for listing a given type of objects + * + * @param string $type the kind of objects you want to retrieve + * + * @return string the SQL query string or null if the driver doesn't + * support the object type requested + * + * @access protected + * @see DB_common::getListOf() + */ + function getSpecialQuery($type) + { + return $this->raiseError(DB_ERROR_UNSUPPORTED); + } + + // }}} + // {{{ _rtrimArrayValues() + + /** + * Right-trims all strings in an array + * + * @param array $array the array to be trimmed (passed by reference) + * + * @return void + * + * @access protected + */ + function _rtrimArrayValues(&$array) + { + foreach ($array as $key => $value) { + if (is_string($value)) { + $array[$key] = rtrim($value); + } + } + } + + // }}} + // {{{ _convertNullArrayValuesToEmpty() + + /** + * Converts all null values in an array to empty strings + * + * @param array $array the array to be de-nullified (passed by reference) + * + * @return void + * + * @access protected + */ + function _convertNullArrayValuesToEmpty(&$array) + { + foreach ($array as $key => $value) { + if (is_null($value)) { + $array[$key] = ''; + } + } + } + + // }}} +} + +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * End: + */ + +?> diff --git a/events/phpFlickr/PEAR/DB/mysql.php b/events/phpFlickr/PEAR/DB/mysql.php new file mode 100644 index 0000000..3ae0adf --- /dev/null +++ b/events/phpFlickr/PEAR/DB/mysql.php @@ -0,0 +1,1034 @@ + + * @author Daniel Convissor + * @copyright 1997-2005 The PHP Group + * @license http://www.php.net/license/3_0.txt PHP License 3.0 + * @version CVS: $Id: mysql.php 32 2005-08-01 06:21:02Z dancoulter $ + * @link http://pear.php.net/package/DB + */ + +/** + * Obtain the DB_common class so it can be extended from + */ +require_once 'DB/common.php'; + +/** + * The methods PEAR DB uses to interact with PHP's mysql extension + * for interacting with MySQL databases + * + * These methods overload the ones declared in DB_common. + * + * @category Database + * @package DB + * @author Stig Bakken + * @author Daniel Convissor + * @copyright 1997-2005 The PHP Group + * @license http://www.php.net/license/3_0.txt PHP License 3.0 + * @version Release: @package_version@ + * @link http://pear.php.net/package/DB + */ +class DB_mysql extends DB_common +{ + // {{{ properties + + /** + * The DB driver type (mysql, oci8, odbc, etc.) + * @var string + */ + var $phptype = 'mysql'; + + /** + * The database syntax variant to be used (db2, access, etc.), if any + * @var string + */ + var $dbsyntax = 'mysql'; + + /** + * The capabilities of this DB implementation + * + * The 'new_link' element contains the PHP version that first provided + * new_link support for this DBMS. Contains false if it's unsupported. + * + * Meaning of the 'limit' element: + * + 'emulate' = emulate with fetch row by number + * + 'alter' = alter the query + * + false = skip rows + * + * @var array + */ + var $features = array( + 'limit' => 'alter', + 'new_link' => '4.2.0', + 'numrows' => true, + 'pconnect' => true, + 'prepare' => false, + 'ssl' => false, + 'transactions' => true, + ); + + /** + * A mapping of native error codes to DB error codes + * @var array + */ + var $errorcode_map = array( + 1004 => DB_ERROR_CANNOT_CREATE, + 1005 => DB_ERROR_CANNOT_CREATE, + 1006 => DB_ERROR_CANNOT_CREATE, + 1007 => DB_ERROR_ALREADY_EXISTS, + 1008 => DB_ERROR_CANNOT_DROP, + 1022 => DB_ERROR_ALREADY_EXISTS, + 1044 => DB_ERROR_ACCESS_VIOLATION, + 1046 => DB_ERROR_NODBSELECTED, + 1048 => DB_ERROR_CONSTRAINT, + 1049 => DB_ERROR_NOSUCHDB, + 1050 => DB_ERROR_ALREADY_EXISTS, + 1051 => DB_ERROR_NOSUCHTABLE, + 1054 => DB_ERROR_NOSUCHFIELD, + 1061 => DB_ERROR_ALREADY_EXISTS, + 1062 => DB_ERROR_ALREADY_EXISTS, + 1064 => DB_ERROR_SYNTAX, + 1091 => DB_ERROR_NOT_FOUND, + 1100 => DB_ERROR_NOT_LOCKED, + 1136 => DB_ERROR_VALUE_COUNT_ON_ROW, + 1142 => DB_ERROR_ACCESS_VIOLATION, + 1146 => DB_ERROR_NOSUCHTABLE, + 1216 => DB_ERROR_CONSTRAINT, + 1217 => DB_ERROR_CONSTRAINT, + ); + + /** + * The raw database connection created by PHP + * @var resource + */ + var $connection; + + /** + * The DSN information for connecting to a database + * @var array + */ + var $dsn = array(); + + + /** + * Should data manipulation queries be committed automatically? + * @var bool + * @access private + */ + var $autocommit = true; + + /** + * The quantity of transactions begun + * + * {@internal While this is private, it can't actually be designated + * private in PHP 5 because it is directly accessed in the test suite.}} + * + * @var integer + * @access private + */ + var $transaction_opcount = 0; + + /** + * The database specified in the DSN + * + * It's a fix to allow calls to different databases in the same script. + * + * @var string + * @access private + */ + var $_db = ''; + + + // }}} + // {{{ constructor + + /** + * This constructor calls $this->DB_common() + * + * @return void + */ + function DB_mysql() + { + $this->DB_common(); + } + + // }}} + // {{{ connect() + + /** + * Connect to the database server, log in and open the database + * + * Don't call this method directly. Use DB::connect() instead. + * + * PEAR DB's mysql driver supports the following extra DSN options: + * + new_link If set to true, causes subsequent calls to connect() + * to return a new connection link instead of the + * existing one. WARNING: this is not portable to + * other DBMS's. Available since PEAR DB 1.7.0. + * + client_flags Any combination of MYSQL_CLIENT_* constants. + * Only used if PHP is at version 4.3.0 or greater. + * Available since PEAR DB 1.7.0. + * + * @param array $dsn the data source name + * @param bool $persistent should the connection be persistent? + * + * @return int DB_OK on success. A DB_Error object on failure. + */ + function connect($dsn, $persistent = false) + { + if (!PEAR::loadExtension('mysql')) { + return $this->raiseError(DB_ERROR_EXTENSION_NOT_FOUND); + } + + $this->dsn = $dsn; + if ($dsn['dbsyntax']) { + $this->dbsyntax = $dsn['dbsyntax']; + } + + $params = array(); + if ($dsn['protocol'] && $dsn['protocol'] == 'unix') { + $params[0] = ':' . $dsn['socket']; + } else { + $params[0] = $dsn['hostspec'] ? $dsn['hostspec'] + : 'localhost'; + if ($dsn['port']) { + $params[0] .= ':' . $dsn['port']; + } + } + $params[] = $dsn['username'] ? $dsn['username'] : null; + $params[] = $dsn['password'] ? $dsn['password'] : null; + + if (!$persistent) { + if (isset($dsn['new_link']) + && ($dsn['new_link'] == 'true' || $dsn['new_link'] === true)) + { + $params[] = true; + } else { + $params[] = false; + } + } + if (version_compare(phpversion(), '4.3.0', '>=')) { + $params[] = isset($dsn['client_flags']) + ? $dsn['client_flags'] : null; + } + + $connect_function = $persistent ? 'mysql_pconnect' : 'mysql_connect'; + + $ini = ini_get('track_errors'); + $php_errormsg = ''; + if ($ini) { + $this->connection = @call_user_func_array($connect_function, + $params); + } else { + ini_set('track_errors', 1); + $this->connection = @call_user_func_array($connect_function, + $params); + ini_set('track_errors', $ini); + } + + if (!$this->connection) { + if (($err = @mysql_error()) != '') { + return $this->raiseError(DB_ERROR_CONNECT_FAILED, + null, null, null, + $err); + } else { + return $this->raiseError(DB_ERROR_CONNECT_FAILED, + null, null, null, + $php_errormsg); + } + } + + if ($dsn['database']) { + if (!@mysql_select_db($dsn['database'], $this->connection)) { + return $this->mysqlRaiseError(); + } + $this->_db = $dsn['database']; + } + + return DB_OK; + } + + // }}} + // {{{ disconnect() + + /** + * Disconnects from the database server + * + * @return bool TRUE on success, FALSE on failure + */ + function disconnect() + { + $ret = @mysql_close($this->connection); + $this->connection = null; + return $ret; + } + + // }}} + // {{{ simpleQuery() + + /** + * Sends a query to the database server + * + * Generally uses mysql_query(). If you want to use + * mysql_unbuffered_query() set the "result_buffering" option to 0 using + * setOptions(). This option was added in Release 1.7.0. + * + * @param string the SQL query string + * + * @return mixed + a PHP result resrouce for successful SELECT queries + * + the DB_OK constant for other successful queries + * + a DB_Error object on failure + */ + function simpleQuery($query) + { + $ismanip = DB::isManip($query); + $this->last_query = $query; + $query = $this->modifyQuery($query); + if ($this->_db) { + if (!@mysql_select_db($this->_db, $this->connection)) { + return $this->mysqlRaiseError(DB_ERROR_NODBSELECTED); + } + } + if (!$this->autocommit && $ismanip) { + if ($this->transaction_opcount == 0) { + $result = @mysql_query('SET AUTOCOMMIT=0', $this->connection); + $result = @mysql_query('BEGIN', $this->connection); + if (!$result) { + return $this->mysqlRaiseError(); + } + } + $this->transaction_opcount++; + } + if (!$this->options['result_buffering']) { + $result = @mysql_unbuffered_query($query, $this->connection); + } else { + $result = @mysql_query($query, $this->connection); + } + if (!$result) { + return $this->mysqlRaiseError(); + } + if (is_resource($result)) { + return $result; + } + return DB_OK; + } + + // }}} + // {{{ nextResult() + + /** + * Move the internal mysql result pointer to the next available result + * + * This method has not been implemented yet. + * + * @param a valid sql result resource + * + * @return false + */ + function nextResult($result) + { + return false; + } + + // }}} + // {{{ fetchInto() + + /** + * Places a row from the result set into the given array + * + * Formating of the array and the data therein are configurable. + * See DB_result::fetchInto() for more information. + * + * This method is not meant to be called directly. Use + * DB_result::fetchInto() instead. It can't be declared "protected" + * because DB_result is a separate object. + * + * @param resource $result the query result resource + * @param array $arr the referenced array to put the data in + * @param int $fetchmode how the resulting array should be indexed + * @param int $rownum the row number to fetch (0 = first row) + * + * @return mixed DB_OK on success, NULL when the end of a result set is + * reached or on failure + * + * @see DB_result::fetchInto() + */ + function fetchInto($result, &$arr, $fetchmode, $rownum = null) + { + if ($rownum !== null) { + if (!@mysql_data_seek($result, $rownum)) { + return null; + } + } + if ($fetchmode & DB_FETCHMODE_ASSOC) { + $arr = @mysql_fetch_array($result, MYSQL_ASSOC); + if ($this->options['portability'] & DB_PORTABILITY_LOWERCASE && $arr) { + $arr = array_change_key_case($arr, CASE_LOWER); + } + } else { + $arr = @mysql_fetch_row($result); + } + if (!$arr) { + return null; + } + if ($this->options['portability'] & DB_PORTABILITY_RTRIM) { + /* + * Even though this DBMS already trims output, we do this because + * a field might have intentional whitespace at the end that + * gets removed by DB_PORTABILITY_RTRIM under another driver. + */ + $this->_rtrimArrayValues($arr); + } + if ($this->options['portability'] & DB_PORTABILITY_NULL_TO_EMPTY) { + $this->_convertNullArrayValuesToEmpty($arr); + } + return DB_OK; + } + + // }}} + // {{{ freeResult() + + /** + * Deletes the result set and frees the memory occupied by the result set + * + * This method is not meant to be called directly. Use + * DB_result::free() instead. It can't be declared "protected" + * because DB_result is a separate object. + * + * @param resource $result PHP's query result resource + * + * @return bool TRUE on success, FALSE if $result is invalid + * + * @see DB_result::free() + */ + function freeResult($result) + { + return @mysql_free_result($result); + } + + // }}} + // {{{ numCols() + + /** + * Gets the number of columns in a result set + * + * This method is not meant to be called directly. Use + * DB_result::numCols() instead. It can't be declared "protected" + * because DB_result is a separate object. + * + * @param resource $result PHP's query result resource + * + * @return int the number of columns. A DB_Error object on failure. + * + * @see DB_result::numCols() + */ + function numCols($result) + { + $cols = @mysql_num_fields($result); + if (!$cols) { + return $this->mysqlRaiseError(); + } + return $cols; + } + + // }}} + // {{{ numRows() + + /** + * Gets the number of rows in a result set + * + * This method is not meant to be called directly. Use + * DB_result::numRows() instead. It can't be declared "protected" + * because DB_result is a separate object. + * + * @param resource $result PHP's query result resource + * + * @return int the number of rows. A DB_Error object on failure. + * + * @see DB_result::numRows() + */ + function numRows($result) + { + $rows = @mysql_num_rows($result); + if ($rows === null) { + return $this->mysqlRaiseError(); + } + return $rows; + } + + // }}} + // {{{ autoCommit() + + /** + * Enables or disables automatic commits + * + * @param bool $onoff true turns it on, false turns it off + * + * @return int DB_OK on success. A DB_Error object if the driver + * doesn't support auto-committing transactions. + */ + function autoCommit($onoff = false) + { + // XXX if $this->transaction_opcount > 0, we should probably + // issue a warning here. + $this->autocommit = $onoff ? true : false; + return DB_OK; + } + + // }}} + // {{{ commit() + + /** + * Commits the current transaction + * + * @return int DB_OK on success. A DB_Error object on failure. + */ + function commit() + { + if ($this->transaction_opcount > 0) { + if ($this->_db) { + if (!@mysql_select_db($this->_db, $this->connection)) { + return $this->mysqlRaiseError(DB_ERROR_NODBSELECTED); + } + } + $result = @mysql_query('COMMIT', $this->connection); + $result = @mysql_query('SET AUTOCOMMIT=1', $this->connection); + $this->transaction_opcount = 0; + if (!$result) { + return $this->mysqlRaiseError(); + } + } + return DB_OK; + } + + // }}} + // {{{ rollback() + + /** + * Reverts the current transaction + * + * @return int DB_OK on success. A DB_Error object on failure. + */ + function rollback() + { + if ($this->transaction_opcount > 0) { + if ($this->_db) { + if (!@mysql_select_db($this->_db, $this->connection)) { + return $this->mysqlRaiseError(DB_ERROR_NODBSELECTED); + } + } + $result = @mysql_query('ROLLBACK', $this->connection); + $result = @mysql_query('SET AUTOCOMMIT=1', $this->connection); + $this->transaction_opcount = 0; + if (!$result) { + return $this->mysqlRaiseError(); + } + } + return DB_OK; + } + + // }}} + // {{{ affectedRows() + + /** + * Determines the number of rows affected by a data maniuplation query + * + * 0 is returned for queries that don't manipulate data. + * + * @return int the number of rows. A DB_Error object on failure. + */ + function affectedRows() + { + if (DB::isManip($this->last_query)) { + return @mysql_affected_rows($this->connection); + } else { + return 0; + } + } + + // }}} + // {{{ nextId() + + /** + * Returns the next free id in a sequence + * + * @param string $seq_name name of the sequence + * @param boolean $ondemand when true, the seqence is automatically + * created if it does not exist + * + * @return int the next id number in the sequence. + * A DB_Error object on failure. + * + * @see DB_common::nextID(), DB_common::getSequenceName(), + * DB_mysql::createSequence(), DB_mysql::dropSequence() + */ + function nextId($seq_name, $ondemand = true) + { + $seqname = $this->getSequenceName($seq_name); + do { + $repeat = 0; + $this->pushErrorHandling(PEAR_ERROR_RETURN); + $result = $this->query("UPDATE ${seqname} ". + 'SET id=LAST_INSERT_ID(id+1)'); + $this->popErrorHandling(); + if ($result === DB_OK) { + // COMMON CASE + $id = @mysql_insert_id($this->connection); + if ($id != 0) { + return $id; + } + // EMPTY SEQ TABLE + // Sequence table must be empty for some reason, so fill + // it and return 1 and obtain a user-level lock + $result = $this->getOne("SELECT GET_LOCK('${seqname}_lock',10)"); + if (DB::isError($result)) { + return $this->raiseError($result); + } + if ($result == 0) { + // Failed to get the lock + return $this->mysqlRaiseError(DB_ERROR_NOT_LOCKED); + } + + // add the default value + $result = $this->query("REPLACE INTO ${seqname} (id) VALUES (0)"); + if (DB::isError($result)) { + return $this->raiseError($result); + } + + // Release the lock + $result = $this->getOne('SELECT RELEASE_LOCK(' + . "'${seqname}_lock')"); + if (DB::isError($result)) { + return $this->raiseError($result); + } + // We know what the result will be, so no need to try again + return 1; + + } elseif ($ondemand && DB::isError($result) && + $result->getCode() == DB_ERROR_NOSUCHTABLE) + { + // ONDEMAND TABLE CREATION + $result = $this->createSequence($seq_name); + if (DB::isError($result)) { + return $this->raiseError($result); + } else { + $repeat = 1; + } + + } elseif (DB::isError($result) && + $result->getCode() == DB_ERROR_ALREADY_EXISTS) + { + // BACKWARDS COMPAT + // see _BCsequence() comment + $result = $this->_BCsequence($seqname); + if (DB::isError($result)) { + return $this->raiseError($result); + } + $repeat = 1; + } + } while ($repeat); + + return $this->raiseError($result); + } + + // }}} + // {{{ createSequence() + + /** + * Creates a new sequence + * + * @param string $seq_name name of the new sequence + * + * @return int DB_OK on success. A DB_Error object on failure. + * + * @see DB_common::createSequence(), DB_common::getSequenceName(), + * DB_mysql::nextID(), DB_mysql::dropSequence() + */ + function createSequence($seq_name) + { + $seqname = $this->getSequenceName($seq_name); + $res = $this->query('CREATE TABLE ' . $seqname + . ' (id INTEGER UNSIGNED AUTO_INCREMENT NOT NULL,' + . ' PRIMARY KEY(id))'); + if (DB::isError($res)) { + return $res; + } + // insert yields value 1, nextId call will generate ID 2 + $res = $this->query("INSERT INTO ${seqname} (id) VALUES (0)"); + if (DB::isError($res)) { + return $res; + } + // so reset to zero + return $this->query("UPDATE ${seqname} SET id = 0"); + } + + // }}} + // {{{ dropSequence() + + /** + * Deletes a sequence + * + * @param string $seq_name name of the sequence to be deleted + * + * @return int DB_OK on success. A DB_Error object on failure. + * + * @see DB_common::dropSequence(), DB_common::getSequenceName(), + * DB_mysql::nextID(), DB_mysql::createSequence() + */ + function dropSequence($seq_name) + { + return $this->query('DROP TABLE ' . $this->getSequenceName($seq_name)); + } + + // }}} + // {{{ _BCsequence() + + /** + * Backwards compatibility with old sequence emulation implementation + * (clean up the dupes) + * + * @param string $seqname the sequence name to clean up + * + * @return bool true on success. A DB_Error object on failure. + * + * @access private + */ + function _BCsequence($seqname) + { + // Obtain a user-level lock... this will release any previous + // application locks, but unlike LOCK TABLES, it does not abort + // the current transaction and is much less frequently used. + $result = $this->getOne("SELECT GET_LOCK('${seqname}_lock',10)"); + if (DB::isError($result)) { + return $result; + } + if ($result == 0) { + // Failed to get the lock, can't do the conversion, bail + // with a DB_ERROR_NOT_LOCKED error + return $this->mysqlRaiseError(DB_ERROR_NOT_LOCKED); + } + + $highest_id = $this->getOne("SELECT MAX(id) FROM ${seqname}"); + if (DB::isError($highest_id)) { + return $highest_id; + } + // This should kill all rows except the highest + // We should probably do something if $highest_id isn't + // numeric, but I'm at a loss as how to handle that... + $result = $this->query('DELETE FROM ' . $seqname + . " WHERE id <> $highest_id"); + if (DB::isError($result)) { + return $result; + } + + // If another thread has been waiting for this lock, + // it will go thru the above procedure, but will have no + // real effect + $result = $this->getOne("SELECT RELEASE_LOCK('${seqname}_lock')"); + if (DB::isError($result)) { + return $result; + } + return true; + } + + // }}} + // {{{ quoteIdentifier() + + /** + * Quotes a string so it can be safely used as a table or column name + * + * MySQL can't handle the backtick character (`) in + * table or column names. + * + * @param string $str identifier name to be quoted + * + * @return string quoted identifier string + * + * @see DB_common::quoteIdentifier() + * @since Method available since Release 1.6.0 + */ + function quoteIdentifier($str) + { + return '`' . $str . '`'; + } + + // }}} + // {{{ quote() + + /** + * @deprecated Deprecated in release 1.6.0 + */ + function quote($str) + { + return $this->quoteSmart($str); + } + + // }}} + // {{{ escapeSimple() + + /** + * Escapes a string according to the current DBMS's standards + * + * @param string $str the string to be escaped + * + * @return string the escaped string + * + * @see DB_common::quoteSmart() + * @since Method available since Release 1.6.0 + */ + function escapeSimple($str) + { + if (function_exists('mysql_real_escape_string')) { + return @mysql_real_escape_string($str, $this->connection); + } else { + return @mysql_escape_string($str); + } + } + + // }}} + // {{{ modifyQuery() + + /** + * Changes a query string for various DBMS specific reasons + * + * This little hack lets you know how many rows were deleted + * when running a "DELETE FROM table" query. Only implemented + * if the DB_PORTABILITY_DELETE_COUNT portability option is on. + * + * @param string $query the query string to modify + * + * @return string the modified query string + * + * @access protected + * @see DB_common::setOption() + */ + function modifyQuery($query) + { + if ($this->options['portability'] & DB_PORTABILITY_DELETE_COUNT) { + // "DELETE FROM table" gives 0 affected rows in MySQL. + // This little hack lets you know how many rows were deleted. + if (preg_match('/^\s*DELETE\s+FROM\s+(\S+)\s*$/i', $query)) { + $query = preg_replace('/^\s*DELETE\s+FROM\s+(\S+)\s*$/', + 'DELETE FROM \1 WHERE 1=1', $query); + } + } + return $query; + } + + // }}} + // {{{ modifyLimitQuery() + + /** + * Adds LIMIT clauses to a query string according to current DBMS standards + * + * @param string $query the query to modify + * @param int $from the row to start to fetching (0 = the first row) + * @param int $count the numbers of rows to fetch + * @param mixed $params array, string or numeric data to be used in + * execution of the statement. Quantity of items + * passed must match quantity of placeholders in + * query: meaning 1 placeholder for non-array + * parameters or 1 placeholder per array element. + * + * @return string the query string with LIMIT clauses added + * + * @access protected + */ + function modifyLimitQuery($query, $from, $count, $params = array()) + { + if (DB::isManip($query)) { + return $query . " LIMIT $count"; + } else { + return $query . " LIMIT $from, $count"; + } + } + + // }}} + // {{{ mysqlRaiseError() + + /** + * Produces a DB_Error object regarding the current problem + * + * @param int $errno if the error is being manually raised pass a + * DB_ERROR* constant here. If this isn't passed + * the error information gathered from the DBMS. + * + * @return object the DB_Error object + * + * @see DB_common::raiseError(), + * DB_mysql::errorNative(), DB_common::errorCode() + */ + function mysqlRaiseError($errno = null) + { + if ($errno === null) { + if ($this->options['portability'] & DB_PORTABILITY_ERRORS) { + $this->errorcode_map[1022] = DB_ERROR_CONSTRAINT; + $this->errorcode_map[1048] = DB_ERROR_CONSTRAINT_NOT_NULL; + $this->errorcode_map[1062] = DB_ERROR_CONSTRAINT; + } else { + // Doing this in case mode changes during runtime. + $this->errorcode_map[1022] = DB_ERROR_ALREADY_EXISTS; + $this->errorcode_map[1048] = DB_ERROR_CONSTRAINT; + $this->errorcode_map[1062] = DB_ERROR_ALREADY_EXISTS; + } + $errno = $this->errorCode(mysql_errno($this->connection)); + } + return $this->raiseError($errno, null, null, null, + @mysql_errno($this->connection) . ' ** ' . + @mysql_error($this->connection)); + } + + // }}} + // {{{ errorNative() + + /** + * Gets the DBMS' native error code produced by the last query + * + * @return int the DBMS' error code + */ + function errorNative() + { + return @mysql_errno($this->connection); + } + + // }}} + // {{{ tableInfo() + + /** + * Returns information about a table or a result set + * + * @param object|string $result DB_result object from a query or a + * string containing the name of a table. + * While this also accepts a query result + * resource identifier, this behavior is + * deprecated. + * @param int $mode a valid tableInfo mode + * + * @return array an associative array with the information requested. + * A DB_Error object on failure. + * + * @see DB_common::tableInfo() + */ + function tableInfo($result, $mode = null) + { + if (is_string($result)) { + /* + * Probably received a table name. + * Create a result resource identifier. + */ + $id = @mysql_list_fields($this->dsn['database'], + $result, $this->connection); + $got_string = true; + } elseif (isset($result->result)) { + /* + * Probably received a result object. + * Extract the result resource identifier. + */ + $id = $result->result; + $got_string = false; + } else { + /* + * Probably received a result resource identifier. + * Copy it. + * Deprecated. Here for compatibility only. + */ + $id = $result; + $got_string = false; + } + + if (!is_resource($id)) { + return $this->mysqlRaiseError(DB_ERROR_NEED_MORE_DATA); + } + + if ($this->options['portability'] & DB_PORTABILITY_LOWERCASE) { + $case_func = 'strtolower'; + } else { + $case_func = 'strval'; + } + + $count = @mysql_num_fields($id); + $res = array(); + + if ($mode) { + $res['num_fields'] = $count; + } + + for ($i = 0; $i < $count; $i++) { + $res[$i] = array( + 'table' => $case_func(@mysql_field_table($id, $i)), + 'name' => $case_func(@mysql_field_name($id, $i)), + 'type' => @mysql_field_type($id, $i), + 'len' => @mysql_field_len($id, $i), + 'flags' => @mysql_field_flags($id, $i), + ); + if ($mode & DB_TABLEINFO_ORDER) { + $res['order'][$res[$i]['name']] = $i; + } + if ($mode & DB_TABLEINFO_ORDERTABLE) { + $res['ordertable'][$res[$i]['table']][$res[$i]['name']] = $i; + } + } + + // free the result only if we were called on a table + if ($got_string) { + @mysql_free_result($id); + } + return $res; + } + + // }}} + // {{{ getSpecialQuery() + + /** + * Obtains the query string needed for listing a given type of objects + * + * @param string $type the kind of objects you want to retrieve + * + * @return string the SQL query string or null if the driver doesn't + * support the object type requested + * + * @access protected + * @see DB_common::getListOf() + */ + function getSpecialQuery($type) + { + switch ($type) { + case 'tables': + return 'SHOW TABLES'; + case 'users': + return 'SELECT DISTINCT User FROM mysql.user'; + case 'databases': + return 'SHOW DATABASES'; + default: + return null; + } + } + + // }}} + +} + +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * End: + */ + +?> diff --git a/events/phpFlickr/PEAR/DB/pgsql.php b/events/phpFlickr/PEAR/DB/pgsql.php new file mode 100644 index 0000000..1e58f48 --- /dev/null +++ b/events/phpFlickr/PEAR/DB/pgsql.php @@ -0,0 +1,1097 @@ + + * @author Stig Bakken + * @author Daniel Convissor + * @copyright 1997-2005 The PHP Group + * @license http://www.php.net/license/3_0.txt PHP License 3.0 + * @version CVS: $Id: pgsql.php 32 2005-08-01 06:21:02Z dancoulter $ + * @link http://pear.php.net/package/DB + */ + +/** + * Obtain the DB_common class so it can be extended from + */ +require_once 'DB/common.php'; + +/** + * The methods PEAR DB uses to interact with PHP's pgsql extension + * for interacting with PostgreSQL databases + * + * These methods overload the ones declared in DB_common. + * + * @category Database + * @package DB + * @author Rui Hirokawa + * @author Stig Bakken + * @author Daniel Convissor + * @copyright 1997-2005 The PHP Group + * @license http://www.php.net/license/3_0.txt PHP License 3.0 + * @version Release: @package_version@ + * @link http://pear.php.net/package/DB + */ +class DB_pgsql extends DB_common +{ + // {{{ properties + + /** + * The DB driver type (mysql, oci8, odbc, etc.) + * @var string + */ + var $phptype = 'pgsql'; + + /** + * The database syntax variant to be used (db2, access, etc.), if any + * @var string + */ + var $dbsyntax = 'pgsql'; + + /** + * The capabilities of this DB implementation + * + * The 'new_link' element contains the PHP version that first provided + * new_link support for this DBMS. Contains false if it's unsupported. + * + * Meaning of the 'limit' element: + * + 'emulate' = emulate with fetch row by number + * + 'alter' = alter the query + * + false = skip rows + * + * @var array + */ + var $features = array( + 'limit' => 'alter', + 'new_link' => '4.3.0', + 'numrows' => true, + 'pconnect' => true, + 'prepare' => false, + 'ssl' => true, + 'transactions' => true, + ); + + /** + * A mapping of native error codes to DB error codes + * @var array + */ + var $errorcode_map = array( + ); + + /** + * The raw database connection created by PHP + * @var resource + */ + var $connection; + + /** + * The DSN information for connecting to a database + * @var array + */ + var $dsn = array(); + + + /** + * Should data manipulation queries be committed automatically? + * @var bool + * @access private + */ + var $autocommit = true; + + /** + * The quantity of transactions begun + * + * {@internal While this is private, it can't actually be designated + * private in PHP 5 because it is directly accessed in the test suite.}} + * + * @var integer + * @access private + */ + var $transaction_opcount = 0; + + /** + * The number of rows affected by a data manipulation query + * @var integer + */ + var $affected = 0; + + /** + * The current row being looked at in fetchInto() + * @var array + * @access private + */ + var $row = array(); + + /** + * The number of rows in a given result set + * @var array + * @access private + */ + var $_num_rows = array(); + + + // }}} + // {{{ constructor + + /** + * This constructor calls $this->DB_common() + * + * @return void + */ + function DB_pgsql() + { + $this->DB_common(); + } + + // }}} + // {{{ connect() + + /** + * Connect to the database server, log in and open the database + * + * Don't call this method directly. Use DB::connect() instead. + * + * PEAR DB's pgsql driver supports the following extra DSN options: + * + connect_timeout How many seconds to wait for a connection to + * be established. Available since PEAR DB 1.7.0. + * + new_link If set to true, causes subsequent calls to + * connect() to return a new connection link + * instead of the existing one. WARNING: this is + * not portable to other DBMS's. Available only + * if PHP is >= 4.3.0 and PEAR DB is >= 1.7.0. + * + options Command line options to be sent to the server. + * Available since PEAR DB 1.6.4. + * + service Specifies a service name in pg_service.conf that + * holds additional connection parameters. + * Available since PEAR DB 1.7.0. + * + sslmode How should SSL be used when connecting? Values: + * disable, allow, prefer or require. + * Available since PEAR DB 1.7.0. + * + tty This was used to specify where to send server + * debug output. Available since PEAR DB 1.6.4. + * + * Example of connecting to a new link via a socket: + * + * require_once 'DB.php'; + * + * $dsn = 'pgsql://user:pass@unix(/tmp)/dbname?new_link=true'; + * $options = array( + * 'portability' => DB_PORTABILITY_ALL, + * ); + * + * $db =& DB::connect($dsn, $options); + * if (PEAR::isError($db)) { + * die($db->getMessage()); + * } + * + * + * @param array $dsn the data source name + * @param bool $persistent should the connection be persistent? + * + * @return int DB_OK on success. A DB_Error object on failure. + * + * @link http://www.postgresql.org/docs/current/static/libpq.html#LIBPQ-CONNECT + */ + function connect($dsn, $persistent = false) + { + if (!PEAR::loadExtension('pgsql')) { + return $this->raiseError(DB_ERROR_EXTENSION_NOT_FOUND); + } + + $this->dsn = $dsn; + if ($dsn['dbsyntax']) { + $this->dbsyntax = $dsn['dbsyntax']; + } + + $protocol = $dsn['protocol'] ? $dsn['protocol'] : 'tcp'; + + $params = array(''); + if ($protocol == 'tcp') { + if ($dsn['hostspec']) { + $params[0] .= 'host=' . $dsn['hostspec']; + } + if ($dsn['port']) { + $params[0] .= ' port=' . $dsn['port']; + } + } elseif ($protocol == 'unix') { + // Allow for pg socket in non-standard locations. + if ($dsn['socket']) { + $params[0] .= 'host=' . $dsn['socket']; + } + if ($dsn['port']) { + $params[0] .= ' port=' . $dsn['port']; + } + } + if ($dsn['database']) { + $params[0] .= ' dbname=\'' . addslashes($dsn['database']) . '\''; + } + if ($dsn['username']) { + $params[0] .= ' user=\'' . addslashes($dsn['username']) . '\''; + } + if ($dsn['password']) { + $params[0] .= ' password=\'' . addslashes($dsn['password']) . '\''; + } + if (!empty($dsn['options'])) { + $params[0] .= ' options=' . $dsn['options']; + } + if (!empty($dsn['tty'])) { + $params[0] .= ' tty=' . $dsn['tty']; + } + if (!empty($dsn['connect_timeout'])) { + $params[0] .= ' connect_timeout=' . $dsn['connect_timeout']; + } + if (!empty($dsn['sslmode'])) { + $params[0] .= ' sslmode=' . $dsn['sslmode']; + } + if (!empty($dsn['service'])) { + $params[0] .= ' service=' . $dsn['service']; + } + + if (isset($dsn['new_link']) + && ($dsn['new_link'] == 'true' || $dsn['new_link'] === true)) + { + if (version_compare(phpversion(), '4.3.0', '>=')) { + $params[] = PGSQL_CONNECT_FORCE_NEW; + } + } + + $connect_function = $persistent ? 'pg_pconnect' : 'pg_connect'; + + $ini = ini_get('track_errors'); + $php_errormsg = ''; + if ($ini) { + $this->connection = @call_user_func_array($connect_function, + $params); + } else { + ini_set('track_errors', 1); + $this->connection = @call_user_func_array($connect_function, + $params); + ini_set('track_errors', $ini); + } + + if (!$this->connection) { + return $this->raiseError(DB_ERROR_CONNECT_FAILED, + null, null, null, + $php_errormsg); + } + return DB_OK; + } + + // }}} + // {{{ disconnect() + + /** + * Disconnects from the database server + * + * @return bool TRUE on success, FALSE on failure + */ + function disconnect() + { + $ret = @pg_close($this->connection); + $this->connection = null; + return $ret; + } + + // }}} + // {{{ simpleQuery() + + /** + * Sends a query to the database server + * + * @param string the SQL query string + * + * @return mixed + a PHP result resrouce for successful SELECT queries + * + the DB_OK constant for other successful queries + * + a DB_Error object on failure + */ + function simpleQuery($query) + { + $ismanip = DB::isManip($query); + $this->last_query = $query; + $query = $this->modifyQuery($query); + if (!$this->autocommit && $ismanip) { + if ($this->transaction_opcount == 0) { + $result = @pg_exec($this->connection, 'begin;'); + if (!$result) { + return $this->pgsqlRaiseError(); + } + } + $this->transaction_opcount++; + } + $result = @pg_exec($this->connection, $query); + if (!$result) { + return $this->pgsqlRaiseError(); + } + // Determine which queries that should return data, and which + // should return an error code only. + if ($ismanip) { + $this->affected = @pg_affected_rows($result); + return DB_OK; + } elseif (preg_match('/^\s*\(*\s*(SELECT|EXPLAIN|SHOW)\s/si', $query)) { + /* PostgreSQL commands: + ABORT, ALTER, BEGIN, CLOSE, CLUSTER, COMMIT, COPY, + CREATE, DECLARE, DELETE, DROP TABLE, EXPLAIN, FETCH, + GRANT, INSERT, LISTEN, LOAD, LOCK, MOVE, NOTIFY, RESET, + REVOKE, ROLLBACK, SELECT, SELECT INTO, SET, SHOW, + UNLISTEN, UPDATE, VACUUM + */ + $this->row[(int)$result] = 0; // reset the row counter. + $numrows = $this->numRows($result); + if (is_object($numrows)) { + return $numrows; + } + $this->_num_rows[(int)$result] = $numrows; + $this->affected = 0; + return $result; + } else { + $this->affected = 0; + return DB_OK; + } + } + + // }}} + // {{{ nextResult() + + /** + * Move the internal pgsql result pointer to the next available result + * + * @param a valid fbsql result resource + * + * @access public + * + * @return true if a result is available otherwise return false + */ + function nextResult($result) + { + return false; + } + + // }}} + // {{{ fetchInto() + + /** + * Places a row from the result set into the given array + * + * Formating of the array and the data therein are configurable. + * See DB_result::fetchInto() for more information. + * + * This method is not meant to be called directly. Use + * DB_result::fetchInto() instead. It can't be declared "protected" + * because DB_result is a separate object. + * + * @param resource $result the query result resource + * @param array $arr the referenced array to put the data in + * @param int $fetchmode how the resulting array should be indexed + * @param int $rownum the row number to fetch (0 = first row) + * + * @return mixed DB_OK on success, NULL when the end of a result set is + * reached or on failure + * + * @see DB_result::fetchInto() + */ + function fetchInto($result, &$arr, $fetchmode, $rownum = null) + { + $result_int = (int)$result; + $rownum = ($rownum !== null) ? $rownum : $this->row[$result_int]; + if ($rownum >= $this->_num_rows[$result_int]) { + return null; + } + if ($fetchmode & DB_FETCHMODE_ASSOC) { + $arr = @pg_fetch_array($result, $rownum, PGSQL_ASSOC); + if ($this->options['portability'] & DB_PORTABILITY_LOWERCASE && $arr) { + $arr = array_change_key_case($arr, CASE_LOWER); + } + } else { + $arr = @pg_fetch_row($result, $rownum); + } + if (!$arr) { + return null; + } + if ($this->options['portability'] & DB_PORTABILITY_RTRIM) { + $this->_rtrimArrayValues($arr); + } + if ($this->options['portability'] & DB_PORTABILITY_NULL_TO_EMPTY) { + $this->_convertNullArrayValuesToEmpty($arr); + } + $this->row[$result_int] = ++$rownum; + return DB_OK; + } + + // }}} + // {{{ freeResult() + + /** + * Deletes the result set and frees the memory occupied by the result set + * + * This method is not meant to be called directly. Use + * DB_result::free() instead. It can't be declared "protected" + * because DB_result is a separate object. + * + * @param resource $result PHP's query result resource + * + * @return bool TRUE on success, FALSE if $result is invalid + * + * @see DB_result::free() + */ + function freeResult($result) + { + if (is_resource($result)) { + unset($this->row[(int)$result]); + unset($this->_num_rows[(int)$result]); + $this->affected = 0; + return @pg_freeresult($result); + } + return false; + } + + // }}} + // {{{ quote() + + /** + * @deprecated Deprecated in release 1.6.0 + * @internal + */ + function quote($str) + { + return $this->quoteSmart($str); + } + + // }}} + // {{{ quoteSmart() + + /** + * Formats input so it can be safely used in a query + * + * @param mixed $in the data to be formatted + * + * @return mixed the formatted data. The format depends on the input's + * PHP type: + * + null = the string NULL + * + boolean = string TRUE or FALSE + * + integer or double = the unquoted number + * + other (including strings and numeric strings) = + * the data escaped according to MySQL's settings + * then encapsulated between single quotes + * + * @see DB_common::quoteSmart() + * @since Method available since Release 1.6.0 + */ + function quoteSmart($in) + { + if (is_int($in) || is_double($in)) { + return $in; + } elseif (is_bool($in)) { + return $in ? 'TRUE' : 'FALSE'; + } elseif (is_null($in)) { + return 'NULL'; + } else { + return "'" . $this->escapeSimple($in) . "'"; + } + } + + // }}} + // {{{ escapeSimple() + + /** + * Escapes a string according to the current DBMS's standards + * + * {@internal PostgreSQL treats a backslash as an escape character, + * so they are escaped as well. + * + * Not using pg_escape_string() yet because it requires PostgreSQL + * to be at version 7.2 or greater.}} + * + * @param string $str the string to be escaped + * + * @return string the escaped string + * + * @see DB_common::quoteSmart() + * @since Method available since Release 1.6.0 + */ + function escapeSimple($str) + { + return str_replace("'", "''", str_replace('\\', '\\\\', $str)); + } + + // }}} + // {{{ numCols() + + /** + * Gets the number of columns in a result set + * + * This method is not meant to be called directly. Use + * DB_result::numCols() instead. It can't be declared "protected" + * because DB_result is a separate object. + * + * @param resource $result PHP's query result resource + * + * @return int the number of columns. A DB_Error object on failure. + * + * @see DB_result::numCols() + */ + function numCols($result) + { + $cols = @pg_numfields($result); + if (!$cols) { + return $this->pgsqlRaiseError(); + } + return $cols; + } + + // }}} + // {{{ numRows() + + /** + * Gets the number of rows in a result set + * + * This method is not meant to be called directly. Use + * DB_result::numRows() instead. It can't be declared "protected" + * because DB_result is a separate object. + * + * @param resource $result PHP's query result resource + * + * @return int the number of rows. A DB_Error object on failure. + * + * @see DB_result::numRows() + */ + function numRows($result) + { + $rows = @pg_numrows($result); + if ($rows === null) { + return $this->pgsqlRaiseError(); + } + return $rows; + } + + // }}} + // {{{ autoCommit() + + /** + * Enables or disables automatic commits + * + * @param bool $onoff true turns it on, false turns it off + * + * @return int DB_OK on success. A DB_Error object if the driver + * doesn't support auto-committing transactions. + */ + function autoCommit($onoff = false) + { + // XXX if $this->transaction_opcount > 0, we should probably + // issue a warning here. + $this->autocommit = $onoff ? true : false; + return DB_OK; + } + + // }}} + // {{{ commit() + + /** + * Commits the current transaction + * + * @return int DB_OK on success. A DB_Error object on failure. + */ + function commit() + { + if ($this->transaction_opcount > 0) { + // (disabled) hack to shut up error messages from libpq.a + //@fclose(@fopen("php://stderr", "w")); + $result = @pg_exec($this->connection, 'end;'); + $this->transaction_opcount = 0; + if (!$result) { + return $this->pgsqlRaiseError(); + } + } + return DB_OK; + } + + // }}} + // {{{ rollback() + + /** + * Reverts the current transaction + * + * @return int DB_OK on success. A DB_Error object on failure. + */ + function rollback() + { + if ($this->transaction_opcount > 0) { + $result = @pg_exec($this->connection, 'abort;'); + $this->transaction_opcount = 0; + if (!$result) { + return $this->pgsqlRaiseError(); + } + } + return DB_OK; + } + + // }}} + // {{{ affectedRows() + + /** + * Determines the number of rows affected by a data maniuplation query + * + * 0 is returned for queries that don't manipulate data. + * + * @return int the number of rows. A DB_Error object on failure. + */ + function affectedRows() + { + return $this->affected; + } + + // }}} + // {{{ nextId() + + /** + * Returns the next free id in a sequence + * + * @param string $seq_name name of the sequence + * @param boolean $ondemand when true, the seqence is automatically + * created if it does not exist + * + * @return int the next id number in the sequence. + * A DB_Error object on failure. + * + * @see DB_common::nextID(), DB_common::getSequenceName(), + * DB_pgsql::createSequence(), DB_pgsql::dropSequence() + */ + function nextId($seq_name, $ondemand = true) + { + $seqname = $this->getSequenceName($seq_name); + $repeat = false; + do { + $this->pushErrorHandling(PEAR_ERROR_RETURN); + $result =& $this->query("SELECT NEXTVAL('${seqname}')"); + $this->popErrorHandling(); + if ($ondemand && DB::isError($result) && + $result->getCode() == DB_ERROR_NOSUCHTABLE) { + $repeat = true; + $this->pushErrorHandling(PEAR_ERROR_RETURN); + $result = $this->createSequence($seq_name); + $this->popErrorHandling(); + if (DB::isError($result)) { + return $this->raiseError($result); + } + } else { + $repeat = false; + } + } while ($repeat); + if (DB::isError($result)) { + return $this->raiseError($result); + } + $arr = $result->fetchRow(DB_FETCHMODE_ORDERED); + $result->free(); + return $arr[0]; + } + + // }}} + // {{{ createSequence() + + /** + * Creates a new sequence + * + * @param string $seq_name name of the new sequence + * + * @return int DB_OK on success. A DB_Error object on failure. + * + * @see DB_common::createSequence(), DB_common::getSequenceName(), + * DB_pgsql::nextID(), DB_pgsql::dropSequence() + */ + function createSequence($seq_name) + { + $seqname = $this->getSequenceName($seq_name); + $result = $this->query("CREATE SEQUENCE ${seqname}"); + return $result; + } + + // }}} + // {{{ dropSequence() + + /** + * Deletes a sequence + * + * @param string $seq_name name of the sequence to be deleted + * + * @return int DB_OK on success. A DB_Error object on failure. + * + * @see DB_common::dropSequence(), DB_common::getSequenceName(), + * DB_pgsql::nextID(), DB_pgsql::createSequence() + */ + function dropSequence($seq_name) + { + return $this->query('DROP SEQUENCE ' + . $this->getSequenceName($seq_name)); + } + + // }}} + // {{{ modifyLimitQuery() + + /** + * Adds LIMIT clauses to a query string according to current DBMS standards + * + * @param string $query the query to modify + * @param int $from the row to start to fetching (0 = the first row) + * @param int $count the numbers of rows to fetch + * @param mixed $params array, string or numeric data to be used in + * execution of the statement. Quantity of items + * passed must match quantity of placeholders in + * query: meaning 1 placeholder for non-array + * parameters or 1 placeholder per array element. + * + * @return string the query string with LIMIT clauses added + * + * @access protected + */ + function modifyLimitQuery($query, $from, $count, $params = array()) + { + return "$query LIMIT $count OFFSET $from"; + } + + // }}} + // {{{ pgsqlRaiseError() + + /** + * Produces a DB_Error object regarding the current problem + * + * @param int $errno if the error is being manually raised pass a + * DB_ERROR* constant here. If this isn't passed + * the error information gathered from the DBMS. + * + * @return object the DB_Error object + * + * @see DB_common::raiseError(), + * DB_pgsql::errorNative(), DB_pgsql::errorCode() + */ + function pgsqlRaiseError($errno = null) + { + $native = $this->errorNative(); + if ($errno === null) { + $errno = $this->errorCode($native); + } + return $this->raiseError($errno, null, null, null, $native); + } + + // }}} + // {{{ errorNative() + + /** + * Gets the DBMS' native error message produced by the last query + * + * {@internal Error messages are used instead of error codes + * in order to support older versions of PostgreSQL.}} + * + * @return string the DBMS' error message + */ + function errorNative() + { + return @pg_errormessage($this->connection); + } + + // }}} + // {{{ errorCode() + + /** + * Determines PEAR::DB error code from the database's text error message. + * + * @param string $errormsg error message returned from the database + * @return integer an error number from a DB error constant + */ + function errorCode($errormsg) + { + static $error_regexps; + if (!isset($error_regexps)) { + $error_regexps = array( + '/(relation|sequence|table).*does not exist|class .* not found/i' + => DB_ERROR_NOSUCHTABLE, + '/index .* does not exist/' + => DB_ERROR_NOT_FOUND, + '/column .* does not exist/i' + => DB_ERROR_NOSUCHFIELD, + '/relation .* already exists/i' + => DB_ERROR_ALREADY_EXISTS, + '/(divide|division) by zero$/i' + => DB_ERROR_DIVZERO, + '/pg_atoi: error in .*: can\'t parse /i' + => DB_ERROR_INVALID_NUMBER, + '/invalid input syntax for( type)? (integer|numeric)/i' + => DB_ERROR_INVALID_NUMBER, + '/value .* is out of range for type \w*int/i' + => DB_ERROR_INVALID_NUMBER, + '/integer out of range/i' + => DB_ERROR_INVALID_NUMBER, + '/value too long for type character/i' + => DB_ERROR_INVALID, + '/attribute .* not found|relation .* does not have attribute/i' + => DB_ERROR_NOSUCHFIELD, + '/column .* specified in USING clause does not exist in (left|right) table/i' + => DB_ERROR_NOSUCHFIELD, + '/parser: parse error at or near/i' + => DB_ERROR_SYNTAX, + '/syntax error at/' + => DB_ERROR_SYNTAX, + '/column reference .* is ambiguous/i' + => DB_ERROR_SYNTAX, + '/permission denied/' + => DB_ERROR_ACCESS_VIOLATION, + '/violates not-null constraint/' + => DB_ERROR_CONSTRAINT_NOT_NULL, + '/violates [\w ]+ constraint/' + => DB_ERROR_CONSTRAINT, + '/referential integrity violation/' + => DB_ERROR_CONSTRAINT, + '/more expressions than target columns/i' + => DB_ERROR_VALUE_COUNT_ON_ROW, + ); + } + foreach ($error_regexps as $regexp => $code) { + if (preg_match($regexp, $errormsg)) { + return $code; + } + } + // Fall back to DB_ERROR if there was no mapping. + return DB_ERROR; + } + + // }}} + // {{{ tableInfo() + + /** + * Returns information about a table or a result set + * + * NOTE: only supports 'table' and 'flags' if $result + * is a table name. + * + * @param object|string $result DB_result object from a query or a + * string containing the name of a table. + * While this also accepts a query result + * resource identifier, this behavior is + * deprecated. + * @param int $mode a valid tableInfo mode + * + * @return array an associative array with the information requested. + * A DB_Error object on failure. + * + * @see DB_common::tableInfo() + */ + function tableInfo($result, $mode = null) + { + if (is_string($result)) { + /* + * Probably received a table name. + * Create a result resource identifier. + */ + $id = @pg_exec($this->connection, "SELECT * FROM $result LIMIT 0"); + $got_string = true; + } elseif (isset($result->result)) { + /* + * Probably received a result object. + * Extract the result resource identifier. + */ + $id = $result->result; + $got_string = false; + } else { + /* + * Probably received a result resource identifier. + * Copy it. + * Deprecated. Here for compatibility only. + */ + $id = $result; + $got_string = false; + } + + if (!is_resource($id)) { + return $this->pgsqlRaiseError(DB_ERROR_NEED_MORE_DATA); + } + + if ($this->options['portability'] & DB_PORTABILITY_LOWERCASE) { + $case_func = 'strtolower'; + } else { + $case_func = 'strval'; + } + + $count = @pg_numfields($id); + $res = array(); + + if ($mode) { + $res['num_fields'] = $count; + } + + for ($i = 0; $i < $count; $i++) { + $res[$i] = array( + 'table' => $got_string ? $case_func($result) : '', + 'name' => $case_func(@pg_fieldname($id, $i)), + 'type' => @pg_fieldtype($id, $i), + 'len' => @pg_fieldsize($id, $i), + 'flags' => $got_string + ? $this->_pgFieldFlags($id, $i, $result) + : '', + ); + if ($mode & DB_TABLEINFO_ORDER) { + $res['order'][$res[$i]['name']] = $i; + } + if ($mode & DB_TABLEINFO_ORDERTABLE) { + $res['ordertable'][$res[$i]['table']][$res[$i]['name']] = $i; + } + } + + // free the result only if we were called on a table + if ($got_string) { + @pg_freeresult($id); + } + return $res; + } + + // }}} + // {{{ _pgFieldFlags() + + /** + * Get a column's flags + * + * Supports "not_null", "default_value", "primary_key", "unique_key" + * and "multiple_key". The default value is passed through + * rawurlencode() in case there are spaces in it. + * + * @param int $resource the PostgreSQL result identifier + * @param int $num_field the field number + * + * @return string the flags + * + * @access private + */ + function _pgFieldFlags($resource, $num_field, $table_name) + { + $field_name = @pg_fieldname($resource, $num_field); + + $result = @pg_exec($this->connection, "SELECT f.attnotnull, f.atthasdef + FROM pg_attribute f, pg_class tab, pg_type typ + WHERE tab.relname = typ.typname + AND typ.typrelid = f.attrelid + AND f.attname = '$field_name' + AND tab.relname = '$table_name'"); + if (@pg_numrows($result) > 0) { + $row = @pg_fetch_row($result, 0); + $flags = ($row[0] == 't') ? 'not_null ' : ''; + + if ($row[1] == 't') { + $result = @pg_exec($this->connection, "SELECT a.adsrc + FROM pg_attribute f, pg_class tab, pg_type typ, pg_attrdef a + WHERE tab.relname = typ.typname AND typ.typrelid = f.attrelid + AND f.attrelid = a.adrelid AND f.attname = '$field_name' + AND tab.relname = '$table_name' AND f.attnum = a.adnum"); + $row = @pg_fetch_row($result, 0); + $num = preg_replace("/'(.*)'::\w+/", "\\1", $row[0]); + $flags .= 'default_' . rawurlencode($num) . ' '; + } + } else { + $flags = ''; + } + $result = @pg_exec($this->connection, "SELECT i.indisunique, i.indisprimary, i.indkey + FROM pg_attribute f, pg_class tab, pg_type typ, pg_index i + WHERE tab.relname = typ.typname + AND typ.typrelid = f.attrelid + AND f.attrelid = i.indrelid + AND f.attname = '$field_name' + AND tab.relname = '$table_name'"); + $count = @pg_numrows($result); + + for ($i = 0; $i < $count ; $i++) { + $row = @pg_fetch_row($result, $i); + $keys = explode(' ', $row[2]); + + if (in_array($num_field + 1, $keys)) { + $flags .= ($row[0] == 't' && $row[1] == 'f') ? 'unique_key ' : ''; + $flags .= ($row[1] == 't') ? 'primary_key ' : ''; + if (count($keys) > 1) + $flags .= 'multiple_key '; + } + } + + return trim($flags); + } + + // }}} + // {{{ getSpecialQuery() + + /** + * Obtains the query string needed for listing a given type of objects + * + * @param string $type the kind of objects you want to retrieve + * + * @return string the SQL query string or null if the driver doesn't + * support the object type requested + * + * @access protected + * @see DB_common::getListOf() + */ + function getSpecialQuery($type) + { + switch ($type) { + case 'tables': + return 'SELECT c.relname AS "Name"' + . ' FROM pg_class c, pg_user u' + . ' WHERE c.relowner = u.usesysid' + . " AND c.relkind = 'r'" + . ' AND NOT EXISTS' + . ' (SELECT 1 FROM pg_views' + . ' WHERE viewname = c.relname)' + . " AND c.relname !~ '^(pg_|sql_)'" + . ' UNION' + . ' SELECT c.relname AS "Name"' + . ' FROM pg_class c' + . " WHERE c.relkind = 'r'" + . ' AND NOT EXISTS' + . ' (SELECT 1 FROM pg_views' + . ' WHERE viewname = c.relname)' + . ' AND NOT EXISTS' + . ' (SELECT 1 FROM pg_user' + . ' WHERE usesysid = c.relowner)' + . " AND c.relname !~ '^pg_'"; + case 'schema.tables': + return "SELECT schemaname || '.' || tablename" + . ' AS "Name"' + . ' FROM pg_catalog.pg_tables' + . ' WHERE schemaname NOT IN' + . " ('pg_catalog', 'information_schema', 'pg_toast')"; + case 'views': + // Table cols: viewname | viewowner | definition + return 'SELECT viewname from pg_views WHERE schemaname' + . " NOT IN ('information_schema', 'pg_catalog')"; + case 'users': + // cols: usename |usesysid|usecreatedb|usetrace|usesuper|usecatupd|passwd |valuntil + return 'SELECT usename FROM pg_user'; + case 'databases': + return 'SELECT datname FROM pg_database'; + case 'functions': + case 'procedures': + return 'SELECT proname FROM pg_proc WHERE proowner <> 1'; + default: + return null; + } + } + + // }}} + +} + +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * End: + */ + +?> diff --git a/events/phpFlickr/PEAR/DB/storage.php b/events/phpFlickr/PEAR/DB/storage.php new file mode 100644 index 0000000..f597b36 --- /dev/null +++ b/events/phpFlickr/PEAR/DB/storage.php @@ -0,0 +1,504 @@ + + * @copyright 1997-2005 The PHP Group + * @license http://www.php.net/license/3_0.txt PHP License 3.0 + * @version CVS: $Id: storage.php 32 2005-08-01 06:21:02Z dancoulter $ + * @link http://pear.php.net/package/DB + */ + +/** + * Obtain the DB class so it can be extended from + */ +require_once 'DB.php'; + +/** + * Provides an object interface to a table row + * + * It lets you add, delete and change rows using objects rather than SQL + * statements. + * + * @category Database + * @package DB + * @author Stig Bakken + * @copyright 1997-2005 The PHP Group + * @license http://www.php.net/license/3_0.txt PHP License 3.0 + * @version Release: @package_version@ + * @link http://pear.php.net/package/DB + */ +class DB_storage extends PEAR +{ + // {{{ properties + + /** the name of the table (or view, if the backend database supports + updates in views) we hold data from */ + var $_table = null; + + /** which column(s) in the table contains primary keys, can be a + string for single-column primary keys, or an array of strings + for multiple-column primary keys */ + var $_keycolumn = null; + + /** DB connection handle used for all transactions */ + var $_dbh = null; + + /** an assoc with the names of database fields stored as properties + in this object */ + var $_properties = array(); + + /** an assoc with the names of the properties in this object that + have been changed since they were fetched from the database */ + var $_changes = array(); + + /** flag that decides if data in this object can be changed. + objects that don't have their table's key column in their + property lists will be flagged as read-only. */ + var $_readonly = false; + + /** function or method that implements a validator for fields that + are set, this validator function returns true if the field is + valid, false if not */ + var $_validator = null; + + // }}} + // {{{ constructor + + /** + * Constructor + * + * @param $table string the name of the database table + * + * @param $keycolumn mixed string with name of key column, or array of + * strings if the table has a primary key of more than one column + * + * @param $dbh object database connection object + * + * @param $validator mixed function or method used to validate + * each new value, called with three parameters: the name of the + * field/column that is changing, a reference to the new value and + * a reference to this object + * + */ + function DB_storage($table, $keycolumn, &$dbh, $validator = null) + { + $this->PEAR('DB_Error'); + $this->_table = $table; + $this->_keycolumn = $keycolumn; + $this->_dbh = $dbh; + $this->_readonly = false; + $this->_validator = $validator; + } + + // }}} + // {{{ _makeWhere() + + /** + * Utility method to build a "WHERE" clause to locate ourselves in + * the table. + * + * XXX future improvement: use rowids? + * + * @access private + */ + function _makeWhere($keyval = null) + { + if (is_array($this->_keycolumn)) { + if ($keyval === null) { + for ($i = 0; $i < sizeof($this->_keycolumn); $i++) { + $keyval[] = $this->{$this->_keycolumn[$i]}; + } + } + $whereclause = ''; + for ($i = 0; $i < sizeof($this->_keycolumn); $i++) { + if ($i > 0) { + $whereclause .= ' AND '; + } + $whereclause .= $this->_keycolumn[$i]; + if (is_null($keyval[$i])) { + // there's not much point in having a NULL key, + // but we support it anyway + $whereclause .= ' IS NULL'; + } else { + $whereclause .= ' = ' . $this->_dbh->quote($keyval[$i]); + } + } + } else { + if ($keyval === null) { + $keyval = @$this->{$this->_keycolumn}; + } + $whereclause = $this->_keycolumn; + if (is_null($keyval)) { + // there's not much point in having a NULL key, + // but we support it anyway + $whereclause .= ' IS NULL'; + } else { + $whereclause .= ' = ' . $this->_dbh->quote($keyval); + } + } + return $whereclause; + } + + // }}} + // {{{ setup() + + /** + * Method used to initialize a DB_storage object from the + * configured table. + * + * @param $keyval mixed the key[s] of the row to fetch (string or array) + * + * @return int DB_OK on success, a DB error if not + */ + function setup($keyval) + { + $whereclause = $this->_makeWhere($keyval); + $query = 'SELECT * FROM ' . $this->_table . ' WHERE ' . $whereclause; + $sth = $this->_dbh->query($query); + if (DB::isError($sth)) { + return $sth; + } + $row = $sth->fetchRow(DB_FETCHMODE_ASSOC); + if (DB::isError($row)) { + return $row; + } + if (!$row) { + return $this->raiseError(null, DB_ERROR_NOT_FOUND, null, null, + $query, null, true); + } + foreach ($row as $key => $value) { + $this->_properties[$key] = true; + $this->$key = $value; + } + return DB_OK; + } + + // }}} + // {{{ insert() + + /** + * Create a new (empty) row in the configured table for this + * object. + */ + function insert($newpk) + { + if (is_array($this->_keycolumn)) { + $primarykey = $this->_keycolumn; + } else { + $primarykey = array($this->_keycolumn); + } + settype($newpk, "array"); + for ($i = 0; $i < sizeof($primarykey); $i++) { + $pkvals[] = $this->_dbh->quote($newpk[$i]); + } + + $sth = $this->_dbh->query("INSERT INTO $this->_table (" . + implode(",", $primarykey) . ") VALUES(" . + implode(",", $pkvals) . ")"); + if (DB::isError($sth)) { + return $sth; + } + if (sizeof($newpk) == 1) { + $newpk = $newpk[0]; + } + $this->setup($newpk); + } + + // }}} + // {{{ toString() + + /** + * Output a simple description of this DB_storage object. + * @return string object description + */ + function toString() + { + $info = strtolower(get_class($this)); + $info .= " (table="; + $info .= $this->_table; + $info .= ", keycolumn="; + if (is_array($this->_keycolumn)) { + $info .= "(" . implode(",", $this->_keycolumn) . ")"; + } else { + $info .= $this->_keycolumn; + } + $info .= ", dbh="; + if (is_object($this->_dbh)) { + $info .= $this->_dbh->toString(); + } else { + $info .= "null"; + } + $info .= ")"; + if (sizeof($this->_properties)) { + $info .= " [loaded, key="; + $keyname = $this->_keycolumn; + if (is_array($keyname)) { + $info .= "("; + for ($i = 0; $i < sizeof($keyname); $i++) { + if ($i > 0) { + $info .= ","; + } + $info .= $this->$keyname[$i]; + } + $info .= ")"; + } else { + $info .= $this->$keyname; + } + $info .= "]"; + } + if (sizeof($this->_changes)) { + $info .= " [modified]"; + } + return $info; + } + + // }}} + // {{{ dump() + + /** + * Dump the contents of this object to "standard output". + */ + function dump() + { + foreach ($this->_properties as $prop => $foo) { + print "$prop = "; + print htmlentities($this->$prop); + print "
\n"; + } + } + + // }}} + // {{{ &create() + + /** + * Static method used to create new DB storage objects. + * @param $data assoc. array where the keys are the names + * of properties/columns + * @return object a new instance of DB_storage or a subclass of it + */ + function &create($table, &$data) + { + $classname = strtolower(get_class($this)); + $obj =& new $classname($table); + foreach ($data as $name => $value) { + $obj->_properties[$name] = true; + $obj->$name = &$value; + } + return $obj; + } + + // }}} + // {{{ loadFromQuery() + + /** + * Loads data into this object from the given query. If this + * object already contains table data, changes will be saved and + * the object re-initialized first. + * + * @param $query SQL query + * + * @param $params parameter list in case you want to use + * prepare/execute mode + * + * @return int DB_OK on success, DB_WARNING_READ_ONLY if the + * returned object is read-only (because the object's specified + * key column was not found among the columns returned by $query), + * or another DB error code in case of errors. + */ +// XXX commented out for now +/* + function loadFromQuery($query, $params = null) + { + if (sizeof($this->_properties)) { + if (sizeof($this->_changes)) { + $this->store(); + $this->_changes = array(); + } + $this->_properties = array(); + } + $rowdata = $this->_dbh->getRow($query, DB_FETCHMODE_ASSOC, $params); + if (DB::isError($rowdata)) { + return $rowdata; + } + reset($rowdata); + $found_keycolumn = false; + while (list($key, $value) = each($rowdata)) { + if ($key == $this->_keycolumn) { + $found_keycolumn = true; + } + $this->_properties[$key] = true; + $this->$key = &$value; + unset($value); // have to unset, or all properties will + // refer to the same value + } + if (!$found_keycolumn) { + $this->_readonly = true; + return DB_WARNING_READ_ONLY; + } + return DB_OK; + } + */ + + // }}} + // {{{ set() + + /** + * Modify an attriute value. + */ + function set($property, $newvalue) + { + // only change if $property is known and object is not + // read-only + if ($this->_readonly) { + return $this->raiseError(null, DB_WARNING_READ_ONLY, null, + null, null, null, true); + } + if (@isset($this->_properties[$property])) { + if (empty($this->_validator)) { + $valid = true; + } else { + $valid = @call_user_func($this->_validator, + $this->_table, + $property, + $newvalue, + $this->$property, + $this); + } + if ($valid) { + $this->$property = $newvalue; + if (empty($this->_changes[$property])) { + $this->_changes[$property] = 0; + } else { + $this->_changes[$property]++; + } + } else { + return $this->raiseError(null, DB_ERROR_INVALID, null, + null, "invalid field: $property", + null, true); + } + return true; + } + return $this->raiseError(null, DB_ERROR_NOSUCHFIELD, null, + null, "unknown field: $property", + null, true); + } + + // }}} + // {{{ &get() + + /** + * Fetch an attribute value. + * + * @param string attribute name + * + * @return attribute contents, or null if the attribute name is + * unknown + */ + function &get($property) + { + // only return if $property is known + if (isset($this->_properties[$property])) { + return $this->$property; + } + $tmp = null; + return $tmp; + } + + // }}} + // {{{ _DB_storage() + + /** + * Destructor, calls DB_storage::store() if there are changes + * that are to be kept. + */ + function _DB_storage() + { + if (sizeof($this->_changes)) { + $this->store(); + } + $this->_properties = array(); + $this->_changes = array(); + $this->_table = null; + } + + // }}} + // {{{ store() + + /** + * Stores changes to this object in the database. + * + * @return DB_OK or a DB error + */ + function store() + { + foreach ($this->_changes as $name => $foo) { + $params[] = &$this->$name; + $vars[] = $name . ' = ?'; + } + if ($vars) { + $query = 'UPDATE ' . $this->_table . ' SET ' . + implode(', ', $vars) . ' WHERE ' . + $this->_makeWhere(); + $stmt = $this->_dbh->prepare($query); + $res = $this->_dbh->execute($stmt, $params); + if (DB::isError($res)) { + return $res; + } + $this->_changes = array(); + } + return DB_OK; + } + + // }}} + // {{{ remove() + + /** + * Remove the row represented by this object from the database. + * + * @return mixed DB_OK or a DB error + */ + function remove() + { + if ($this->_readonly) { + return $this->raiseError(null, DB_WARNING_READ_ONLY, null, + null, null, null, true); + } + $query = 'DELETE FROM ' . $this->_table .' WHERE '. + $this->_makeWhere(); + $res = $this->_dbh->query($query); + if (DB::isError($res)) { + return $res; + } + foreach ($this->_properties as $prop => $foo) { + unset($this->$prop); + } + $this->_properties = array(); + $this->_changes = array(); + return DB_OK; + } + + // }}} +} + +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * End: + */ + +?> diff --git a/events/phpFlickr/PEAR/HTTP/Request.php b/events/phpFlickr/PEAR/HTTP/Request.php new file mode 100644 index 0000000..55e227b --- /dev/null +++ b/events/phpFlickr/PEAR/HTTP/Request.php @@ -0,0 +1,1484 @@ + + * @author Alexey Borzov + * @copyright 2002-2007 Richard Heyes + * @license http://opensource.org/licenses/bsd-license.php New BSD License + * @version CVS: $Id: Request.php 127 2008-01-17 20:21:37Z dcoulter $ + * @link http://pear.php.net/package/HTTP_Request/ + */ + +/** + * PEAR and PEAR_Error classes (for error handling) + */ +require_once 'PEAR.php'; +/** + * Socket class + */ +require_once 'Net/Socket.php'; +/** + * URL handling class + */ +require_once 'Net/URL.php'; + +/**#@+ + * Constants for HTTP request methods + */ +define('HTTP_REQUEST_METHOD_GET', 'GET', true); +define('HTTP_REQUEST_METHOD_HEAD', 'HEAD', true); +define('HTTP_REQUEST_METHOD_POST', 'POST', true); +define('HTTP_REQUEST_METHOD_PUT', 'PUT', true); +define('HTTP_REQUEST_METHOD_DELETE', 'DELETE', true); +define('HTTP_REQUEST_METHOD_OPTIONS', 'OPTIONS', true); +define('HTTP_REQUEST_METHOD_TRACE', 'TRACE', true); +/**#@-*/ + +/**#@+ + * Constants for HTTP request error codes + */ +define('HTTP_REQUEST_ERROR_FILE', 1); +define('HTTP_REQUEST_ERROR_URL', 2); +define('HTTP_REQUEST_ERROR_PROXY', 4); +define('HTTP_REQUEST_ERROR_REDIRECTS', 8); +define('HTTP_REQUEST_ERROR_RESPONSE', 16); +define('HTTP_REQUEST_ERROR_GZIP_METHOD', 32); +define('HTTP_REQUEST_ERROR_GZIP_READ', 64); +define('HTTP_REQUEST_ERROR_GZIP_DATA', 128); +define('HTTP_REQUEST_ERROR_GZIP_CRC', 256); +/**#@-*/ + +/**#@+ + * Constants for HTTP protocol versions + */ +define('HTTP_REQUEST_HTTP_VER_1_0', '1.0', true); +define('HTTP_REQUEST_HTTP_VER_1_1', '1.1', true); +/**#@-*/ + +if (extension_loaded('mbstring') && (2 & ini_get('mbstring.func_overload'))) { + /** + * Whether string functions are overloaded by their mbstring equivalents + */ + define('HTTP_REQUEST_MBSTRING', true); +} else { + /** + * @ignore + */ + define('HTTP_REQUEST_MBSTRING', false); +} + +/** + * Class for performing HTTP requests + * + * Simple example (fetches yahoo.com and displays it): + * + * $a = &new HTTP_Request('http://www.yahoo.com/'); + * $a->sendRequest(); + * echo $a->getResponseBody(); + * + * + * @category HTTP + * @package HTTP_Request + * @author Richard Heyes + * @author Alexey Borzov + * @version Release: 1.4.2 + */ +class HTTP_Request +{ + /**#@+ + * @access private + */ + /** + * Instance of Net_URL + * @var Net_URL + */ + var $_url; + + /** + * Type of request + * @var string + */ + var $_method; + + /** + * HTTP Version + * @var string + */ + var $_http; + + /** + * Request headers + * @var array + */ + var $_requestHeaders; + + /** + * Basic Auth Username + * @var string + */ + var $_user; + + /** + * Basic Auth Password + * @var string + */ + var $_pass; + + /** + * Socket object + * @var Net_Socket + */ + var $_sock; + + /** + * Proxy server + * @var string + */ + var $_proxy_host; + + /** + * Proxy port + * @var integer + */ + var $_proxy_port; + + /** + * Proxy username + * @var string + */ + var $_proxy_user; + + /** + * Proxy password + * @var string + */ + var $_proxy_pass; + + /** + * Post data + * @var array + */ + var $_postData; + + /** + * Request body + * @var string + */ + var $_body; + + /** + * A list of methods that MUST NOT have a request body, per RFC 2616 + * @var array + */ + var $_bodyDisallowed = array('TRACE'); + + /** + * Files to post + * @var array + */ + var $_postFiles = array(); + + /** + * Connection timeout. + * @var float + */ + var $_timeout; + + /** + * HTTP_Response object + * @var HTTP_Response + */ + var $_response; + + /** + * Whether to allow redirects + * @var boolean + */ + var $_allowRedirects; + + /** + * Maximum redirects allowed + * @var integer + */ + var $_maxRedirects; + + /** + * Current number of redirects + * @var integer + */ + var $_redirects; + + /** + * Whether to append brackets [] to array variables + * @var bool + */ + var $_useBrackets = true; + + /** + * Attached listeners + * @var array + */ + var $_listeners = array(); + + /** + * Whether to save response body in response object property + * @var bool + */ + var $_saveBody = true; + + /** + * Timeout for reading from socket (array(seconds, microseconds)) + * @var array + */ + var $_readTimeout = null; + + /** + * Options to pass to Net_Socket::connect. See stream_context_create + * @var array + */ + var $_socketOptions = null; + /**#@-*/ + + /** + * Constructor + * + * Sets up the object + * @param string The url to fetch/access + * @param array Associative array of parameters which can have the following keys: + *
    + *
  • method - Method to use, GET, POST etc (string)
  • + *
  • http - HTTP Version to use, 1.0 or 1.1 (string)
  • + *
  • user - Basic Auth username (string)
  • + *
  • pass - Basic Auth password (string)
  • + *
  • proxy_host - Proxy server host (string)
  • + *
  • proxy_port - Proxy server port (integer)
  • + *
  • proxy_user - Proxy auth username (string)
  • + *
  • proxy_pass - Proxy auth password (string)
  • + *
  • timeout - Connection timeout in seconds (float)
  • + *
  • allowRedirects - Whether to follow redirects or not (bool)
  • + *
  • maxRedirects - Max number of redirects to follow (integer)
  • + *
  • useBrackets - Whether to append [] to array variable names (bool)
  • + *
  • saveBody - Whether to save response body in response object property (bool)
  • + *
  • readTimeout - Timeout for reading / writing data over the socket (array (seconds, microseconds))
  • + *
  • socketOptions - Options to pass to Net_Socket object (array)
  • + *
+ * @access public + */ + function HTTP_Request($url = '', $params = array()) + { + $this->_method = HTTP_REQUEST_METHOD_GET; + $this->_http = HTTP_REQUEST_HTTP_VER_1_1; + $this->_requestHeaders = array(); + $this->_postData = array(); + $this->_body = null; + + $this->_user = null; + $this->_pass = null; + + $this->_proxy_host = null; + $this->_proxy_port = null; + $this->_proxy_user = null; + $this->_proxy_pass = null; + + $this->_allowRedirects = false; + $this->_maxRedirects = 3; + $this->_redirects = 0; + + $this->_timeout = null; + $this->_response = null; + + foreach ($params as $key => $value) { + $this->{'_' . $key} = $value; + } + + if (!empty($url)) { + $this->setURL($url); + } + + // Default useragent + $this->addHeader('User-Agent', 'PEAR HTTP_Request class ( http://pear.php.net/ )'); + + // We don't do keep-alives by default + $this->addHeader('Connection', 'close'); + + // Basic authentication + if (!empty($this->_user)) { + $this->addHeader('Authorization', 'Basic ' . base64_encode($this->_user . ':' . $this->_pass)); + } + + // Proxy authentication (see bug #5913) + if (!empty($this->_proxy_user)) { + $this->addHeader('Proxy-Authorization', 'Basic ' . base64_encode($this->_proxy_user . ':' . $this->_proxy_pass)); + } + + // Use gzip encoding if possible + if (HTTP_REQUEST_HTTP_VER_1_1 == $this->_http && extension_loaded('zlib')) { + $this->addHeader('Accept-Encoding', 'gzip'); + } + } + + /** + * Generates a Host header for HTTP/1.1 requests + * + * @access private + * @return string + */ + function _generateHostHeader() + { + if ($this->_url->port != 80 AND strcasecmp($this->_url->protocol, 'http') == 0) { + $host = $this->_url->host . ':' . $this->_url->port; + + } elseif ($this->_url->port != 443 AND strcasecmp($this->_url->protocol, 'https') == 0) { + $host = $this->_url->host . ':' . $this->_url->port; + + } elseif ($this->_url->port == 443 AND strcasecmp($this->_url->protocol, 'https') == 0 AND strpos($this->_url->url, ':443') !== false) { + $host = $this->_url->host . ':' . $this->_url->port; + + } else { + $host = $this->_url->host; + } + + return $host; + } + + /** + * Resets the object to its initial state (DEPRECATED). + * Takes the same parameters as the constructor. + * + * @param string $url The url to be requested + * @param array $params Associative array of parameters + * (see constructor for details) + * @access public + * @deprecated deprecated since 1.2, call the constructor if this is necessary + */ + function reset($url, $params = array()) + { + $this->HTTP_Request($url, $params); + } + + /** + * Sets the URL to be requested + * + * @param string The url to be requested + * @access public + */ + function setURL($url) + { + $this->_url = &new Net_URL($url, $this->_useBrackets); + + if (!empty($this->_url->user) || !empty($this->_url->pass)) { + $this->setBasicAuth($this->_url->user, $this->_url->pass); + } + + if (HTTP_REQUEST_HTTP_VER_1_1 == $this->_http) { + $this->addHeader('Host', $this->_generateHostHeader()); + } + + // set '/' instead of empty path rather than check later (see bug #8662) + if (empty($this->_url->path)) { + $this->_url->path = '/'; + } + } + + /** + * Returns the current request URL + * + * @return string Current request URL + * @access public + */ + function getUrl() + { + return empty($this->_url)? '': $this->_url->getUrl(); + } + + /** + * Sets a proxy to be used + * + * @param string Proxy host + * @param int Proxy port + * @param string Proxy username + * @param string Proxy password + * @access public + */ + function setProxy($host, $port = 8080, $user = null, $pass = null) + { + $this->_proxy_host = $host; + $this->_proxy_port = $port; + $this->_proxy_user = $user; + $this->_proxy_pass = $pass; + + if (!empty($user)) { + $this->addHeader('Proxy-Authorization', 'Basic ' . base64_encode($user . ':' . $pass)); + } + } + + /** + * Sets basic authentication parameters + * + * @param string Username + * @param string Password + */ + function setBasicAuth($user, $pass) + { + $this->_user = $user; + $this->_pass = $pass; + + $this->addHeader('Authorization', 'Basic ' . base64_encode($user . ':' . $pass)); + } + + /** + * Sets the method to be used, GET, POST etc. + * + * @param string Method to use. Use the defined constants for this + * @access public + */ + function setMethod($method) + { + $this->_method = $method; + } + + /** + * Sets the HTTP version to use, 1.0 or 1.1 + * + * @param string Version to use. Use the defined constants for this + * @access public + */ + function setHttpVer($http) + { + $this->_http = $http; + } + + /** + * Adds a request header + * + * @param string Header name + * @param string Header value + * @access public + */ + function addHeader($name, $value) + { + $this->_requestHeaders[strtolower($name)] = $value; + } + + /** + * Removes a request header + * + * @param string Header name to remove + * @access public + */ + function removeHeader($name) + { + if (isset($this->_requestHeaders[strtolower($name)])) { + unset($this->_requestHeaders[strtolower($name)]); + } + } + + /** + * Adds a querystring parameter + * + * @param string Querystring parameter name + * @param string Querystring parameter value + * @param bool Whether the value is already urlencoded or not, default = not + * @access public + */ + function addQueryString($name, $value, $preencoded = false) + { + $this->_url->addQueryString($name, $value, $preencoded); + } + + /** + * Sets the querystring to literally what you supply + * + * @param string The querystring data. Should be of the format foo=bar&x=y etc + * @param bool Whether data is already urlencoded or not, default = already encoded + * @access public + */ + function addRawQueryString($querystring, $preencoded = true) + { + $this->_url->addRawQueryString($querystring, $preencoded); + } + + /** + * Adds postdata items + * + * @param string Post data name + * @param string Post data value + * @param bool Whether data is already urlencoded or not, default = not + * @access public + */ + function addPostData($name, $value, $preencoded = false) + { + if ($preencoded) { + $this->_postData[$name] = $value; + } else { + $this->_postData[$name] = $this->_arrayMapRecursive('urlencode', $value); + } + } + + /** + * Recursively applies the callback function to the value + * + * @param mixed Callback function + * @param mixed Value to process + * @access private + * @return mixed Processed value + */ + function _arrayMapRecursive($callback, $value) + { + if (!is_array($value)) { + return call_user_func($callback, $value); + } else { + $map = array(); + foreach ($value as $k => $v) { + $map[$k] = $this->_arrayMapRecursive($callback, $v); + } + return $map; + } + } + + /** + * Adds a file to upload + * + * This also changes content-type to 'multipart/form-data' for proper upload + * + * @access public + * @param string name of file-upload field + * @param mixed file name(s) + * @param mixed content-type(s) of file(s) being uploaded + * @return bool true on success + * @throws PEAR_Error + */ + function addFile($inputName, $fileName, $contentType = 'application/octet-stream') + { + if (!is_array($fileName) && !is_readable($fileName)) { + return PEAR::raiseError("File '{$fileName}' is not readable", HTTP_REQUEST_ERROR_FILE); + } elseif (is_array($fileName)) { + foreach ($fileName as $name) { + if (!is_readable($name)) { + return PEAR::raiseError("File '{$name}' is not readable", HTTP_REQUEST_ERROR_FILE); + } + } + } + $this->addHeader('Content-Type', 'multipart/form-data'); + $this->_postFiles[$inputName] = array( + 'name' => $fileName, + 'type' => $contentType + ); + return true; + } + + /** + * Adds raw postdata (DEPRECATED) + * + * @param string The data + * @param bool Whether data is preencoded or not, default = already encoded + * @access public + * @deprecated deprecated since 1.3.0, method setBody() should be used instead + */ + function addRawPostData($postdata, $preencoded = true) + { + $this->_body = $preencoded ? $postdata : urlencode($postdata); + } + + /** + * Sets the request body (for POST, PUT and similar requests) + * + * @param string Request body + * @access public + */ + function setBody($body) + { + $this->_body = $body; + } + + /** + * Clears any postdata that has been added (DEPRECATED). + * + * Useful for multiple request scenarios. + * + * @access public + * @deprecated deprecated since 1.2 + */ + function clearPostData() + { + $this->_postData = null; + } + + /** + * Appends a cookie to "Cookie:" header + * + * @param string $name cookie name + * @param string $value cookie value + * @access public + */ + function addCookie($name, $value) + { + $cookies = isset($this->_requestHeaders['cookie']) ? $this->_requestHeaders['cookie']. '; ' : ''; + $this->addHeader('Cookie', $cookies . $name . '=' . $value); + } + + /** + * Clears any cookies that have been added (DEPRECATED). + * + * Useful for multiple request scenarios + * + * @access public + * @deprecated deprecated since 1.2 + */ + function clearCookies() + { + $this->removeHeader('Cookie'); + } + + /** + * Sends the request + * + * @access public + * @param bool Whether to store response body in Response object property, + * set this to false if downloading a LARGE file and using a Listener + * @return mixed PEAR error on error, true otherwise + */ + function sendRequest($saveBody = true) + { + if (!is_a($this->_url, 'Net_URL')) { + return PEAR::raiseError('No URL given', HTTP_REQUEST_ERROR_URL); + } + + $host = isset($this->_proxy_host) ? $this->_proxy_host : $this->_url->host; + $port = isset($this->_proxy_port) ? $this->_proxy_port : $this->_url->port; + + // 4.3.0 supports SSL connections using OpenSSL. The function test determines + // we running on at least 4.3.0 + if (strcasecmp($this->_url->protocol, 'https') == 0 AND function_exists('file_get_contents') AND extension_loaded('openssl')) { + if (isset($this->_proxy_host)) { + return PEAR::raiseError('HTTPS proxies are not supported', HTTP_REQUEST_ERROR_PROXY); + } + $host = 'ssl://' . $host; + } + + // magic quotes may fuck up file uploads and chunked response processing + $magicQuotes = ini_get('magic_quotes_runtime'); + ini_set('magic_quotes_runtime', false); + + // RFC 2068, section 19.7.1: A client MUST NOT send the Keep-Alive + // connection token to a proxy server... + if (isset($this->_proxy_host) && !empty($this->_requestHeaders['connection']) && + 'Keep-Alive' == $this->_requestHeaders['connection']) + { + $this->removeHeader('connection'); + } + + $keepAlive = (HTTP_REQUEST_HTTP_VER_1_1 == $this->_http && empty($this->_requestHeaders['connection'])) || + (!empty($this->_requestHeaders['connection']) && 'Keep-Alive' == $this->_requestHeaders['connection']); + $sockets = &PEAR::getStaticProperty('HTTP_Request', 'sockets'); + $sockKey = $host . ':' . $port; + unset($this->_sock); + + // There is a connected socket in the "static" property? + if ($keepAlive && !empty($sockets[$sockKey]) && + !empty($sockets[$sockKey]->fp)) + { + $this->_sock =& $sockets[$sockKey]; + $err = null; + } else { + $this->_notify('connect'); + $this->_sock =& new Net_Socket(); + $err = $this->_sock->connect($host, $port, null, $this->_timeout, $this->_socketOptions); + } + PEAR::isError($err) or $err = $this->_sock->write($this->_buildRequest()); + + if (!PEAR::isError($err)) { + if (!empty($this->_readTimeout)) { + $this->_sock->setTimeout($this->_readTimeout[0], $this->_readTimeout[1]); + } + + $this->_notify('sentRequest'); + + // Read the response + $this->_response = &new HTTP_Response($this->_sock, $this->_listeners); + $err = $this->_response->process( + $this->_saveBody && $saveBody, + HTTP_REQUEST_METHOD_HEAD != $this->_method + ); + + if ($keepAlive) { + $keepAlive = (isset($this->_response->_headers['content-length']) + || (isset($this->_response->_headers['transfer-encoding']) + && strtolower($this->_response->_headers['transfer-encoding']) == 'chunked')); + if ($keepAlive) { + if (isset($this->_response->_headers['connection'])) { + $keepAlive = strtolower($this->_response->_headers['connection']) == 'keep-alive'; + } else { + $keepAlive = 'HTTP/'.HTTP_REQUEST_HTTP_VER_1_1 == $this->_response->_protocol; + } + } + } + } + + ini_set('magic_quotes_runtime', $magicQuotes); + + if (PEAR::isError($err)) { + return $err; + } + + if (!$keepAlive) { + $this->disconnect(); + // Store the connected socket in "static" property + } elseif (empty($sockets[$sockKey]) || empty($sockets[$sockKey]->fp)) { + $sockets[$sockKey] =& $this->_sock; + } + + // Check for redirection + if ( $this->_allowRedirects + AND $this->_redirects <= $this->_maxRedirects + AND $this->getResponseCode() > 300 + AND $this->getResponseCode() < 399 + AND !empty($this->_response->_headers['location'])) { + + + $redirect = $this->_response->_headers['location']; + + // Absolute URL + if (preg_match('/^https?:\/\//i', $redirect)) { + $this->_url = &new Net_URL($redirect); + $this->addHeader('Host', $this->_generateHostHeader()); + // Absolute path + } elseif ($redirect{0} == '/') { + $this->_url->path = $redirect; + + // Relative path + } elseif (substr($redirect, 0, 3) == '../' OR substr($redirect, 0, 2) == './') { + if (substr($this->_url->path, -1) == '/') { + $redirect = $this->_url->path . $redirect; + } else { + $redirect = dirname($this->_url->path) . '/' . $redirect; + } + $redirect = Net_URL::resolvePath($redirect); + $this->_url->path = $redirect; + + // Filename, no path + } else { + if (substr($this->_url->path, -1) == '/') { + $redirect = $this->_url->path . $redirect; + } else { + $redirect = dirname($this->_url->path) . '/' . $redirect; + } + $this->_url->path = $redirect; + } + + $this->_redirects++; + return $this->sendRequest($saveBody); + + // Too many redirects + } elseif ($this->_allowRedirects AND $this->_redirects > $this->_maxRedirects) { + return PEAR::raiseError('Too many redirects', HTTP_REQUEST_ERROR_REDIRECTS); + } + + return true; + } + + /** + * Disconnect the socket, if connected. Only useful if using Keep-Alive. + * + * @access public + */ + function disconnect() + { + if (!empty($this->_sock) && !empty($this->_sock->fp)) { + $this->_notify('disconnect'); + $this->_sock->disconnect(); + } + } + + /** + * Returns the response code + * + * @access public + * @return mixed Response code, false if not set + */ + function getResponseCode() + { + return isset($this->_response->_code) ? $this->_response->_code : false; + } + + /** + * Returns either the named header or all if no name given + * + * @access public + * @param string The header name to return, do not set to get all headers + * @return mixed either the value of $headername (false if header is not present) + * or an array of all headers + */ + function getResponseHeader($headername = null) + { + if (!isset($headername)) { + return isset($this->_response->_headers)? $this->_response->_headers: array(); + } else { + $headername = strtolower($headername); + return isset($this->_response->_headers[$headername]) ? $this->_response->_headers[$headername] : false; + } + } + + /** + * Returns the body of the response + * + * @access public + * @return mixed response body, false if not set + */ + function getResponseBody() + { + return isset($this->_response->_body) ? $this->_response->_body : false; + } + + /** + * Returns cookies set in response + * + * @access public + * @return mixed array of response cookies, false if none are present + */ + function getResponseCookies() + { + return isset($this->_response->_cookies) ? $this->_response->_cookies : false; + } + + /** + * Builds the request string + * + * @access private + * @return string The request string + */ + function _buildRequest() + { + $separator = ini_get('arg_separator.output'); + ini_set('arg_separator.output', '&'); + $querystring = ($querystring = $this->_url->getQueryString()) ? '?' . $querystring : ''; + ini_set('arg_separator.output', $separator); + + $host = isset($this->_proxy_host) ? $this->_url->protocol . '://' . $this->_url->host : ''; + $port = (isset($this->_proxy_host) AND $this->_url->port != 80) ? ':' . $this->_url->port : ''; + $path = $this->_url->path . $querystring; + $url = $host . $port . $path; + + if (!strlen($url)) { + $url = '/'; + } + + $request = $this->_method . ' ' . $url . ' HTTP/' . $this->_http . "\r\n"; + + if (in_array($this->_method, $this->_bodyDisallowed) || + (0 == strlen($this->_body) && (HTTP_REQUEST_METHOD_POST != $this->_method || + (empty($this->_postData) && empty($this->_postFiles))))) + { + $this->removeHeader('Content-Type'); + } else { + if (empty($this->_requestHeaders['content-type'])) { + // Add default content-type + $this->addHeader('Content-Type', 'application/x-www-form-urlencoded'); + } elseif ('multipart/form-data' == $this->_requestHeaders['content-type']) { + $boundary = 'HTTP_Request_' . md5(uniqid('request') . microtime()); + $this->addHeader('Content-Type', 'multipart/form-data; boundary=' . $boundary); + } + } + + // Request Headers + if (!empty($this->_requestHeaders)) { + foreach ($this->_requestHeaders as $name => $value) { + $canonicalName = implode('-', array_map('ucfirst', explode('-', $name))); + $request .= $canonicalName . ': ' . $value . "\r\n"; + } + } + + // No post data or wrong method, so simply add a final CRLF + if (in_array($this->_method, $this->_bodyDisallowed) || + (HTTP_REQUEST_METHOD_POST != $this->_method && 0 == strlen($this->_body))) { + + $request .= "\r\n"; + + // Post data if it's an array + } elseif (HTTP_REQUEST_METHOD_POST == $this->_method && + (!empty($this->_postData) || !empty($this->_postFiles))) { + + // "normal" POST request + if (!isset($boundary)) { + $postdata = implode('&', array_map( + create_function('$a', 'return $a[0] . \'=\' . $a[1];'), + $this->_flattenArray('', $this->_postData) + )); + + // multipart request, probably with file uploads + } else { + $postdata = ''; + if (!empty($this->_postData)) { + $flatData = $this->_flattenArray('', $this->_postData); + foreach ($flatData as $item) { + $postdata .= '--' . $boundary . "\r\n"; + $postdata .= 'Content-Disposition: form-data; name="' . $item[0] . '"'; + $postdata .= "\r\n\r\n" . urldecode($item[1]) . "\r\n"; + } + } + foreach ($this->_postFiles as $name => $value) { + if (is_array($value['name'])) { + $varname = $name . ($this->_useBrackets? '[]': ''); + } else { + $varname = $name; + $value['name'] = array($value['name']); + } + foreach ($value['name'] as $key => $filename) { + $fp = fopen($filename, 'r'); + $data = fread($fp, filesize($filename)); + fclose($fp); + $basename = basename($filename); + $type = is_array($value['type'])? @$value['type'][$key]: $value['type']; + + $postdata .= '--' . $boundary . "\r\n"; + $postdata .= 'Content-Disposition: form-data; name="' . $varname . '"; filename="' . $basename . '"'; + $postdata .= "\r\nContent-Type: " . $type; + $postdata .= "\r\n\r\n" . $data . "\r\n"; + } + } + $postdata .= '--' . $boundary . "--\r\n"; + } + $request .= 'Content-Length: ' . + (HTTP_REQUEST_MBSTRING? mb_strlen($postdata, 'iso-8859-1'): strlen($postdata)) . + "\r\n\r\n"; + $request .= $postdata; + + // Explicitly set request body + } elseif (0 < strlen($this->_body)) { + + $request .= 'Content-Length: ' . + (HTTP_REQUEST_MBSTRING? mb_strlen($this->_body, 'iso-8859-1'): strlen($this->_body)) . + "\r\n\r\n"; + $request .= $this->_body; + + // Terminate headers with CRLF on POST request with no body, too + } else { + + $request .= "\r\n"; + } + + return $request; + } + + /** + * Helper function to change the (probably multidimensional) associative array + * into the simple one. + * + * @param string name for item + * @param mixed item's values + * @return array array with the following items: array('item name', 'item value'); + * @access private + */ + function _flattenArray($name, $values) + { + if (!is_array($values)) { + return array(array($name, $values)); + } else { + $ret = array(); + foreach ($values as $k => $v) { + if (empty($name)) { + $newName = $k; + } elseif ($this->_useBrackets) { + $newName = $name . '[' . $k . ']'; + } else { + $newName = $name; + } + $ret = array_merge($ret, $this->_flattenArray($newName, $v)); + } + return $ret; + } + } + + + /** + * Adds a Listener to the list of listeners that are notified of + * the object's events + * + * Events sent by HTTP_Request object + * - 'connect': on connection to server + * - 'sentRequest': after the request was sent + * - 'disconnect': on disconnection from server + * + * Events sent by HTTP_Response object + * - 'gotHeaders': after receiving response headers (headers are passed in $data) + * - 'tick': on receiving a part of response body (the part is passed in $data) + * - 'gzTick': on receiving a gzip-encoded part of response body (ditto) + * - 'gotBody': after receiving the response body (passes the decoded body in $data if it was gzipped) + * + * @param HTTP_Request_Listener listener to attach + * @return boolean whether the listener was successfully attached + * @access public + */ + function attach(&$listener) + { + if (!is_a($listener, 'HTTP_Request_Listener')) { + return false; + } + $this->_listeners[$listener->getId()] =& $listener; + return true; + } + + + /** + * Removes a Listener from the list of listeners + * + * @param HTTP_Request_Listener listener to detach + * @return boolean whether the listener was successfully detached + * @access public + */ + function detach(&$listener) + { + if (!is_a($listener, 'HTTP_Request_Listener') || + !isset($this->_listeners[$listener->getId()])) { + return false; + } + unset($this->_listeners[$listener->getId()]); + return true; + } + + + /** + * Notifies all registered listeners of an event. + * + * @param string Event name + * @param mixed Additional data + * @access private + * @see HTTP_Request::attach() + */ + function _notify($event, $data = null) + { + foreach (array_keys($this->_listeners) as $id) { + $this->_listeners[$id]->update($this, $event, $data); + } + } +} + + +/** + * Response class to complement the Request class + * + * @category HTTP + * @package HTTP_Request + * @author Richard Heyes + * @author Alexey Borzov + * @version Release: 1.4.2 + */ +class HTTP_Response +{ + /** + * Socket object + * @var Net_Socket + */ + var $_sock; + + /** + * Protocol + * @var string + */ + var $_protocol; + + /** + * Return code + * @var string + */ + var $_code; + + /** + * Response headers + * @var array + */ + var $_headers; + + /** + * Cookies set in response + * @var array + */ + var $_cookies; + + /** + * Response body + * @var string + */ + var $_body = ''; + + /** + * Used by _readChunked(): remaining length of the current chunk + * @var string + */ + var $_chunkLength = 0; + + /** + * Attached listeners + * @var array + */ + var $_listeners = array(); + + /** + * Bytes left to read from message-body + * @var null|int + */ + var $_toRead; + + /** + * Constructor + * + * @param Net_Socket socket to read the response from + * @param array listeners attached to request + */ + function HTTP_Response(&$sock, &$listeners) + { + $this->_sock =& $sock; + $this->_listeners =& $listeners; + } + + + /** + * Processes a HTTP response + * + * This extracts response code, headers, cookies and decodes body if it + * was encoded in some way + * + * @access public + * @param bool Whether to store response body in object property, set + * this to false if downloading a LARGE file and using a Listener. + * This is assumed to be true if body is gzip-encoded. + * @param bool Whether the response can actually have a message-body. + * Will be set to false for HEAD requests. + * @throws PEAR_Error + * @return mixed true on success, PEAR_Error in case of malformed response + */ + function process($saveBody = true, $canHaveBody = true) + { + do { + $line = $this->_sock->readLine(); + if (sscanf($line, 'HTTP/%s %s', $http_version, $returncode) != 2) { + return PEAR::raiseError('Malformed response', HTTP_REQUEST_ERROR_RESPONSE); + } else { + $this->_protocol = 'HTTP/' . $http_version; + $this->_code = intval($returncode); + } + while ('' !== ($header = $this->_sock->readLine())) { + $this->_processHeader($header); + } + } while (100 == $this->_code); + + $this->_notify('gotHeaders', $this->_headers); + + // RFC 2616, section 4.4: + // 1. Any response message which "MUST NOT" include a message-body ... + // is always terminated by the first empty line after the header fields + // 3. ... If a message is received with both a + // Transfer-Encoding header field and a Content-Length header field, + // the latter MUST be ignored. + $canHaveBody = $canHaveBody && $this->_code >= 200 && + $this->_code != 204 && $this->_code != 304; + + // If response body is present, read it and decode + $chunked = isset($this->_headers['transfer-encoding']) && ('chunked' == $this->_headers['transfer-encoding']); + $gzipped = isset($this->_headers['content-encoding']) && ('gzip' == $this->_headers['content-encoding']); + $hasBody = false; + if ($canHaveBody && ($chunked || !isset($this->_headers['content-length']) || + 0 != $this->_headers['content-length'])) + { + if ($chunked || !isset($this->_headers['content-length'])) { + $this->_toRead = null; + } else { + $this->_toRead = $this->_headers['content-length']; + } + while (!$this->_sock->eof() && (is_null($this->_toRead) || 0 < $this->_toRead)) { + if ($chunked) { + $data = $this->_readChunked(); + } elseif (is_null($this->_toRead)) { + $data = $this->_sock->read(4096); + } else { + $data = $this->_sock->read(min(4096, $this->_toRead)); + $this->_toRead -= HTTP_REQUEST_MBSTRING? mb_strlen($data, 'iso-8859-1'): strlen($data); + } + if ('' == $data) { + break; + } else { + $hasBody = true; + if ($saveBody || $gzipped) { + $this->_body .= $data; + } + $this->_notify($gzipped? 'gzTick': 'tick', $data); + } + } + } + + if ($hasBody) { + // Uncompress the body if needed + if ($gzipped) { + $body = $this->_decodeGzip($this->_body); + if (PEAR::isError($body)) { + return $body; + } + $this->_body = $body; + $this->_notify('gotBody', $this->_body); + } else { + $this->_notify('gotBody'); + } + } + return true; + } + + + /** + * Processes the response header + * + * @access private + * @param string HTTP header + */ + function _processHeader($header) + { + if (false === strpos($header, ':')) { + return; + } + list($headername, $headervalue) = explode(':', $header, 2); + $headername = strtolower($headername); + $headervalue = ltrim($headervalue); + + if ('set-cookie' != $headername) { + if (isset($this->_headers[$headername])) { + $this->_headers[$headername] .= ',' . $headervalue; + } else { + $this->_headers[$headername] = $headervalue; + } + } else { + $this->_parseCookie($headervalue); + } + } + + + /** + * Parse a Set-Cookie header to fill $_cookies array + * + * @access private + * @param string value of Set-Cookie header + */ + function _parseCookie($headervalue) + { + $cookie = array( + 'expires' => null, + 'domain' => null, + 'path' => null, + 'secure' => false + ); + + // Only a name=value pair + if (!strpos($headervalue, ';')) { + $pos = strpos($headervalue, '='); + $cookie['name'] = trim(substr($headervalue, 0, $pos)); + $cookie['value'] = trim(substr($headervalue, $pos + 1)); + + // Some optional parameters are supplied + } else { + $elements = explode(';', $headervalue); + $pos = strpos($elements[0], '='); + $cookie['name'] = trim(substr($elements[0], 0, $pos)); + $cookie['value'] = trim(substr($elements[0], $pos + 1)); + + for ($i = 1; $i < count($elements); $i++) { + if (false === strpos($elements[$i], '=')) { + $elName = trim($elements[$i]); + $elValue = null; + } else { + list ($elName, $elValue) = array_map('trim', explode('=', $elements[$i])); + } + $elName = strtolower($elName); + if ('secure' == $elName) { + $cookie['secure'] = true; + } elseif ('expires' == $elName) { + $cookie['expires'] = str_replace('"', '', $elValue); + } elseif ('path' == $elName || 'domain' == $elName) { + $cookie[$elName] = urldecode($elValue); + } else { + $cookie[$elName] = $elValue; + } + } + } + $this->_cookies[] = $cookie; + } + + + /** + * Read a part of response body encoded with chunked Transfer-Encoding + * + * @access private + * @return string + */ + function _readChunked() + { + // at start of the next chunk? + if (0 == $this->_chunkLength) { + $line = $this->_sock->readLine(); + if (preg_match('/^([0-9a-f]+)/i', $line, $matches)) { + $this->_chunkLength = hexdec($matches[1]); + // Chunk with zero length indicates the end + if (0 == $this->_chunkLength) { + $this->_sock->readLine(); // make this an eof() + return ''; + } + } else { + return ''; + } + } + $data = $this->_sock->read($this->_chunkLength); + $this->_chunkLength -= HTTP_REQUEST_MBSTRING? mb_strlen($data, 'iso-8859-1'): strlen($data); + if (0 == $this->_chunkLength) { + $this->_sock->readLine(); // Trailing CRLF + } + return $data; + } + + + /** + * Notifies all registered listeners of an event. + * + * @param string Event name + * @param mixed Additional data + * @access private + * @see HTTP_Request::_notify() + */ + function _notify($event, $data = null) + { + foreach (array_keys($this->_listeners) as $id) { + $this->_listeners[$id]->update($this, $event, $data); + } + } + + + /** + * Decodes the message-body encoded by gzip + * + * The real decoding work is done by gzinflate() built-in function, this + * method only parses the header and checks data for compliance with + * RFC 1952 + * + * @access private + * @param string gzip-encoded data + * @return string decoded data + */ + function _decodeGzip($data) + { + if (HTTP_REQUEST_MBSTRING) { + $oldEncoding = mb_internal_encoding(); + mb_internal_encoding('iso-8859-1'); + } + $length = strlen($data); + // If it doesn't look like gzip-encoded data, don't bother + if (18 > $length || strcmp(substr($data, 0, 2), "\x1f\x8b")) { + return $data; + } + $method = ord(substr($data, 2, 1)); + if (8 != $method) { + return PEAR::raiseError('_decodeGzip(): unknown compression method', HTTP_REQUEST_ERROR_GZIP_METHOD); + } + $flags = ord(substr($data, 3, 1)); + if ($flags & 224) { + return PEAR::raiseError('_decodeGzip(): reserved bits are set', HTTP_REQUEST_ERROR_GZIP_DATA); + } + + // header is 10 bytes minimum. may be longer, though. + $headerLength = 10; + // extra fields, need to skip 'em + if ($flags & 4) { + if ($length - $headerLength - 2 < 8) { + return PEAR::raiseError('_decodeGzip(): data too short', HTTP_REQUEST_ERROR_GZIP_DATA); + } + $extraLength = unpack('v', substr($data, 10, 2)); + if ($length - $headerLength - 2 - $extraLength[1] < 8) { + return PEAR::raiseError('_decodeGzip(): data too short', HTTP_REQUEST_ERROR_GZIP_DATA); + } + $headerLength += $extraLength[1] + 2; + } + // file name, need to skip that + if ($flags & 8) { + if ($length - $headerLength - 1 < 8) { + return PEAR::raiseError('_decodeGzip(): data too short', HTTP_REQUEST_ERROR_GZIP_DATA); + } + $filenameLength = strpos(substr($data, $headerLength), chr(0)); + if (false === $filenameLength || $length - $headerLength - $filenameLength - 1 < 8) { + return PEAR::raiseError('_decodeGzip(): data too short', HTTP_REQUEST_ERROR_GZIP_DATA); + } + $headerLength += $filenameLength + 1; + } + // comment, need to skip that also + if ($flags & 16) { + if ($length - $headerLength - 1 < 8) { + return PEAR::raiseError('_decodeGzip(): data too short', HTTP_REQUEST_ERROR_GZIP_DATA); + } + $commentLength = strpos(substr($data, $headerLength), chr(0)); + if (false === $commentLength || $length - $headerLength - $commentLength - 1 < 8) { + return PEAR::raiseError('_decodeGzip(): data too short', HTTP_REQUEST_ERROR_GZIP_DATA); + } + $headerLength += $commentLength + 1; + } + // have a CRC for header. let's check + if ($flags & 1) { + if ($length - $headerLength - 2 < 8) { + return PEAR::raiseError('_decodeGzip(): data too short', HTTP_REQUEST_ERROR_GZIP_DATA); + } + $crcReal = 0xffff & crc32(substr($data, 0, $headerLength)); + $crcStored = unpack('v', substr($data, $headerLength, 2)); + if ($crcReal != $crcStored[1]) { + return PEAR::raiseError('_decodeGzip(): header CRC check failed', HTTP_REQUEST_ERROR_GZIP_CRC); + } + $headerLength += 2; + } + // unpacked data CRC and size at the end of encoded data + $tmp = unpack('V2', substr($data, -8)); + $dataCrc = $tmp[1]; + $dataSize = $tmp[2]; + + // finally, call the gzinflate() function + $unpacked = @gzinflate(substr($data, $headerLength, -8), $dataSize); + if (false === $unpacked) { + return PEAR::raiseError('_decodeGzip(): gzinflate() call failed', HTTP_REQUEST_ERROR_GZIP_READ); + } elseif ($dataSize != strlen($unpacked)) { + return PEAR::raiseError('_decodeGzip(): data size check failed', HTTP_REQUEST_ERROR_GZIP_READ); + } elseif ((0xffffffff & $dataCrc) != (0xffffffff & crc32($unpacked))) { + return PEAR::raiseError('_decodeGzip(): data CRC check failed', HTTP_REQUEST_ERROR_GZIP_CRC); + } + if (HTTP_REQUEST_MBSTRING) { + mb_internal_encoding($oldEncoding); + } + return $unpacked; + } +} // End class HTTP_Response +?> diff --git a/events/phpFlickr/PEAR/HTTP/Request/Listener.php b/events/phpFlickr/PEAR/HTTP/Request/Listener.php new file mode 100644 index 0000000..b005142 --- /dev/null +++ b/events/phpFlickr/PEAR/HTTP/Request/Listener.php @@ -0,0 +1,106 @@ + + * @copyright 2002-2007 Richard Heyes + * @license http://opensource.org/licenses/bsd-license.php New BSD License + * @version CVS: $Id: Listener.php 127 2008-01-17 20:21:37Z dcoulter $ + * @link http://pear.php.net/package/HTTP_Request/ + */ + +/** + * Listener for HTTP_Request and HTTP_Response objects + * + * This class implements the Observer part of a Subject-Observer + * design pattern. + * + * @category HTTP + * @package HTTP_Request + * @author Alexey Borzov + * @version Release: 1.4.2 + */ +class HTTP_Request_Listener +{ + /** + * A listener's identifier + * @var string + */ + var $_id; + + /** + * Constructor, sets the object's identifier + * + * @access public + */ + function HTTP_Request_Listener() + { + $this->_id = md5(uniqid('http_request_', 1)); + } + + + /** + * Returns the listener's identifier + * + * @access public + * @return string + */ + function getId() + { + return $this->_id; + } + + + /** + * This method is called when Listener is notified of an event + * + * @access public + * @param object an object the listener is attached to + * @param string Event name + * @param mixed Additional data + * @abstract + */ + function update(&$subject, $event, $data = null) + { + echo "Notified of event: '$event'\n"; + if (null !== $data) { + echo "Additional data: "; + var_dump($data); + } + } +} +?> diff --git a/events/phpFlickr/PEAR/Net/Socket.php b/events/phpFlickr/PEAR/Net/Socket.php new file mode 100644 index 0000000..96f2c4b --- /dev/null +++ b/events/phpFlickr/PEAR/Net/Socket.php @@ -0,0 +1,528 @@ + | +// | Chuck Hagenbuch | +// +----------------------------------------------------------------------+ +// +// $Id: Socket.php 32 2005-08-01 06:21:02Z dancoulter $ + +require_once 'PEAR.php'; + +define('NET_SOCKET_READ', 1); +define('NET_SOCKET_WRITE', 2); +define('NET_SOCKET_ERROR', 3); + +/** + * Generalized Socket class. + * + * @version 1.1 + * @author Stig Bakken + * @author Chuck Hagenbuch + */ +class Net_Socket extends PEAR { + + /** + * Socket file pointer. + * @var resource $fp + */ + var $fp = null; + + /** + * Whether the socket is blocking. Defaults to true. + * @var boolean $blocking + */ + var $blocking = true; + + /** + * Whether the socket is persistent. Defaults to false. + * @var boolean $persistent + */ + var $persistent = false; + + /** + * The IP address to connect to. + * @var string $addr + */ + var $addr = ''; + + /** + * The port number to connect to. + * @var integer $port + */ + var $port = 0; + + /** + * Number of seconds to wait on socket connections before assuming + * there's no more data. Defaults to no timeout. + * @var integer $timeout + */ + var $timeout = false; + + /** + * Number of bytes to read at a time in readLine() and + * readAll(). Defaults to 2048. + * @var integer $lineLength + */ + var $lineLength = 2048; + + /** + * Connect to the specified port. If called when the socket is + * already connected, it disconnects and connects again. + * + * @param string $addr IP address or host name. + * @param integer $port TCP port number. + * @param boolean $persistent (optional) Whether the connection is + * persistent (kept open between requests + * by the web server). + * @param integer $timeout (optional) How long to wait for data. + * @param array $options See options for stream_context_create. + * + * @access public + * + * @return boolean | PEAR_Error True on success or a PEAR_Error on failure. + */ + function connect($addr, $port = 0, $persistent = null, $timeout = null, $options = null) + { + if (is_resource($this->fp)) { + @fclose($this->fp); + $this->fp = null; + } + + if (!$addr) { + return $this->raiseError('$addr cannot be empty'); + } elseif (strspn($addr, '.0123456789') == strlen($addr) || + strstr($addr, '/') !== false) { + $this->addr = $addr; + } else { + $this->addr = @gethostbyname($addr); + } + + $this->port = $port % 65536; + + if ($persistent !== null) { + $this->persistent = $persistent; + } + + if ($timeout !== null) { + $this->timeout = $timeout; + } + + $openfunc = $this->persistent ? 'pfsockopen' : 'fsockopen'; + $errno = 0; + $errstr = ''; + if ($options && function_exists('stream_context_create')) { + if ($this->timeout) { + $timeout = $this->timeout; + } else { + $timeout = 0; + } + $context = stream_context_create($options); + $fp = @$openfunc($this->addr, $this->port, $errno, $errstr, $timeout, $context); + } else { + if ($this->timeout) { + $fp = @$openfunc($this->addr, $this->port, $errno, $errstr, $this->timeout); + } else { + $fp = @$openfunc($this->addr, $this->port, $errno, $errstr); + } + } + + if (!$fp) { + return $this->raiseError($errstr, $errno); + } + + $this->fp = $fp; + + return $this->setBlocking($this->blocking); + } + + /** + * Disconnects from the peer, closes the socket. + * + * @access public + * @return mixed true on success or an error object otherwise + */ + function disconnect() + { + if (!is_resource($this->fp)) { + return $this->raiseError('not connected'); + } + + @fclose($this->fp); + $this->fp = null; + return true; + } + + /** + * Find out if the socket is in blocking mode. + * + * @access public + * @return boolean The current blocking mode. + */ + function isBlocking() + { + return $this->blocking; + } + + /** + * Sets whether the socket connection should be blocking or + * not. A read call to a non-blocking socket will return immediately + * if there is no data available, whereas it will block until there + * is data for blocking sockets. + * + * @param boolean $mode True for blocking sockets, false for nonblocking. + * @access public + * @return mixed true on success or an error object otherwise + */ + function setBlocking($mode) + { + if (!is_resource($this->fp)) { + return $this->raiseError('not connected'); + } + + $this->blocking = $mode; + socket_set_blocking($this->fp, $this->blocking); + return true; + } + + /** + * Sets the timeout value on socket descriptor, + * expressed in the sum of seconds and microseconds + * + * @param integer $seconds Seconds. + * @param integer $microseconds Microseconds. + * @access public + * @return mixed true on success or an error object otherwise + */ + function setTimeout($seconds, $microseconds) + { + if (!is_resource($this->fp)) { + return $this->raiseError('not connected'); + } + + return socket_set_timeout($this->fp, $seconds, $microseconds); + } + + /** + * Returns information about an existing socket resource. + * Currently returns four entries in the result array: + * + *

+ * timed_out (bool) - The socket timed out waiting for data
+ * blocked (bool) - The socket was blocked
+ * eof (bool) - Indicates EOF event
+ * unread_bytes (int) - Number of bytes left in the socket buffer
+ *

+ * + * @access public + * @return mixed Array containing information about existing socket resource or an error object otherwise + */ + function getStatus() + { + if (!is_resource($this->fp)) { + return $this->raiseError('not connected'); + } + + return socket_get_status($this->fp); + } + + /** + * Get a specified line of data + * + * @access public + * @return $size bytes of data from the socket, or a PEAR_Error if + * not connected. + */ + function gets($size) + { + if (!is_resource($this->fp)) { + return $this->raiseError('not connected'); + } + + return @fgets($this->fp, $size); + } + + /** + * Read a specified amount of data. This is guaranteed to return, + * and has the added benefit of getting everything in one fread() + * chunk; if you know the size of the data you're getting + * beforehand, this is definitely the way to go. + * + * @param integer $size The number of bytes to read from the socket. + * @access public + * @return $size bytes of data from the socket, or a PEAR_Error if + * not connected. + */ + function read($size) + { + if (!is_resource($this->fp)) { + return $this->raiseError('not connected'); + } + + return @fread($this->fp, $size); + } + + /** + * Write a specified amount of data. + * + * @param string $data Data to write. + * @param integer $blocksize Amount of data to write at once. + * NULL means all at once. + * + * @access public + * @return mixed true on success or an error object otherwise + */ + function write($data, $blocksize = null) + { + if (!is_resource($this->fp)) { + return $this->raiseError('not connected'); + } + + if (is_null($blocksize) && !OS_WINDOWS) { + return fwrite($this->fp, $data); + } else { + if (is_null($blocksize)) { + $blocksize = 1024; + } + + $pos = 0; + $size = strlen($data); + while ($pos < $size) { + $written = @fwrite($this->fp, substr($data, $pos, $blocksize)); + if ($written === false) { + return false; + } + $pos += $written; + } + + return $pos; + } + } + + /** + * Write a line of data to the socket, followed by a trailing "\r\n". + * + * @access public + * @return mixed fputs result, or an error + */ + function writeLine($data) + { + if (!is_resource($this->fp)) { + return $this->raiseError('not connected'); + } + + return fwrite($this->fp, $data . "\r\n"); + } + + /** + * Tests for end-of-file on a socket descriptor. + * + * @access public + * @return bool + */ + function eof() + { + return (is_resource($this->fp) && feof($this->fp)); + } + + /** + * Reads a byte of data + * + * @access public + * @return 1 byte of data from the socket, or a PEAR_Error if + * not connected. + */ + function readByte() + { + if (!is_resource($this->fp)) { + return $this->raiseError('not connected'); + } + + return ord(@fread($this->fp, 1)); + } + + /** + * Reads a word of data + * + * @access public + * @return 1 word of data from the socket, or a PEAR_Error if + * not connected. + */ + function readWord() + { + if (!is_resource($this->fp)) { + return $this->raiseError('not connected'); + } + + $buf = @fread($this->fp, 2); + return (ord($buf[0]) + (ord($buf[1]) << 8)); + } + + /** + * Reads an int of data + * + * @access public + * @return integer 1 int of data from the socket, or a PEAR_Error if + * not connected. + */ + function readInt() + { + if (!is_resource($this->fp)) { + return $this->raiseError('not connected'); + } + + $buf = @fread($this->fp, 4); + return (ord($buf[0]) + (ord($buf[1]) << 8) + + (ord($buf[2]) << 16) + (ord($buf[3]) << 24)); + } + + /** + * Reads a zero-terminated string of data + * + * @access public + * @return string, or a PEAR_Error if + * not connected. + */ + function readString() + { + if (!is_resource($this->fp)) { + return $this->raiseError('not connected'); + } + + $string = ''; + while (($char = @fread($this->fp, 1)) != "\x00") { + $string .= $char; + } + return $string; + } + + /** + * Reads an IP Address and returns it in a dot formated string + * + * @access public + * @return Dot formated string, or a PEAR_Error if + * not connected. + */ + function readIPAddress() + { + if (!is_resource($this->fp)) { + return $this->raiseError('not connected'); + } + + $buf = @fread($this->fp, 4); + return sprintf("%s.%s.%s.%s", ord($buf[0]), ord($buf[1]), + ord($buf[2]), ord($buf[3])); + } + + /** + * Read until either the end of the socket or a newline, whichever + * comes first. Strips the trailing newline from the returned data. + * + * @access public + * @return All available data up to a newline, without that + * newline, or until the end of the socket, or a PEAR_Error if + * not connected. + */ + function readLine() + { + if (!is_resource($this->fp)) { + return $this->raiseError('not connected'); + } + + $line = ''; + $timeout = time() + $this->timeout; + while (!feof($this->fp) && (!$this->timeout || time() < $timeout)) { + $line .= @fgets($this->fp, $this->lineLength); + if (substr($line, -1) == "\n") { + return rtrim($line, "\r\n"); + } + } + return $line; + } + + /** + * Read until the socket closes, or until there is no more data in + * the inner PHP buffer. If the inner buffer is empty, in blocking + * mode we wait for at least 1 byte of data. Therefore, in + * blocking mode, if there is no data at all to be read, this + * function will never exit (unless the socket is closed on the + * remote end). + * + * @access public + * + * @return string All data until the socket closes, or a PEAR_Error if + * not connected. + */ + function readAll() + { + if (!is_resource($this->fp)) { + return $this->raiseError('not connected'); + } + + $data = ''; + while (!feof($this->fp)) { + $data .= @fread($this->fp, $this->lineLength); + } + return $data; + } + + /** + * Runs the equivalent of the select() system call on the socket + * with a timeout specified by tv_sec and tv_usec. + * + * @param integer $state Which of read/write/error to check for. + * @param integer $tv_sec Number of seconds for timeout. + * @param integer $tv_usec Number of microseconds for timeout. + * + * @access public + * @return False if select fails, integer describing which of read/write/error + * are ready, or PEAR_Error if not connected. + */ + function select($state, $tv_sec, $tv_usec = 0) + { + if (!is_resource($this->fp)) { + return $this->raiseError('not connected'); + } + + $read = null; + $write = null; + $except = null; + if ($state & NET_SOCKET_READ) { + $read[] = $this->fp; + } + if ($state & NET_SOCKET_WRITE) { + $write[] = $this->fp; + } + if ($state & NET_SOCKET_ERROR) { + $except[] = $this->fp; + } + if (false === ($sr = stream_select($read, $write, $except, $tv_sec, $tv_usec))) { + return false; + } + + $result = 0; + if (count($read)) { + $result |= NET_SOCKET_READ; + } + if (count($write)) { + $result |= NET_SOCKET_WRITE; + } + if (count($except)) { + $result |= NET_SOCKET_ERROR; + } + return $result; + } + +} diff --git a/events/phpFlickr/PEAR/Net/URL.php b/events/phpFlickr/PEAR/Net/URL.php new file mode 100644 index 0000000..38e26fd --- /dev/null +++ b/events/phpFlickr/PEAR/Net/URL.php @@ -0,0 +1,410 @@ + | +// +-----------------------------------------------------------------------+ +// +// $Id: URL.php 32 2005-08-01 06:21:02Z dancoulter $ +// +// Net_URL Class + +class Net_URL +{ + /** + * Full url + * @var string + */ + var $url; + + /** + * Protocol + * @var string + */ + var $protocol; + + /** + * Username + * @var string + */ + var $username; + + /** + * Password + * @var string + */ + var $password; + + /** + * Host + * @var string + */ + var $host; + + /** + * Port + * @var integer + */ + var $port; + + /** + * Path + * @var string + */ + var $path; + + /** + * Query string + * @var array + */ + var $querystring; + + /** + * Anchor + * @var string + */ + var $anchor; + + /** + * Whether to use [] + * @var bool + */ + var $useBrackets; + + /** + * PHP4 Constructor + * + * @see __construct() + */ + function Net_URL($url = null, $useBrackets = true) + { + $this->__construct($url, $useBrackets); + } + + /** + * PHP5 Constructor + * + * Parses the given url and stores the various parts + * Defaults are used in certain cases + * + * @param string $url Optional URL + * @param bool $useBrackets Whether to use square brackets when + * multiple querystrings with the same name + * exist + */ + function __construct($url = null, $useBrackets = true) + { + $HTTP_SERVER_VARS = !empty($_SERVER) ? $_SERVER : $GLOBALS['HTTP_SERVER_VARS']; + + $this->useBrackets = $useBrackets; + $this->url = $url; + $this->user = ''; + $this->pass = ''; + $this->host = ''; + $this->port = 80; + $this->path = ''; + $this->querystring = array(); + $this->anchor = ''; + + // Only use defaults if not an absolute URL given + if (!preg_match('/^[a-z0-9]+:\/\//i', $url)) { + + $this->protocol = (@$HTTP_SERVER_VARS['HTTPS'] == 'on' ? 'https' : 'http'); + + /** + * Figure out host/port + */ + if (!empty($HTTP_SERVER_VARS['HTTP_HOST']) AND preg_match('/^(.*)(:([0-9]+))?$/U', $HTTP_SERVER_VARS['HTTP_HOST'], $matches)) { + $host = $matches[1]; + if (!empty($matches[3])) { + $port = $matches[3]; + } else { + $port = $this->getStandardPort($this->protocol); + } + } + + $this->user = ''; + $this->pass = ''; + $this->host = !empty($host) ? $host : (isset($HTTP_SERVER_VARS['SERVER_NAME']) ? $HTTP_SERVER_VARS['SERVER_NAME'] : 'localhost'); + $this->port = !empty($port) ? $port : (isset($HTTP_SERVER_VARS['SERVER_PORT']) ? $HTTP_SERVER_VARS['SERVER_PORT'] : $this->getStandardPort($this->protocol)); + $this->path = !empty($HTTP_SERVER_VARS['PHP_SELF']) ? $HTTP_SERVER_VARS['PHP_SELF'] : '/'; + $this->querystring = isset($HTTP_SERVER_VARS['QUERY_STRING']) ? $this->_parseRawQuerystring($HTTP_SERVER_VARS['QUERY_STRING']) : null; + $this->anchor = ''; + } + + // Parse the url and store the various parts + if (!empty($url)) { + $urlinfo = parse_url($url); + + // Default querystring + $this->querystring = array(); + + foreach ($urlinfo as $key => $value) { + switch ($key) { + case 'scheme': + $this->protocol = $value; + $this->port = $this->getStandardPort($value); + break; + + case 'user': + case 'pass': + case 'host': + case 'port': + $this->$key = $value; + break; + + case 'path': + if ($value{0} == '/') { + $this->path = $value; + } else { + $path = dirname($this->path) == DIRECTORY_SEPARATOR ? '' : dirname($this->path); + $this->path = sprintf('%s/%s', $path, $value); + } + break; + + case 'query': + $this->querystring = $this->_parseRawQueryString($value); + break; + + case 'fragment': + $this->anchor = $value; + break; + } + } + } + } + + /** + * Returns full url + * + * @return string Full url + * @access public + */ + function getURL() + { + $querystring = $this->getQueryString(); + + $this->url = $this->protocol . '://' + . $this->user . (!empty($this->pass) ? ':' : '') + . $this->pass . (!empty($this->user) ? '@' : '') + . $this->host . ($this->port == $this->getStandardPort($this->protocol) ? '' : ':' . $this->port) + . $this->path + . (!empty($querystring) ? '?' . $querystring : '') + . (!empty($this->anchor) ? '#' . $this->anchor : ''); + + return $this->url; + } + + /** + * Adds a querystring item + * + * @param string $name Name of item + * @param string $value Value of item + * @param bool $preencoded Whether value is urlencoded or not, default = not + * @access public + */ + function addQueryString($name, $value, $preencoded = false) + { + if ($preencoded) { + $this->querystring[$name] = $value; + } else { + $this->querystring[$name] = is_array($value) ? array_map('rawurlencode', $value): rawurlencode($value); + } + } + + /** + * Removes a querystring item + * + * @param string $name Name of item + * @access public + */ + function removeQueryString($name) + { + if (isset($this->querystring[$name])) { + unset($this->querystring[$name]); + } + } + + /** + * Sets the querystring to literally what you supply + * + * @param string $querystring The querystring data. Should be of the format foo=bar&x=y etc + * @access public + */ + function addRawQueryString($querystring) + { + $this->querystring = $this->_parseRawQueryString($querystring); + } + + /** + * Returns flat querystring + * + * @return string Querystring + * @access public + */ + function getQueryString() + { + if (!empty($this->querystring)) { + foreach ($this->querystring as $name => $value) { + if (is_array($value)) { + foreach ($value as $k => $v) { + $querystring[] = $this->useBrackets ? sprintf('%s[%s]=%s', $name, $k, $v) : ($name . '=' . $v); + } + } elseif (!is_null($value)) { + $querystring[] = $name . '=' . $value; + } else { + $querystring[] = $name; + } + } + $querystring = implode(ini_get('arg_separator.output'), $querystring); + } else { + $querystring = ''; + } + + return $querystring; + } + + /** + * Parses raw querystring and returns an array of it + * + * @param string $querystring The querystring to parse + * @return array An array of the querystring data + * @access private + */ + function _parseRawQuerystring($querystring) + { + $parts = preg_split('/[' . preg_quote(ini_get('arg_separator.input'), '/') . ']/', $querystring, -1, PREG_SPLIT_NO_EMPTY); + $return = array(); + + foreach ($parts as $part) { + if (strpos($part, '=') !== false) { + $value = substr($part, strpos($part, '=') + 1); + $key = substr($part, 0, strpos($part, '=')); + } else { + $value = null; + $key = $part; + } + if (substr($key, -2) == '[]') { + $key = substr($key, 0, -2); + if (@!is_array($return[$key])) { + $return[$key] = array(); + $return[$key][] = $value; + } else { + $return[$key][] = $value; + } + } elseif (!$this->useBrackets AND !empty($return[$key])) { + $return[$key] = (array)$return[$key]; + $return[$key][] = $value; + } else { + $return[$key] = $value; + } + } + + return $return; + } + + /** + * Resolves //, ../ and ./ from a path and returns + * the result. Eg: + * + * /foo/bar/../boo.php => /foo/boo.php + * /foo/bar/../../boo.php => /boo.php + * /foo/bar/.././/boo.php => /foo/boo.php + * + * This method can also be called statically. + * + * @param string $url URL path to resolve + * @return string The result + */ + function resolvePath($path) + { + $path = explode('/', str_replace('//', '/', $path)); + + for ($i=0; $i 1 OR ($i == 1 AND $path[0] != '') ) ) { + unset($path[$i]); + unset($path[$i-1]); + $path = array_values($path); + $i -= 2; + + } elseif ($path[$i] == '..' AND $i == 1 AND $path[0] == '') { + unset($path[$i]); + $path = array_values($path); + $i--; + + } else { + continue; + } + } + + return implode('/', $path); + } + + /** + * Returns the standard port number for a protocol + * + * @param string $scheme The protocol to lookup + * @return integer Port number or NULL if no scheme matches + * + * @author Philippe Jausions + */ + function getStandardPort($scheme) + { + switch (strtolower($scheme)) { + case 'http': return 80; + case 'https': return 443; + case 'ftp': return 21; + case 'imap': return 143; + case 'imaps': return 993; + case 'pop3': return 110; + case 'pop3s': return 995; + default: return null; + } + } + + /** + * Forces the URL to a particular protocol + * + * @param string $protocol Protocol to force the URL to + * @param integer $port Optional port (standard port is used by default) + */ + function setProtocol($protocol, $port = null) + { + $this->protocol = $protocol; + $this->port = is_null($port) ? $this->getStandardPort() : $port; + } + +} +?> diff --git a/events/phpFlickr/PEAR/PEAR.php b/events/phpFlickr/PEAR/PEAR.php new file mode 100644 index 0000000..e442d8c --- /dev/null +++ b/events/phpFlickr/PEAR/PEAR.php @@ -0,0 +1,1108 @@ + + * @author Stig Bakken + * @author Tomas V.V.Cox + * @author Greg Beaver + * @copyright 1997-2006 The PHP Group + * @license http://www.php.net/license/3_0.txt PHP License 3.0 + * @version CVS: $Id: PEAR.php 127 2008-01-17 20:21:37Z dcoulter $ + * @link http://pear.php.net/package/PEAR + * @since File available since Release 0.1 + */ + +/**#@+ + * ERROR constants + */ +define('PEAR_ERROR_RETURN', 1); +define('PEAR_ERROR_PRINT', 2); +define('PEAR_ERROR_TRIGGER', 4); +define('PEAR_ERROR_DIE', 8); +define('PEAR_ERROR_CALLBACK', 16); +/** + * WARNING: obsolete + * @deprecated + */ +define('PEAR_ERROR_EXCEPTION', 32); +/**#@-*/ +define('PEAR_ZE2', (function_exists('version_compare') && + version_compare(zend_version(), "2-dev", "ge"))); + +if (substr(PHP_OS, 0, 3) == 'WIN') { + define('OS_WINDOWS', true); + define('OS_UNIX', false); + define('PEAR_OS', 'Windows'); +} else { + define('OS_WINDOWS', false); + define('OS_UNIX', true); + define('PEAR_OS', 'Unix'); // blatant assumption +} + +// instant backwards compatibility +if (!defined('PATH_SEPARATOR')) { + if (OS_WINDOWS) { + define('PATH_SEPARATOR', ';'); + } else { + define('PATH_SEPARATOR', ':'); + } +} + +$GLOBALS['_PEAR_default_error_mode'] = PEAR_ERROR_RETURN; +$GLOBALS['_PEAR_default_error_options'] = E_USER_NOTICE; +$GLOBALS['_PEAR_destructor_object_list'] = array(); +$GLOBALS['_PEAR_shutdown_funcs'] = array(); +$GLOBALS['_PEAR_error_handler_stack'] = array(); + +@ini_set('track_errors', true); + +/** + * Base class for other PEAR classes. Provides rudimentary + * emulation of destructors. + * + * If you want a destructor in your class, inherit PEAR and make a + * destructor method called _yourclassname (same name as the + * constructor, but with a "_" prefix). Also, in your constructor you + * have to call the PEAR constructor: $this->PEAR();. + * The destructor method will be called without parameters. Note that + * at in some SAPI implementations (such as Apache), any output during + * the request shutdown (in which destructors are called) seems to be + * discarded. If you need to get any debug information from your + * destructor, use error_log(), syslog() or something similar. + * + * IMPORTANT! To use the emulated destructors you need to create the + * objects by reference: $obj =& new PEAR_child; + * + * @category pear + * @package PEAR + * @author Stig Bakken + * @author Tomas V.V. Cox + * @author Greg Beaver + * @copyright 1997-2006 The PHP Group + * @license http://www.php.net/license/3_0.txt PHP License 3.0 + * @version Release: 1.6.2 + * @link http://pear.php.net/package/PEAR + * @see PEAR_Error + * @since Class available since PHP 4.0.2 + * @link http://pear.php.net/manual/en/core.pear.php#core.pear.pear + */ +class PEAR +{ + // {{{ properties + + /** + * Whether to enable internal debug messages. + * + * @var bool + * @access private + */ + var $_debug = false; + + /** + * Default error mode for this object. + * + * @var int + * @access private + */ + var $_default_error_mode = null; + + /** + * Default error options used for this object when error mode + * is PEAR_ERROR_TRIGGER. + * + * @var int + * @access private + */ + var $_default_error_options = null; + + /** + * Default error handler (callback) for this object, if error mode is + * PEAR_ERROR_CALLBACK. + * + * @var string + * @access private + */ + var $_default_error_handler = ''; + + /** + * Which class to use for error objects. + * + * @var string + * @access private + */ + var $_error_class = 'PEAR_Error'; + + /** + * An array of expected errors. + * + * @var array + * @access private + */ + var $_expected_errors = array(); + + // }}} + + // {{{ constructor + + /** + * Constructor. Registers this object in + * $_PEAR_destructor_object_list for destructor emulation if a + * destructor object exists. + * + * @param string $error_class (optional) which class to use for + * error objects, defaults to PEAR_Error. + * @access public + * @return void + */ + function PEAR($error_class = null) + { + $classname = strtolower(get_class($this)); + if ($this->_debug) { + print "PEAR constructor called, class=$classname\n"; + } + if ($error_class !== null) { + $this->_error_class = $error_class; + } + while ($classname && strcasecmp($classname, "pear")) { + $destructor = "_$classname"; + if (method_exists($this, $destructor)) { + global $_PEAR_destructor_object_list; + $_PEAR_destructor_object_list[] = &$this; + if (!isset($GLOBALS['_PEAR_SHUTDOWN_REGISTERED'])) { + register_shutdown_function("_PEAR_call_destructors"); + $GLOBALS['_PEAR_SHUTDOWN_REGISTERED'] = true; + } + break; + } else { + $classname = get_parent_class($classname); + } + } + } + + // }}} + // {{{ destructor + + /** + * Destructor (the emulated type of...). Does nothing right now, + * but is included for forward compatibility, so subclass + * destructors should always call it. + * + * See the note in the class desciption about output from + * destructors. + * + * @access public + * @return void + */ + function _PEAR() { + if ($this->_debug) { + printf("PEAR destructor called, class=%s\n", strtolower(get_class($this))); + } + } + + // }}} + // {{{ getStaticProperty() + + /** + * If you have a class that's mostly/entirely static, and you need static + * properties, you can use this method to simulate them. Eg. in your method(s) + * do this: $myVar = &PEAR::getStaticProperty('myclass', 'myVar'); + * You MUST use a reference, or they will not persist! + * + * @access public + * @param string $class The calling classname, to prevent clashes + * @param string $var The variable to retrieve. + * @return mixed A reference to the variable. If not set it will be + * auto initialised to NULL. + */ + function &getStaticProperty($class, $var) + { + static $properties; + if (!isset($properties[$class])) { + $properties[$class] = array(); + } + if (!array_key_exists($var, $properties[$class])) { + $properties[$class][$var] = null; + } + return $properties[$class][$var]; + } + + // }}} + // {{{ registerShutdownFunc() + + /** + * Use this function to register a shutdown method for static + * classes. + * + * @access public + * @param mixed $func The function name (or array of class/method) to call + * @param mixed $args The arguments to pass to the function + * @return void + */ + function registerShutdownFunc($func, $args = array()) + { + // if we are called statically, there is a potential + // that no shutdown func is registered. Bug #6445 + if (!isset($GLOBALS['_PEAR_SHUTDOWN_REGISTERED'])) { + register_shutdown_function("_PEAR_call_destructors"); + $GLOBALS['_PEAR_SHUTDOWN_REGISTERED'] = true; + } + $GLOBALS['_PEAR_shutdown_funcs'][] = array($func, $args); + } + + // }}} + // {{{ isError() + + /** + * Tell whether a value is a PEAR error. + * + * @param mixed $data the value to test + * @param int $code if $data is an error object, return true + * only if $code is a string and + * $obj->getMessage() == $code or + * $code is an integer and $obj->getCode() == $code + * @access public + * @return bool true if parameter is an error + */ + function isError($data, $code = null) + { + if (is_a($data, 'PEAR_Error')) { + if (is_null($code)) { + return true; + } elseif (is_string($code)) { + return $data->getMessage() == $code; + } else { + return $data->getCode() == $code; + } + } + return false; + } + + // }}} + // {{{ setErrorHandling() + + /** + * Sets how errors generated by this object should be handled. + * Can be invoked both in objects and statically. If called + * statically, setErrorHandling sets the default behaviour for all + * PEAR objects. If called in an object, setErrorHandling sets + * the default behaviour for that object. + * + * @param int $mode + * One of PEAR_ERROR_RETURN, PEAR_ERROR_PRINT, + * PEAR_ERROR_TRIGGER, PEAR_ERROR_DIE, + * PEAR_ERROR_CALLBACK or PEAR_ERROR_EXCEPTION. + * + * @param mixed $options + * When $mode is PEAR_ERROR_TRIGGER, this is the error level (one + * of E_USER_NOTICE, E_USER_WARNING or E_USER_ERROR). + * + * When $mode is PEAR_ERROR_CALLBACK, this parameter is expected + * to be the callback function or method. A callback + * function is a string with the name of the function, a + * callback method is an array of two elements: the element + * at index 0 is the object, and the element at index 1 is + * the name of the method to call in the object. + * + * When $mode is PEAR_ERROR_PRINT or PEAR_ERROR_DIE, this is + * a printf format string used when printing the error + * message. + * + * @access public + * @return void + * @see PEAR_ERROR_RETURN + * @see PEAR_ERROR_PRINT + * @see PEAR_ERROR_TRIGGER + * @see PEAR_ERROR_DIE + * @see PEAR_ERROR_CALLBACK + * @see PEAR_ERROR_EXCEPTION + * + * @since PHP 4.0.5 + */ + + function setErrorHandling($mode = null, $options = null) + { + if (isset($this) && is_a($this, 'PEAR')) { + $setmode = &$this->_default_error_mode; + $setoptions = &$this->_default_error_options; + } else { + $setmode = &$GLOBALS['_PEAR_default_error_mode']; + $setoptions = &$GLOBALS['_PEAR_default_error_options']; + } + + switch ($mode) { + case PEAR_ERROR_EXCEPTION: + case PEAR_ERROR_RETURN: + case PEAR_ERROR_PRINT: + case PEAR_ERROR_TRIGGER: + case PEAR_ERROR_DIE: + case null: + $setmode = $mode; + $setoptions = $options; + break; + + case PEAR_ERROR_CALLBACK: + $setmode = $mode; + // class/object method callback + if (is_callable($options)) { + $setoptions = $options; + } else { + trigger_error("invalid error callback", E_USER_WARNING); + } + break; + + default: + trigger_error("invalid error mode", E_USER_WARNING); + break; + } + } + + // }}} + // {{{ expectError() + + /** + * This method is used to tell which errors you expect to get. + * Expected errors are always returned with error mode + * PEAR_ERROR_RETURN. Expected error codes are stored in a stack, + * and this method pushes a new element onto it. The list of + * expected errors are in effect until they are popped off the + * stack with the popExpect() method. + * + * Note that this method can not be called statically + * + * @param mixed $code a single error code or an array of error codes to expect + * + * @return int the new depth of the "expected errors" stack + * @access public + */ + function expectError($code = '*') + { + if (is_array($code)) { + array_push($this->_expected_errors, $code); + } else { + array_push($this->_expected_errors, array($code)); + } + return sizeof($this->_expected_errors); + } + + // }}} + // {{{ popExpect() + + /** + * This method pops one element off the expected error codes + * stack. + * + * @return array the list of error codes that were popped + */ + function popExpect() + { + return array_pop($this->_expected_errors); + } + + // }}} + // {{{ _checkDelExpect() + + /** + * This method checks unsets an error code if available + * + * @param mixed error code + * @return bool true if the error code was unset, false otherwise + * @access private + * @since PHP 4.3.0 + */ + function _checkDelExpect($error_code) + { + $deleted = false; + + foreach ($this->_expected_errors AS $key => $error_array) { + if (in_array($error_code, $error_array)) { + unset($this->_expected_errors[$key][array_search($error_code, $error_array)]); + $deleted = true; + } + + // clean up empty arrays + if (0 == count($this->_expected_errors[$key])) { + unset($this->_expected_errors[$key]); + } + } + return $deleted; + } + + // }}} + // {{{ delExpect() + + /** + * This method deletes all occurences of the specified element from + * the expected error codes stack. + * + * @param mixed $error_code error code that should be deleted + * @return mixed list of error codes that were deleted or error + * @access public + * @since PHP 4.3.0 + */ + function delExpect($error_code) + { + $deleted = false; + + if ((is_array($error_code) && (0 != count($error_code)))) { + // $error_code is a non-empty array here; + // we walk through it trying to unset all + // values + foreach($error_code as $key => $error) { + if ($this->_checkDelExpect($error)) { + $deleted = true; + } else { + $deleted = false; + } + } + return $deleted ? true : PEAR::raiseError("The expected error you submitted does not exist"); // IMPROVE ME + } elseif (!empty($error_code)) { + // $error_code comes alone, trying to unset it + if ($this->_checkDelExpect($error_code)) { + return true; + } else { + return PEAR::raiseError("The expected error you submitted does not exist"); // IMPROVE ME + } + } else { + // $error_code is empty + return PEAR::raiseError("The expected error you submitted is empty"); // IMPROVE ME + } + } + + // }}} + // {{{ raiseError() + + /** + * This method is a wrapper that returns an instance of the + * configured error class with this object's default error + * handling applied. If the $mode and $options parameters are not + * specified, the object's defaults are used. + * + * @param mixed $message a text error message or a PEAR error object + * + * @param int $code a numeric error code (it is up to your class + * to define these if you want to use codes) + * + * @param int $mode One of PEAR_ERROR_RETURN, PEAR_ERROR_PRINT, + * PEAR_ERROR_TRIGGER, PEAR_ERROR_DIE, + * PEAR_ERROR_CALLBACK, PEAR_ERROR_EXCEPTION. + * + * @param mixed $options If $mode is PEAR_ERROR_TRIGGER, this parameter + * specifies the PHP-internal error level (one of + * E_USER_NOTICE, E_USER_WARNING or E_USER_ERROR). + * If $mode is PEAR_ERROR_CALLBACK, this + * parameter specifies the callback function or + * method. In other error modes this parameter + * is ignored. + * + * @param string $userinfo If you need to pass along for example debug + * information, this parameter is meant for that. + * + * @param string $error_class The returned error object will be + * instantiated from this class, if specified. + * + * @param bool $skipmsg If true, raiseError will only pass error codes, + * the error message parameter will be dropped. + * + * @access public + * @return object a PEAR error object + * @see PEAR::setErrorHandling + * @since PHP 4.0.5 + */ + function &raiseError($message = null, + $code = null, + $mode = null, + $options = null, + $userinfo = null, + $error_class = null, + $skipmsg = false) + { + // The error is yet a PEAR error object + if (is_object($message)) { + $code = $message->getCode(); + $userinfo = $message->getUserInfo(); + $error_class = $message->getType(); + $message->error_message_prefix = ''; + $message = $message->getMessage(); + } + + if (isset($this) && isset($this->_expected_errors) && sizeof($this->_expected_errors) > 0 && sizeof($exp = end($this->_expected_errors))) { + if ($exp[0] == "*" || + (is_int(reset($exp)) && in_array($code, $exp)) || + (is_string(reset($exp)) && in_array($message, $exp))) { + $mode = PEAR_ERROR_RETURN; + } + } + // No mode given, try global ones + if ($mode === null) { + // Class error handler + if (isset($this) && isset($this->_default_error_mode)) { + $mode = $this->_default_error_mode; + $options = $this->_default_error_options; + // Global error handler + } elseif (isset($GLOBALS['_PEAR_default_error_mode'])) { + $mode = $GLOBALS['_PEAR_default_error_mode']; + $options = $GLOBALS['_PEAR_default_error_options']; + } + } + + if ($error_class !== null) { + $ec = $error_class; + } elseif (isset($this) && isset($this->_error_class)) { + $ec = $this->_error_class; + } else { + $ec = 'PEAR_Error'; + } + if ($skipmsg) { + $a = &new $ec($code, $mode, $options, $userinfo); + return $a; + } else { + $a = &new $ec($message, $code, $mode, $options, $userinfo); + return $a; + } + } + + // }}} + // {{{ throwError() + + /** + * Simpler form of raiseError with fewer options. In most cases + * message, code and userinfo are enough. + * + * @param string $message + * + */ + function &throwError($message = null, + $code = null, + $userinfo = null) + { + if (isset($this) && is_a($this, 'PEAR')) { + $a = &$this->raiseError($message, $code, null, null, $userinfo); + return $a; + } else { + $a = &PEAR::raiseError($message, $code, null, null, $userinfo); + return $a; + } + } + + // }}} + function staticPushErrorHandling($mode, $options = null) + { + $stack = &$GLOBALS['_PEAR_error_handler_stack']; + $def_mode = &$GLOBALS['_PEAR_default_error_mode']; + $def_options = &$GLOBALS['_PEAR_default_error_options']; + $stack[] = array($def_mode, $def_options); + switch ($mode) { + case PEAR_ERROR_EXCEPTION: + case PEAR_ERROR_RETURN: + case PEAR_ERROR_PRINT: + case PEAR_ERROR_TRIGGER: + case PEAR_ERROR_DIE: + case null: + $def_mode = $mode; + $def_options = $options; + break; + + case PEAR_ERROR_CALLBACK: + $def_mode = $mode; + // class/object method callback + if (is_callable($options)) { + $def_options = $options; + } else { + trigger_error("invalid error callback", E_USER_WARNING); + } + break; + + default: + trigger_error("invalid error mode", E_USER_WARNING); + break; + } + $stack[] = array($mode, $options); + return true; + } + + function staticPopErrorHandling() + { + $stack = &$GLOBALS['_PEAR_error_handler_stack']; + $setmode = &$GLOBALS['_PEAR_default_error_mode']; + $setoptions = &$GLOBALS['_PEAR_default_error_options']; + array_pop($stack); + list($mode, $options) = $stack[sizeof($stack) - 1]; + array_pop($stack); + switch ($mode) { + case PEAR_ERROR_EXCEPTION: + case PEAR_ERROR_RETURN: + case PEAR_ERROR_PRINT: + case PEAR_ERROR_TRIGGER: + case PEAR_ERROR_DIE: + case null: + $setmode = $mode; + $setoptions = $options; + break; + + case PEAR_ERROR_CALLBACK: + $setmode = $mode; + // class/object method callback + if (is_callable($options)) { + $setoptions = $options; + } else { + trigger_error("invalid error callback", E_USER_WARNING); + } + break; + + default: + trigger_error("invalid error mode", E_USER_WARNING); + break; + } + return true; + } + + // {{{ pushErrorHandling() + + /** + * Push a new error handler on top of the error handler options stack. With this + * you can easily override the actual error handler for some code and restore + * it later with popErrorHandling. + * + * @param mixed $mode (same as setErrorHandling) + * @param mixed $options (same as setErrorHandling) + * + * @return bool Always true + * + * @see PEAR::setErrorHandling + */ + function pushErrorHandling($mode, $options = null) + { + $stack = &$GLOBALS['_PEAR_error_handler_stack']; + if (isset($this) && is_a($this, 'PEAR')) { + $def_mode = &$this->_default_error_mode; + $def_options = &$this->_default_error_options; + } else { + $def_mode = &$GLOBALS['_PEAR_default_error_mode']; + $def_options = &$GLOBALS['_PEAR_default_error_options']; + } + $stack[] = array($def_mode, $def_options); + + if (isset($this) && is_a($this, 'PEAR')) { + $this->setErrorHandling($mode, $options); + } else { + PEAR::setErrorHandling($mode, $options); + } + $stack[] = array($mode, $options); + return true; + } + + // }}} + // {{{ popErrorHandling() + + /** + * Pop the last error handler used + * + * @return bool Always true + * + * @see PEAR::pushErrorHandling + */ + function popErrorHandling() + { + $stack = &$GLOBALS['_PEAR_error_handler_stack']; + array_pop($stack); + list($mode, $options) = $stack[sizeof($stack) - 1]; + array_pop($stack); + if (isset($this) && is_a($this, 'PEAR')) { + $this->setErrorHandling($mode, $options); + } else { + PEAR::setErrorHandling($mode, $options); + } + return true; + } + + // }}} + // {{{ loadExtension() + + /** + * OS independant PHP extension load. Remember to take care + * on the correct extension name for case sensitive OSes. + * + * @param string $ext The extension name + * @return bool Success or not on the dl() call + */ + function loadExtension($ext) + { + if (!extension_loaded($ext)) { + // if either returns true dl() will produce a FATAL error, stop that + if ((ini_get('enable_dl') != 1) || (ini_get('safe_mode') == 1)) { + return false; + } + if (OS_WINDOWS) { + $suffix = '.dll'; + } elseif (PHP_OS == 'HP-UX') { + $suffix = '.sl'; + } elseif (PHP_OS == 'AIX') { + $suffix = '.a'; + } elseif (PHP_OS == 'OSX') { + $suffix = '.bundle'; + } else { + $suffix = '.so'; + } + return @dl('php_'.$ext.$suffix) || @dl($ext.$suffix); + } + return true; + } + + // }}} +} + +// {{{ _PEAR_call_destructors() + +function _PEAR_call_destructors() +{ + global $_PEAR_destructor_object_list; + if (is_array($_PEAR_destructor_object_list) && + sizeof($_PEAR_destructor_object_list)) + { + reset($_PEAR_destructor_object_list); + if (PEAR::getStaticProperty('PEAR', 'destructlifo')) { + $_PEAR_destructor_object_list = array_reverse($_PEAR_destructor_object_list); + } + while (list($k, $objref) = each($_PEAR_destructor_object_list)) { + $classname = get_class($objref); + while ($classname) { + $destructor = "_$classname"; + if (method_exists($objref, $destructor)) { + $objref->$destructor(); + break; + } else { + $classname = get_parent_class($classname); + } + } + } + // Empty the object list to ensure that destructors are + // not called more than once. + $_PEAR_destructor_object_list = array(); + } + + // Now call the shutdown functions + if (is_array($GLOBALS['_PEAR_shutdown_funcs']) AND !empty($GLOBALS['_PEAR_shutdown_funcs'])) { + foreach ($GLOBALS['_PEAR_shutdown_funcs'] as $value) { + call_user_func_array($value[0], $value[1]); + } + } +} + +// }}} +/** + * Standard PEAR error class for PHP 4 + * + * This class is supserseded by {@link PEAR_Exception} in PHP 5 + * + * @category pear + * @package PEAR + * @author Stig Bakken + * @author Tomas V.V. Cox + * @author Gregory Beaver + * @copyright 1997-2006 The PHP Group + * @license http://www.php.net/license/3_0.txt PHP License 3.0 + * @version Release: 1.6.2 + * @link http://pear.php.net/manual/en/core.pear.pear-error.php + * @see PEAR::raiseError(), PEAR::throwError() + * @since Class available since PHP 4.0.2 + */ +class PEAR_Error +{ + // {{{ properties + + var $error_message_prefix = ''; + var $mode = PEAR_ERROR_RETURN; + var $level = E_USER_NOTICE; + var $code = -1; + var $message = ''; + var $userinfo = ''; + var $backtrace = null; + + // }}} + // {{{ constructor + + /** + * PEAR_Error constructor + * + * @param string $message message + * + * @param int $code (optional) error code + * + * @param int $mode (optional) error mode, one of: PEAR_ERROR_RETURN, + * PEAR_ERROR_PRINT, PEAR_ERROR_DIE, PEAR_ERROR_TRIGGER, + * PEAR_ERROR_CALLBACK or PEAR_ERROR_EXCEPTION + * + * @param mixed $options (optional) error level, _OR_ in the case of + * PEAR_ERROR_CALLBACK, the callback function or object/method + * tuple. + * + * @param string $userinfo (optional) additional user/debug info + * + * @access public + * + */ + function PEAR_Error($message = 'unknown error', $code = null, + $mode = null, $options = null, $userinfo = null) + { + if ($mode === null) { + $mode = PEAR_ERROR_RETURN; + } + $this->message = $message; + $this->code = $code; + $this->mode = $mode; + $this->userinfo = $userinfo; + if (!PEAR::getStaticProperty('PEAR_Error', 'skiptrace')) { + $this->backtrace = debug_backtrace(); + if (isset($this->backtrace[0]) && isset($this->backtrace[0]['object'])) { + unset($this->backtrace[0]['object']); + } + } + if ($mode & PEAR_ERROR_CALLBACK) { + $this->level = E_USER_NOTICE; + $this->callback = $options; + } else { + if ($options === null) { + $options = E_USER_NOTICE; + } + $this->level = $options; + $this->callback = null; + } + if ($this->mode & PEAR_ERROR_PRINT) { + if (is_null($options) || is_int($options)) { + $format = "%s"; + } else { + $format = $options; + } + printf($format, $this->getMessage()); + } + if ($this->mode & PEAR_ERROR_TRIGGER) { + trigger_error($this->getMessage(), $this->level); + } + if ($this->mode & PEAR_ERROR_DIE) { + $msg = $this->getMessage(); + if (is_null($options) || is_int($options)) { + $format = "%s"; + if (substr($msg, -1) != "\n") { + $msg .= "\n"; + } + } else { + $format = $options; + } + die(sprintf($format, $msg)); + } + if ($this->mode & PEAR_ERROR_CALLBACK) { + if (is_callable($this->callback)) { + call_user_func($this->callback, $this); + } + } + if ($this->mode & PEAR_ERROR_EXCEPTION) { + trigger_error("PEAR_ERROR_EXCEPTION is obsolete, use class PEAR_Exception for exceptions", E_USER_WARNING); + eval('$e = new Exception($this->message, $this->code);throw($e);'); + } + } + + // }}} + // {{{ getMode() + + /** + * Get the error mode from an error object. + * + * @return int error mode + * @access public + */ + function getMode() { + return $this->mode; + } + + // }}} + // {{{ getCallback() + + /** + * Get the callback function/method from an error object. + * + * @return mixed callback function or object/method array + * @access public + */ + function getCallback() { + return $this->callback; + } + + // }}} + // {{{ getMessage() + + + /** + * Get the error message from an error object. + * + * @return string full error message + * @access public + */ + function getMessage() + { + return ($this->error_message_prefix . $this->message); + } + + + // }}} + // {{{ getCode() + + /** + * Get error code from an error object + * + * @return int error code + * @access public + */ + function getCode() + { + return $this->code; + } + + // }}} + // {{{ getType() + + /** + * Get the name of this error/exception. + * + * @return string error/exception name (type) + * @access public + */ + function getType() + { + return get_class($this); + } + + // }}} + // {{{ getUserInfo() + + /** + * Get additional user-supplied information. + * + * @return string user-supplied information + * @access public + */ + function getUserInfo() + { + return $this->userinfo; + } + + // }}} + // {{{ getDebugInfo() + + /** + * Get additional debug information supplied by the application. + * + * @return string debug information + * @access public + */ + function getDebugInfo() + { + return $this->getUserInfo(); + } + + // }}} + // {{{ getBacktrace() + + /** + * Get the call backtrace from where the error was generated. + * Supported with PHP 4.3.0 or newer. + * + * @param int $frame (optional) what frame to fetch + * @return array Backtrace, or NULL if not available. + * @access public + */ + function getBacktrace($frame = null) + { + if (defined('PEAR_IGNORE_BACKTRACE')) { + return null; + } + if ($frame === null) { + return $this->backtrace; + } + return $this->backtrace[$frame]; + } + + // }}} + // {{{ addUserInfo() + + function addUserInfo($info) + { + if (empty($this->userinfo)) { + $this->userinfo = $info; + } else { + $this->userinfo .= " ** $info"; + } + } + + // }}} + // {{{ toString() + + /** + * Make a string representation of this object. + * + * @return string a string with an object summary + * @access public + */ + function toString() { + $modes = array(); + $levels = array(E_USER_NOTICE => 'notice', + E_USER_WARNING => 'warning', + E_USER_ERROR => 'error'); + if ($this->mode & PEAR_ERROR_CALLBACK) { + if (is_array($this->callback)) { + $callback = (is_object($this->callback[0]) ? + strtolower(get_class($this->callback[0])) : + $this->callback[0]) . '::' . + $this->callback[1]; + } else { + $callback = $this->callback; + } + return sprintf('[%s: message="%s" code=%d mode=callback '. + 'callback=%s prefix="%s" info="%s"]', + strtolower(get_class($this)), $this->message, $this->code, + $callback, $this->error_message_prefix, + $this->userinfo); + } + if ($this->mode & PEAR_ERROR_PRINT) { + $modes[] = 'print'; + } + if ($this->mode & PEAR_ERROR_TRIGGER) { + $modes[] = 'trigger'; + } + if ($this->mode & PEAR_ERROR_DIE) { + $modes[] = 'die'; + } + if ($this->mode & PEAR_ERROR_RETURN) { + $modes[] = 'return'; + } + return sprintf('[%s: message="%s" code=%d mode=%s level=%s '. + 'prefix="%s" info="%s"]', + strtolower(get_class($this)), $this->message, $this->code, + implode("|", $modes), $levels[$this->level], + $this->error_message_prefix, + $this->userinfo); + } + + // }}} +} + +/* + * Local Variables: + * mode: php + * tab-width: 4 + * c-basic-offset: 4 + * End: + */ +?> diff --git a/events/phpFlickr/README.txt b/events/phpFlickr/README.txt new file mode 100644 index 0000000..568756b --- /dev/null +++ b/events/phpFlickr/README.txt @@ -0,0 +1,215 @@ +phpFlickr Class 2.3.0.1 +Written by Dan Coulter (dancoulter@users.sourceforge.net) +Project Homepage: http://www.phpflickr.com/ +Google Code Project Page: http://code.google.com/p/phpflickr/ +Released under GNU Lesser General Public License (http://www.gnu.org/copyleft/lgpl.html) +For more information about the class and upcoming tools and applications using it, +visit http://www.phpflickr.com/ or http://code.google.com/p/phpflickr/ + +If you are interested in hiring me for a project (involving phpFlickr +or not), feel free to email me. + +Installation instructions: +1. Copy the files from the installation package into a folder on your + server. They need to be readible by your web server. You can put + them into an include folder defined in your php.ini file, if you + like, though it's not required. + +2. All you have to do now is include the file in your PHP scripts and + create an instance. For example: + $f = new phpFlickr(); + + The constructor has three arguments: + A. $api_key - This is the API key given to you by flickr.com. This + argument is required and you can get an API Key at: + http://www.flickr.com/services/api/key.gne + + B. $secret - The "secret" is optional because is not required to + make unauthenticated calls, but is absolutely required for the + new authentication API (see Authentication section below). You + will get one assigned alongside your api key. + + C. $die_on_error - This takes a boolean value and determines + whether the class will die (aka cease operation) if the API + returns an error statement. It defaults to false. Every method + will return false if the API returns an error. You can access + error messages using the getErrorCode() and getErrorMsg() + methods. + +3. All of the API methods have been implemented in my class. You can + see a full list and documentation here: + http://www.flickr.com/services/api/ + To call a method, remove the "flickr." part of the name and replace + any periods with underscores. For example, instead of + flickr.photos.search, you would call $f->photos_search() or instead + of flickr.photos.licenses.getInfo, you would call + $f->photos_licenses_getInfo() (yes, it is case sensitive). + + All functions have their arguments implemented in the list order on + their documentation page (a link to which is included with each + method in the phpFlickr clasS). The only exceptions to this are + photos_search(), photos_getWithoutGeodata() and + photos_getWithoutGeodata() which have so many optional arguments + that it's easier for everyone if you just have to pass an + associative array of arguments. See the comment in the + photos_search() definition in phpFlickr.php for more information. + + + +Authentication: + As of this release of the phpFlickr class there is only one authentication method + available to the API. This method is somewhat complex, but is far more secure and + allows your users to feel a little safer authenticating to your application. You'll + no longer have to ask for their username and password. + + Authentication API - http://www.flickr.com/services/api/auth.spec.html + + I know how complicated this API looks at first glance, so I've tried to + make this as transparent to the coding process. I'll go through the steps + you'll need to use this. Both the auth.php and getToken.php file will + need your API Key and Secret entered before you can use them. + + To have end users authenticate their accounts: + First, setup a callback script. I've included a callback script that + is pretty flexible. You'll find it in the package entitled "auth.php". + You'll need to go to flickr and point your api key to this file as the + callback script. Once you've done this, on any page that you want to + require the end user end user to authenticate their flickr account to + your app, just call the phpFlickr::auth() function with whatever + permission you need to use. + For example: + $f->auth("write"); + The three permissions are "read", "write" and "delete". The function + defaults to "read", if you leave it blank. + + Calling this function will send the user's browser to Flickr's page to + authenticate to your app. Once they have logged in, it will bounce + them back to your callback script which will redirect back to the + original page that you called the auth() function from after setting + a session variable to save their authentication token. If that session + variable exists, calling the auth() function will return the permissions + that the user granted your app on the Flickr page instead of redirecting + to an external page. + + To authenticate the app to your account to show your private pictures (for example) + This method will allow you to have the app authenticate to one specific + account, no matter who views your website. This is useful to display + private photos or photosets (among other things). + + *Note*: The method below is a little hard to understand, so I've setup a tool + to help you through this: http://www.phpflickr.com/tools/auth/. + + First, you'll have to setup a callback script with Flickr. Once you've + done that, edit line 12 of the included getToken.php file to reflect + which permissions you'll need for the app. Then browse to the page. + Once you've authorized the app with Flickr, it'll send you back to that + page which will give you a token which will look something like this: + 1234-567890abcdef1234 + Go to the file where you are creating an instance of phpFlickr (I suggest + an include file) and after you've created it set the token to use: + $f->setToken(""); + This token never expires, so you don't have to worry about having to + login periodically. + + +Using Caching: + Caching can be very important to a project. Just a few calls to the Flickr API + can take long enough to bore your average web user (depending on the calls you + are making). I've built in caching that will access either a database or files + in your filesystem. To enable caching, use the phpFlickr::enableCache() function. + This function requires at least two arguments. The first will be the type of + cache you're using (either "db" or "fs") + + 1. If you're using database caching, you'll need to supply a PEAR::DB connection + string. For example: + $flickr->enableCache("db", "mysql://user:password@server/database"); + The third (optional) argument is expiration of the cache in seconds (defaults + to 600). The fourth (optional) argument is the table where you want to store + the cache. This defaults to flickr_cache and will attempt to create the table + if it does not already exist. + + 2. If you're using filesystem caching, you'll need to supply a folder where the + web server has write access. For example: + $flickr->enableCache("fs", "/var/www/phpFlickrCache"); + The third (optional) argument is, the same as in the Database caching, an + expiration in seconds for the cache. + Note: filesystem caching will probably be slower than database caching. I + haven't done any tests of this, but if you get large amounts of calls, the + process of cleaning out old calls may get hard on your server. + + You may not want to allow the world to view the files that are created during + caching. If you want to hide this information, either make sure that your + permissions are set correctly, or disable the webserver from displaying + *.cache files. In Apache, you can specify this in the configuration files + or in a .htaccess file with the following directives: + + + Deny from all + + + Alternatively, you can specify a directory that is outside of the web server's + document root. + +Uploading + Uploading is pretty simple. Aside from being authenticated (see Authentication + section) the very minimum that you'll have to pass is a path to an image file on + your php server. You can do either synchronous or asynchronous uploading as follows: + synchronous: sync_upload("photo.jpg"); + asynchronous: async_upload("photo.jpg"); + + The basic difference is that synchronous uploading waits around until Flickr + processes the photo and returns a PhotoID. Asynchronous just uploads the + picture and gets a "ticketid" that you can use to check on the status of your + upload. Asynchronous is much faster, though the photoid won't be instantly + available for you. You can read more about asynchronous uploading here: + http://www.flickr.com/services/api/upload.async.html + + Both of the functions take the same arguments which are: + Photo: The path of the file to upload. + Title: The title of the photo. + Description: A description of the photo. May contain some limited HTML. + Tags: A space-separated list of tags to apply to the photo. + is_public: Set to 0 for no, 1 for yes. + is_friend: Set to 0 for no, 1 for yes. + is_family: Set to 0 for no, 1 for yes. + +Replacing Photos + Flickr has released API support for uploading a replacement photo. To use this + new method, just use the "replace" function in phpFlickr. You'll be required + to pass the file name and Flickr's photo ID. You need to authenticate your script + with "write" permissions before you can replace a photo. The arguments are: + Photo: The path of the file to upload. + Photo ID: The numeric Flickr ID of the photo you want to replace. + Async (optional): Set to 0 for a synchronous call, 1 for asynchronous. + If you use the asynchronous call, it will return a ticketid instead + of photoid. + +Other Notes: + 1. Many of the methods have optional arguments. For these, I have implemented + them in the same order that the Flickr API documentation lists them. PHP + allows for optional arguments in function calls, but if you want to use the + third optional argument, you have to fill in the others to the left first. + You can use the "NULL" value (without quotes) in the place of an actual + argument. For example: + $f->groups_pools_getPhotos($group_id, NULL, NULL, 10); + This will get the first ten photos from a specific group's pool. If you look + at the documentation, you will see that there is another argument, "page". I've + left it off because it appears after "per_page". + 2. Some people will need to ues phpFlickr from behind a proxy server. I've + implemented a method that will allow you to use an HTTP proxy for all of your + traffic. Let's say that you have a proxy server on your local server running + at port 8181. This is the code you would use: + $f = new phpFlickr("[api key]"); + $f->setProxy("localhost", "8181"); + After that, all of your calls will be automatically made through your proxy server. + + +That's it! Enjoy the class. Check out the project page (listed above) for updates +and news. I plan to implement file uploads and functions to aggregate data from +several different methods for easier use in a web application. Thanks for your +interest in this project! + + Please email me if you have any questions or problems. You'll find my email + at the top of this file. + + diff --git a/events/phpFlickr/auth.php b/events/phpFlickr/auth.php new file mode 100644 index 0000000..9582dc4 --- /dev/null +++ b/events/phpFlickr/auth.php @@ -0,0 +1,37 @@ +auth($permissions, false); + } else { + $f->auth_getToken($_GET['frob']); + } + + if (empty($redirect)) { + header("Location: " . $default_redirect); + } else { + header("Location: " . $redirect); + } + +?> \ No newline at end of file diff --git a/events/phpFlickr/example.php b/events/phpFlickr/example.php new file mode 100644 index 0000000..673a87e --- /dev/null +++ b/events/phpFlickr/example.php @@ -0,0 +1,30 @@ +" with one provided + * by Flickr: http://www.flickr.com/services/api/key.gne + */ + +require_once("phpFlickr.php"); +$f = new phpFlickr(""); + +$recent = $f->photos_getRecent(); + +foreach ($recent['photo'] as $photo) { + $owner = $f->people_getInfo($photo['owner']); + echo ""; + echo $photo['title']; + echo " Owner: "; + echo ""; + echo $owner['username']; + echo "
"; +} +?> diff --git a/events/phpFlickr/getToken.php b/events/phpFlickr/getToken.php new file mode 100644 index 0000000..1d232e4 --- /dev/null +++ b/events/phpFlickr/getToken.php @@ -0,0 +1,19 @@ +", ""); + + //change this to the permissions you will need + $f->auth("read"); + + echo "Copy this token into your code: " . $_SESSION['phpFlickr_auth_token']; + +?> \ No newline at end of file diff --git a/events/phpFlickr/phpFlickr.php b/events/phpFlickr/phpFlickr.php new file mode 100644 index 0000000..a50b799 --- /dev/null +++ b/events/phpFlickr/phpFlickr.php @@ -0,0 +1,1386 @@ +api_key = $api_key; + $this->secret = $secret; + $this->die_on_error = $die_on_error; + $this->service = "flickr"; + + //Find the PHP version and store it for future reference + $this->php_version = explode("-", phpversion()); + $this->php_version = explode(".", $this->php_version[0]); + + //All calls to the API are done via the POST method using the PEAR::HTTP_Request package. + require_once 'HTTP/Request.php'; + $this->req =& new HTTP_Request(); + $this->req->setMethod(HTTP_REQUEST_METHOD_POST); + } + + function enableCache ($type, $connection, $cache_expire = 600, $table = 'flickr_cache') { + // Turns on caching. $type must be either "db" (for database caching) or "fs" (for filesystem). + // When using db, $connection must be a PEAR::DB connection string. Example: + // "mysql://user:password@server/database" + // If the $table, doesn't exist, it will attempt to create it. + // When using file system, caching, the $connection is the folder that the web server has write + // access to. Use absolute paths for best results. Relative paths may have unexpected behavior + // when you include this. They'll usually work, you'll just want to test them. + if ($type == 'db') { + require_once 'DB.php'; + $db =& DB::connect($connection); + if (PEAR::isError($db)) { + die($db->getMessage()); + } + + /* + * If high performance is crucial, you can easily comment + * out this query once you've created your database table. + */ + + $db->query(" + CREATE TABLE IF NOT EXISTS `$table` ( + `request` CHAR( 35 ) NOT NULL , + `response` MEDIUMTEXT NOT NULL , + `expiration` DATETIME NOT NULL , + INDEX ( `request` ) + ) TYPE = MYISAM"); + + if ($db->getOne("SELECT COUNT(*) FROM $table") > $this->max_cache_rows) { + $db->query("DELETE FROM $table WHERE expiration < DATE_SUB(NOW(), INTERVAL $cache_expire second)"); + $db->query('OPTIMIZE TABLE ' . $this->cache_table); + } + + $this->cache = 'db'; + $this->cache_db = $db; + $this->cache_table = $table; + } elseif ($type == 'fs') { + $this->cache = 'fs'; + $connection = realpath($connection); + $this->cache_dir = $connection; + if ($dir = opendir($this->cache_dir)) { + while ($file = readdir($dir)) { + if (substr($file, -6) == '.cache' && ((filemtime($this->cache_dir . '/' . $file) + $cache_expire) < time()) ) { + unlink($this->cache_dir . '/' . $file); + } + } + } + } + $this->cache_expire = $cache_expire; + } + + function getCached ($request) { + //Checks the database or filesystem for a cached result to the request. + //If there is no cache result, it returns a value of false. If it finds one, + //it returns the unparsed XML. + $reqhash = md5(serialize($request)); + if ($this->cache == 'db') { + $result = $this->cache_db->getOne("SELECT response FROM " . $this->cache_table . " WHERE request = ? AND DATE_SUB(NOW(), INTERVAL " . (int) $this->cache_expire . " SECOND) < expiration", $reqhash); + if (!empty($result)) { + return $result; + } + } elseif ($this->cache == 'fs') { + $file = $this->cache_dir . '/' . $reqhash . '.cache'; + if (file_exists($file)) { + if ($this->php_version[0] > 4 || ($this->php_version[0] == 4 && $this->php_version[1] >= 3)) { + return file_get_contents($file); + } else { + return implode('', file($file)); + } + } + } + return false; + } + + function cache ($request, $response) { + //Caches the unparsed XML of a request. + $reqhash = md5(serialize($request)); + if ($this->cache == 'db') { + //$this->cache_db->query("DELETE FROM $this->cache_table WHERE request = '$reqhash'"); + if ($this->cache_db->getOne("SELECT COUNT(*) FROM {$this->cache_table} WHERE request = '$reqhash'")) { + $sql = "UPDATE " . $this->cache_table . " SET response = ?, expiration = ? WHERE request = ?"; + $this->cache_db->query($sql, array($response, strftime("%Y-%m-%d %H:%M:%S"), $reqhash)); + } else { + $sql = "INSERT INTO " . $this->cache_table . " (request, response, expiration) VALUES ('$reqhash', '" . str_replace("'", "''", $response) . "', '" . strftime("%Y-%m-%d %H:%M:%S") . "')"; + $this->cache_db->query($sql); + } + } elseif ($this->cache == "fs") { + $file = $this->cache_dir . "/" . $reqhash . ".cache"; + $fstream = fopen($file, "w"); + $result = fwrite($fstream,$response); + fclose($fstream); + return $result; + } + return false; + } + + function request ($command, $args = array(), $nocache = false) { + //Sends a request to Flickr's REST endpoint via POST. + $this->req->setURL($this->REST); + $this->req->clearPostData(); + if (substr($command,0,7) != "flickr.") { + $command = "flickr." . $command; + } + + //Process arguments, including method and login data. + $args = array_merge(array("method" => $command, "format" => "php_serial", "api_key" => $this->api_key), $args); + if (!empty($this->token)) { + $args = array_merge($args, array("auth_token" => $this->token)); + } elseif (!empty($_SESSION['phpFlickr_auth_token'])) { + $args = array_merge($args, array("auth_token" => $_SESSION['phpFlickr_auth_token'])); + } + ksort($args); + $auth_sig = ""; + if (!($this->response = $this->getCached($args)) || $nocache) { + foreach ($args as $key => $data) { + $auth_sig .= $key . $data; + $this->req->addPostData($key, $data); + } + if (!empty($this->secret)) { + $api_sig = md5($this->secret . $auth_sig); + $this->req->addPostData("api_sig", $api_sig); + } + + $this->req->addHeader("Connection", "Keep-Alive"); + + //Send Requests + if ($this->req->sendRequest()) { + $this->response = $this->req->getResponseBody(); + $this->cache($args, $this->response); + } else { + die("There has been a problem sending your command to the server."); + } + } + /* + * Uncomment this line (and comment out the next one) if you're doing large queries + * and you're concerned about time. This will, however, change the structure of + * the result, so be sure that you look at the results. + */ + //$this->parsed_response = unserialize($this->response); + $this->parsed_response = $this->clean_text_nodes(unserialize($this->response)); + if ($this->parsed_response['stat'] == 'fail') { + if ($this->die_on_error) die("The Flickr API returned the following error: #{$this->parsed_response['code']} - {$this->parsed_response['message']}"); + else { + $this->error_code = $this->parsed_response['code']; + $this->error_msg = $this->parsed_response['message']; + $this->parsed_response = false; + } + } else { + $this->error_code = false; + $this->error_msg = false; + } + return $this->response; + } + + function clean_text_nodes ($arr) { + if (!is_array($arr)) { + return $arr; + } elseif (count($arr) == 0) { + return $arr; + } elseif (count($arr) == 1 && array_key_exists('_content', $arr)) { + return $arr['_content']; + } else { + foreach ($arr as $key => $element) { + $arr[$key] = $this->clean_text_nodes($element); + } + return($arr); + } + } + + function setToken ($token) { + // Sets an authentication token to use instead of the session variable + $this->token = $token; + } + + function setProxy ($server, $port) { + // Sets the proxy for all phpFlickr calls. + $this->req->setProxy($server, $port); + } + + function getErrorCode () { + // Returns the error code of the last call. If the last call did not + // return an error. This will return a false boolean. + return $this->error_code; + } + + function getErrorMsg () { + // Returns the error message of the last call. If the last call did not + // return an error. This will return a false boolean. + return $this->error_msg; + } + + /* These functions are front ends for the flickr calls */ + + function buildPhotoURL ($photo, $size = "Medium") { + //receives an array (can use the individual photo data returned + //from an API call) and returns a URL (doesn't mean that the + //file size exists) + $sizes = array( + "square" => "_s", + "thumbnail" => "_t", + "small" => "_m", + "medium" => "", + "large" => "_b", + "original" => "_o" + ); + + $size = strtolower($size); + if (!array_key_exists($size, $sizes)) { + $size = "medium"; + } + + if ($size == "original") { + $url = "http://farm" . $photo['farm'] . ".static.flickr.com/" . $photo['server'] . "/" . $photo['id'] . "_" . $photo['originalsecret'] . "_o" . "." . $photo['originalformat']; + } else { + $url = "http://farm" . $photo['farm'] . ".static.flickr.com/" . $photo['server'] . "/" . $photo['id'] . "_" . $photo['secret'] . $sizes[$size] . ".jpg"; + } + return $url; + } + + function getFriendlyGeodata ($lat, $lon) { + /* I've added this method to get the friendly geodata (i.e. 'in New York, NY') that the + * website provides, but isn't available in the API. I'm providing this service as long + * as it doesn't flood my server with requests and crash it all the time. + */ + return unserialize(file_get_contents('http://phpflickr.com/geodata/?format=php&lat=' . $lat . '&lon=' . $lon)); + } + + function sync_upload ($photo, $title = null, $description = null, $tags = null, $is_public = null, $is_friend = null, $is_family = null) { + $upload_req =& new HTTP_Request(); + $upload_req->setMethod(HTTP_REQUEST_METHOD_POST); + + + $upload_req->setURL($this->Upload); + $upload_req->clearPostData(); + + //Process arguments, including method and login data. + $args = array("api_key" => $this->api_key, "title" => $title, "description" => $description, "tags" => $tags, "is_public" => $is_public, "is_friend" => $is_friend, "is_family" => $is_family); + if (!empty($this->email)) { + $args = array_merge($args, array("email" => $this->email)); + } + if (!empty($this->password)) { + $args = array_merge($args, array("password" => $this->password)); + } + if (!empty($this->token)) { + $args = array_merge($args, array("auth_token" => $this->token)); + } elseif (!empty($_SESSION['phpFlickr_auth_token'])) { + $args = array_merge($args, array("auth_token" => $_SESSION['phpFlickr_auth_token'])); + } + + ksort($args); + $auth_sig = ""; + foreach ($args as $key => $data) { + if ($data !== null) { + $auth_sig .= $key . $data; + $upload_req->addPostData($key, $data); + } + } + if (!empty($this->secret)) { + $api_sig = md5($this->secret . $auth_sig); + $upload_req->addPostData("api_sig", $api_sig); + } + + $photo = realpath($photo); + + $result = $upload_req->addFile("photo", $photo); + + if (PEAR::isError($result)) { + die($result->getMessage()); + } + + //Send Requests + if ($upload_req->sendRequest()) { + $this->response = $upload_req->getResponseBody(); + } else { + die("There has been a problem sending your command to the server."); + } + + $rsp = explode("\n", $this->response); + foreach ($rsp as $line) { + if (ereg('die_on_error) + die("The Flickr API returned the following error: #{$match[1]} - {$match[2]}"); + else { + $this->error_code = $match[1]; + $this->error_msg = $match[2]; + $this->parsed_response = false; + return false; + } + } elseif (ereg("(.*)", $line, $match)) { + $this->error_code = false; + $this->error_msg = false; + return $match[1]; + } + } + } + + function async_upload ($photo, $title = null, $description = null, $tags = null, $is_public = null, $is_friend = null, $is_family = null) { + $upload_req =& new HTTP_Request(); + $upload_req->setMethod(HTTP_REQUEST_METHOD_POST); + + $upload_req->setURL($this->Upload); + $upload_req->clearPostData(); + + //Process arguments, including method and login data. + $args = array("async" => 1, "api_key" => $this->api_key, "title" => $title, "description" => $description, "tags" => $tags, "is_public" => $is_public, "is_friend" => $is_friend, "is_family" => $is_family); + if (!empty($this->email)) { + $args = array_merge($args, array("email" => $this->email)); + } + if (!empty($this->password)) { + $args = array_merge($args, array("password" => $this->password)); + } + if (!empty($this->token)) { + $args = array_merge($args, array("auth_token" => $this->token)); + } elseif (!empty($_SESSION['phpFlickr_auth_token'])) { + $args = array_merge($args, array("auth_token" => $_SESSION['phpFlickr_auth_token'])); + } + + ksort($args); + $auth_sig = ""; + foreach ($args as $key => $data) { + if ($data !== null) { + $auth_sig .= $key . $data; + $upload_req->addPostData($key, $data); + } + } + if (!empty($this->secret)) { + $api_sig = md5($this->secret . $auth_sig); + $upload_req->addPostData("api_sig", $api_sig); + } + + $photo = realpath($photo); + + $result = $upload_req->addFile("photo", $photo); + + if (PEAR::isError($result)) { + die($result->getMessage()); + } + + //Send Requests + if ($upload_req->sendRequest()) { + $this->response = $upload_req->getResponseBody(); + } else { + die("There has been a problem sending your command to the server."); + } + + $rsp = explode("\n", $this->response); + foreach ($rsp as $line) { + if (ereg('die_on_error) + die("The Flickr API returned the following error: #{$match[1]} - {$match[2]}"); + else { + $this->error_code = $match[1]; + $this->error_msg = $match[2]; + $this->parsed_response = false; + return false; + } + } elseif (ereg("(.*)error_code = false; + $this->error_msg = false; + return $match[1]; + } + } + } + + // Interface for new replace API method. + function replace ($photo, $photo_id, $async = null) { + $upload_req =& new HTTP_Request(); + $upload_req->setMethod(HTTP_REQUEST_METHOD_POST); + + $upload_req->setURL($this->Replace); + $upload_req->clearPostData(); + + //Process arguments, including method and login data. + $args = array("api_key" => $this->api_key, "photo_id" => $photo_id, "async" => $async); + if (!empty($this->email)) { + $args = array_merge($args, array("email" => $this->email)); + } + if (!empty($this->password)) { + $args = array_merge($args, array("password" => $this->password)); + } + if (!empty($this->token)) { + $args = array_merge($args, array("auth_token" => $this->token)); + } elseif (!empty($_SESSION['phpFlickr_auth_token'])) { + $args = array_merge($args, array("auth_token" => $_SESSION['phpFlickr_auth_token'])); + } + + ksort($args); + $auth_sig = ""; + foreach ($args as $key => $data) { + if ($data !== null) { + $auth_sig .= $key . $data; + $upload_req->addPostData($key, $data); + } + } + if (!empty($this->secret)) { + $api_sig = md5($this->secret . $auth_sig); + $upload_req->addPostData("api_sig", $api_sig); + } + + $photo = realpath($photo); + + $result = $upload_req->addFile("photo", $photo); + + if (PEAR::isError($result)) { + die($result->getMessage()); + } + + //Send Requests + if ($upload_req->sendRequest()) { + $this->response = $upload_req->getResponseBody(); + } else { + die("There has been a problem sending your command to the server."); + } + if ($async == 1) + $find = 'ticketid'; + else + $find = 'photoid'; + + $rsp = explode("\n", $this->response); + foreach ($rsp as $line) { + if (ereg('die_on_error) + die("The Flickr API returned the following error: #{$match[1]} - {$match[2]}"); + else { + $this->error_code = $match[1]; + $this->error_msg = $match[2]; + $this->parsed_response = false; + return false; + } + } elseif (ereg("<" . $find . ">(.*)error_code = false; + $this->error_msg = false; + return $match[1]; + } + } + } + + function auth ($perms = "read", $remember_uri = true) { + // Redirects to Flickr's authentication piece if there is no valid token. + // If remember_uri is set to false, the callback script (included) will + // redirect to its default page. + + if (empty($_SESSION['phpFlickr_auth_token']) && empty($this->token)) { + if ($remember_uri) { + $redirect = $_SERVER['REQUEST_URI']; + } + $api_sig = md5($this->secret . "api_key" . $this->api_key . "extra" . $redirect . "perms" . $perms); + if ($this->service == "23") { + header("Location: http://www.23hq.com/services/auth/?api_key=" . $this->api_key . "&extra=" . $redirect . "&perms=" . $perms . "&api_sig=". $api_sig); + } else { + header("Location: http://www.flickr.com/services/auth/?api_key=" . $this->api_key . "&extra=" . $redirect . "&perms=" . $perms . "&api_sig=". $api_sig); + } + exit; + } else { + $tmp = $this->die_on_error; + $this->die_on_error = false; + $rsp = $this->auth_checkToken(); + if ($this->error_code !== false) { + unset($_SESSION['phpFlickr_auth_token']); + $this->auth($perms, $remember_uri); + } + $this->die_on_error = $tmp; + return $rsp['perms']; + } + } + + /******************************* + + To use the phpFlickr::call method, pass a string containing the API method you want + to use and an associative array of arguments. For example: + $result = $f->call("flickr.photos.comments.getList", array("photo_id"=>'34952612')); + This method will allow you to make calls to arbitrary methods that haven't been + implemented in phpFlickr yet. + + *******************************/ + + function call ($method, $arguments) { + foreach ( $arguments as $key => $value ) { + if ( is_null($value) ) unset($arguments[$key]); + } + $this->request($method, $arguments); + return $this->parsed_response ? $this->parsed_response : false; + } + + /* + These functions are the direct implementations of flickr calls. + For method documentation, including arguments, visit the address + included in a comment in the function. + */ + + /* Activity methods */ + function activity_userComments ($per_page = NULL, $page = NULL) { + /* http://www.flickr.com/services/api/flickr.activity.userComments.html */ + $this->request('flickr.activity.userComments', array("per_page" => $per_page, "page" => $page)); + return $this->parsed_response ? $this->parsed_response['items']['item'] : false; + } + + function activity_userPhotos ($timeframe = NULL, $per_page = NULL, $page = NULL) { + /* http://www.flickr.com/services/api/flickr.activity.userPhotos.html */ + $this->request('flickr.activity.userPhotos', array("timeframe" => $timeframe, "per_page" => $per_page, "page" => $page)); + return $this->parsed_response ? $this->parsed_response['items']['item'] : false; + } + + /* Authentication methods */ + function auth_checkToken () { + /* http://www.flickr.com/services/api/flickr.auth.checkToken.html */ + $this->request('flickr.auth.checkToken'); + return $this->parsed_response ? $this->parsed_response['auth'] : false; + } + + function auth_getFrob () { + /* http://www.flickr.com/services/api/flickr.auth.getFrob.html */ + $this->request('flickr.auth.getFrob'); + return $this->parsed_response ? $this->parsed_response['frob'] : false; + } + + function auth_getFullToken ($mini_token) { + /* http://www.flickr.com/services/api/flickr.auth.getFullToken.html */ + $this->request('flickr.auth.getFullToken', array('mini_token'=>$mini_token)); + return $this->parsed_response ? $this->parsed_response['auth'] : false; + } + + function auth_getToken ($frob) { + /* http://www.flickr.com/services/api/flickr.auth.getToken.html */ + $this->request('flickr.auth.getToken', array('frob'=>$frob)); + session_register('phpFlickr_auth_token'); + $_SESSION['phpFlickr_auth_token'] = $this->parsed_response['auth']['token']; + return $this->parsed_response ? $this->parsed_response['auth'] : false; + } + + /* Blogs methods */ + function blogs_getList () { + /* http://www.flickr.com/services/api/flickr.blogs.getList.html */ + $this->request('flickr.blogs.getList'); + return $this->parsed_response ? $this->parsed_response['blogs']['blog'] : false; + } + + function blogs_postPhoto ($blog_id, $photo_id, $title, $description, $blog_password = NULL) { + /* http://www.flickr.com/services/api/flickr.blogs.postPhoto.html */ + $this->request('flickr.blogs.postPhoto', array('blog_id'=>$blog_id, 'photo_id'=>$photo_id, 'title'=>$title, 'description'=>$description, 'blog_password'=>$blog_password), TRUE); + return $this->parsed_response ? true : false; + } + + /* Contacts Methods */ + function contacts_getList ($filter = NULL, $page = NULL, $per_page = NULL) { + /* http://www.flickr.com/services/api/flickr.contacts.getList.html */ + $this->request('flickr.contacts.getList', array('filter'=>$filter, 'page'=>$page, 'per_page'=>$per_page)); + return $this->parsed_response ? $this->parsed_response['contacts'] : false; + } + + function contacts_getPublicList ($user_id, $page = NULL, $per_page = NULL) { + /* http://www.flickr.com/services/api/flickr.contacts.getPublicList.html */ + $this->request('flickr.contacts.getPublicList', array('user_id'=>$user_id, 'page'=>$page, 'per_page'=>$per_page)); + return $this->parsed_response ? $this->parsed_response['contacts'] : false; + } + + /* Favorites Methods */ + function favorites_add ($photo_id) { + /* http://www.flickr.com/services/api/flickr.favorites.add.html */ + $this->request('flickr.favorites.add', array('photo_id'=>$photo_id), TRUE); + return $this->parsed_response ? true : false; + } + + function favorites_getList ($user_id = NULL, $min_fave_date = NULL, $max_fave_date = NULL, $extras = NULL, $per_page = NULL, $page = NULL) { + /* http://www.flickr.com/services/api/flickr.favorites.getList.html */ + return $this->call('flickr.favorites.getList', array('user_id' => $user_id, 'min_fave_date' => $min_fave_date, 'max_fave_date' => $max_fave_date, 'extras' => $extras, 'per_page' => $per_page, 'page' => $page)); + } + + function favorites_getPublicList ($user_id, $min_fave_date = NULL, $max_fave_date = NULL, $extras = NULL, $per_page = NULL, $page = NULL) { + /* http://www.flickr.com/services/api/flickr.favorites.getPublicList.html */ + return $this->call('flickr.favorites.getPublicList', array('user_id' => $user_id, 'min_fave_date' => $min_fave_date, 'max_fave_date' => $max_fave_date, 'extras' => $extras, 'per_page' => $per_page, 'page' => $page)); + } + + function favorites_remove ($photo_id) { + /* http://www.flickr.com/services/api/flickr.favorites.remove.html */ + $this->request("flickr.favorites.remove", array("photo_id"=>$photo_id), TRUE); + return $this->parsed_response ? true : false; + } + + /* Groups Methods */ + function groups_browse ($cat_id = NULL) { + /* http://www.flickr.com/services/api/flickr.groups.browse.html */ + $this->request("flickr.groups.browse", array("cat_id"=>$cat_id)); + return $this->parsed_response ? $this->parsed_response['category'] : false; + } + + function groups_getInfo ($group_id, $lang = NULL) { + /* http://www.flickr.com/services/api/flickr.groups.getInfo.html */ + return $this->call('flickr.groups.getInfo', array('group_id' => $group_id, 'lang' => $lang)); + } + + function groups_search ($text, $per_page = NULL, $page = NULL) { + /* http://www.flickr.com/services/api/flickr.groups.search.html */ + $this->request("flickr.groups.search", array("text"=>$text,"per_page"=>$per_page,"page"=>$page)); + return $this->parsed_response ? $this->parsed_response['groups'] : false; + } + + /* Groups Pools Methods */ + function groups_pools_add ($photo_id, $group_id) { + /* http://www.flickr.com/services/api/flickr.groups.pools.add.html */ + $this->request("flickr.groups.pools.add", array("photo_id"=>$photo_id, "group_id"=>$group_id), TRUE); + return $this->parsed_response ? true : false; + } + + function groups_pools_getContext ($photo_id, $group_id) { + /* http://www.flickr.com/services/api/flickr.groups.pools.getContext.html */ + $this->request("flickr.groups.pools.getContext", array("photo_id"=>$photo_id, "group_id"=>$group_id)); + return $this->parsed_response ? $this->parsed_response : false; + } + + function groups_pools_getGroups ($page = NULL, $per_page = NULL) { + /* http://www.flickr.com/services/api/flickr.groups.pools.getGroups.html */ + $this->request("flickr.groups.pools.getGroups", array('page'=>$page, 'per_page'=>$per_page)); + return $this->parsed_response ? $this->parsed_response['groups'] : false; + } + + function groups_pools_getPhotos ($group_id, $tags = NULL, $user_id = NULL, $extras = NULL, $per_page = NULL, $page = NULL) { + /* http://www.flickr.com/services/api/flickr.groups.pools.getPhotos.html */ + if (is_array($extras)) { + $extras = implode(",", $extras); + } + $this->request("flickr.groups.pools.getPhotos", array("group_id"=>$group_id, "tags"=>$tags, "user_id"=>$user_id, "extras"=>$extras, "per_page"=>$per_page, "page"=>$page)); + return $this->parsed_response ? $this->parsed_response['photos'] : false; + } + + function groups_pools_remove ($photo_id, $group_id) { + /* http://www.flickr.com/services/api/flickr.groups.pools.remove.html */ + $this->request("flickr.groups.pools.remove", array("photo_id"=>$photo_id, "group_id"=>$group_id), TRUE); + return $this->parsed_response ? true : false; + } + + /* Interestingness methods */ + function interestingness_getList ($date = NULL, $extras = NULL, $per_page = NULL, $page = NULL) { + /* http://www.flickr.com/services/api/flickr.interestingness.getList.html */ + if (is_array($extras)) { + $extras = implode(",", $extras); + } + + $this->request("flickr.interestingness.getList", array("date"=>$date, "extras"=>$extras, "per_page"=>$per_page, "page"=>$page)); + return $this->parsed_response ? $this->parsed_response['photos'] : false; + } + + /* Machine Tag methods */ + function machinetags_getNamespaces ($predicate = NULL, $per_page = NULL, $page = NULL) { + /* http://www.flickr.com/services/api/flickr.machinetags.getNamespaces.html */ + return $this->call('flickr.machinetags.getNamespaces', array('predicate' => $predicate, 'per_page' => $per_page, 'page' => $page)); + } + + function machinetags_getPairs ($namespace = NULL, $predicate = NULL, $per_page = NULL, $page = NULL) { + /* http://www.flickr.com/services/api/flickr.machinetags.getPairs.html */ + return $this->call('flickr.machinetags.getPairs', array('namespace' => $namespace, 'predicate' => $predicate, 'per_page' => $per_page, 'page' => $page)); + } + + function machinetags_getPredicates ($namespace = NULL, $per_page = NULL, $page = NULL) { + /* http://www.flickr.com/services/api/flickr.machinetags.getPredicates.html */ + return $this->call('flickr.machinetags.getPredicates', array('namespace' => $namespace, 'per_page' => $per_page, 'page' => $page)); + } + + function machinetags_getValues ($namespace, $predicate, $per_page = NULL, $page = NULL) { + /* http://www.flickr.com/services/api/flickr.machinetags.getValues.html */ + return $this->call('flickr.machinetags.getValues', array('namespace' => $namespace, 'predicate' => $predicate, 'per_page' => $per_page, 'page' => $page)); + } + + /* People methods */ + function people_findByEmail ($find_email) { + /* http://www.flickr.com/services/api/flickr.people.findByEmail.html */ + $this->request("flickr.people.findByEmail", array("find_email"=>$find_email)); + return $this->parsed_response ? $this->parsed_response['user'] : false; + } + + function people_findByUsername ($username) { + /* http://www.flickr.com/services/api/flickr.people.findByUsername.html */ + $this->request("flickr.people.findByUsername", array("username"=>$username)); + return $this->parsed_response ? $this->parsed_response['user'] : false; + } + + function people_getInfo ($user_id) { + /* http://www.flickr.com/services/api/flickr.people.getInfo.html */ + $this->request("flickr.people.getInfo", array("user_id"=>$user_id)); + return $this->parsed_response ? $this->parsed_response['person'] : false; + } + + function people_getPublicGroups ($user_id) { + /* http://www.flickr.com/services/api/flickr.people.getPublicGroups.html */ + $this->request("flickr.people.getPublicGroups", array("user_id"=>$user_id)); + return $this->parsed_response ? $this->parsed_response['groups']['group'] : false; + } + + function people_getPublicPhotos ($user_id, $safe_search = NULL, $extras = NULL, $per_page = NULL, $page = NULL) { + /* http://www.flickr.com/services/api/flickr.people.getPublicPhotos.html */ + return $this->call('flickr.people.getPublicPhotos', array('user_id' => $user_id, 'safe_search' => $safe_search, 'extras' => $extras, 'per_page' => $per_page, 'page' => $page)); + } + + function people_getUploadStatus () { + /* http://www.flickr.com/services/api/flickr.people.getUploadStatus.html */ + /* Requires Authentication */ + $this->request("flickr.people.getUploadStatus"); + return $this->parsed_response ? $this->parsed_response['user'] : false; + } + + + /* Photos Methods */ + function photos_addTags ($photo_id, $tags) { + /* http://www.flickr.com/services/api/flickr.photos.addTags.html */ + $this->request("flickr.photos.addTags", array("photo_id"=>$photo_id, "tags"=>$tags), TRUE); + return $this->parsed_response ? true : false; + } + + function photos_delete ($photo_id) { + /* http://www.flickr.com/services/api/flickr.photos.delete.html */ + $this->request("flickr.photos.delete", array("photo_id"=>$photo_id), TRUE); + return $this->parsed_response ? true : false; + } + + function photos_getAllContexts ($photo_id) { + /* http://www.flickr.com/services/api/flickr.photos.getAllContexts.html */ + $this->request("flickr.photos.getAllContexts", array("photo_id"=>$photo_id)); + return $this->parsed_response ? $this->parsed_response : false; + } + + function photos_getContactsPhotos ($count = NULL, $just_friends = NULL, $single_photo = NULL, $include_self = NULL, $extras = NULL) { + /* http://www.flickr.com/services/api/flickr.photos.getContactsPhotos.html */ + $this->request("flickr.photos.getContactsPhotos", array("count"=>$count, "just_friends"=>$just_friends, "single_photo"=>$single_photo, "include_self"=>$include_self, "extras"=>$extras)); + return $this->parsed_response ? $this->parsed_response['photos']['photo'] : false; + } + + function photos_getContactsPublicPhotos ($user_id, $count = NULL, $just_friends = NULL, $single_photo = NULL, $include_self = NULL, $extras = NULL) { + /* http://www.flickr.com/services/api/flickr.photos.getContactsPublicPhotos.html */ + $this->request("flickr.photos.getContactsPublicPhotos", array("user_id"=>$user_id, "count"=>$count, "just_friends"=>$just_friends, "single_photo"=>$single_photo, "include_self"=>$include_self, "extras"=>$extras)); + return $this->parsed_response ? $this->parsed_response['photos']['photo'] : false; + } + + function photos_getContext ($photo_id) { + /* http://www.flickr.com/services/api/flickr.photos.getContext.html */ + $this->request("flickr.photos.getContext", array("photo_id"=>$photo_id)); + return $this->parsed_response ? $this->parsed_response : false; + } + + function photos_getCounts ($dates = NULL, $taken_dates = NULL) { + /* http://www.flickr.com/services/api/flickr.photos.getCounts.html */ + $this->request("flickr.photos.getCounts", array("dates"=>$dates, "taken_dates"=>$taken_dates)); + return $this->parsed_response ? $this->parsed_response['photocounts']['photocount'] : false; + } + + function photos_getExif ($photo_id, $secret = NULL) { + /* http://www.flickr.com/services/api/flickr.photos.getExif.html */ + $this->request("flickr.photos.getExif", array("photo_id"=>$photo_id, "secret"=>$secret)); + return $this->parsed_response ? $this->parsed_response['photo'] : false; + } + + function photos_getFavorites ($photo_id, $page = NULL, $per_page = NULL) { + /* http://www.flickr.com/services/api/flickr.photos.getFavorites.html */ + $this->request("flickr.photos.getFavorites", array("photo_id"=>$photo_id, "page"=>$page, "per_page"=>$per_page)); + return $this->parsed_response ? $this->parsed_response['photo'] : false; + } + + function photos_getInfo ($photo_id, $secret = NULL) { + /* http://www.flickr.com/services/api/flickr.photos.getInfo.html */ + $this->request("flickr.photos.getInfo", array("photo_id"=>$photo_id, "secret"=>$secret)); + return $this->parsed_response ? $this->parsed_response['photo'] : false; + } + + function photos_getNotInSet ($min_upload_date = NULL, $max_upload_date = NULL, $min_taken_date = NULL, $max_taken_date = NULL, $privacy_filter = NULL, $media = NULL, $extras = NULL, $per_page = NULL, $page = NULL) { + /* http://www.flickr.com/services/api/flickr.photos.getNotInSet.html */ + return $this->call('flickr.photos.getNotInSet', array('min_upload_date' => $min_upload_date, 'max_upload_date' => $max_upload_date, 'min_taken_date' => $min_taken_date, 'max_taken_date' => $max_taken_date, 'privacy_filter' => $privacy_filter, 'media' => $media, 'extras' => $extras, 'per_page' => $per_page, 'page' => $page)); + } + + function photos_getPerms ($photo_id) { + /* http://www.flickr.com/services/api/flickr.photos.getPerms.html */ + $this->request("flickr.photos.getPerms", array("photo_id"=>$photo_id)); + return $this->parsed_response ? $this->parsed_response['perms'] : false; + } + + function photos_getRecent ($extras = NULL, $per_page = NULL, $page = NULL) { + /* http://www.flickr.com/services/api/flickr.photos.getRecent.html */ + + if (is_array($extras)) { + $extras = implode(",", $extras); + } + $this->request("flickr.photos.getRecent", array("extras"=>$extras, "per_page"=>$per_page, "page"=>$page)); + return $this->parsed_response ? $this->parsed_response['photos'] : false; + } + + function photos_getSizes ($photo_id) { + /* http://www.flickr.com/services/api/flickr.photos.getSizes.html */ + $this->request("flickr.photos.getSizes", array("photo_id"=>$photo_id)); + return $this->parsed_response ? $this->parsed_response['sizes']['size'] : false; + } + + function photos_getUntagged ($min_upload_date = NULL, $max_upload_date = NULL, $min_taken_date = NULL, $max_taken_date = NULL, $privacy_filter = NULL, $media = NULL, $extras = NULL, $per_page = NULL, $page = NULL) { + /* http://www.flickr.com/services/api/flickr.photos.getUntagged.html */ + return $this->call('flickr.photos.getUntagged', array('min_upload_date' => $min_upload_date, 'max_upload_date' => $max_upload_date, 'min_taken_date' => $min_taken_date, 'max_taken_date' => $max_taken_date, 'privacy_filter' => $privacy_filter, 'media' => $media, 'extras' => $extras, 'per_page' => $per_page, 'page' => $page)); + } + + function photos_getWithGeoData ($args = array()) { + /* See the documentation included with the photos_search() function. + * I'm using the same style of arguments for this function. The only + * difference here is that this doesn't require any arguments. The + * flickr.photos.search method requires at least one search parameter. + */ + /* http://www.flickr.com/services/api/flickr.photos.getWithGeoData.html */ + $this->request("flickr.photos.getWithGeoData", $args); + return $this->parsed_response ? $this->parsed_response['photos'] : false; + } + + function photos_getWithoutGeoData ($args = array()) { + /* See the documentation included with the photos_search() function. + * I'm using the same style of arguments for this function. The only + * difference here is that this doesn't require any arguments. The + * flickr.photos.search method requires at least one search parameter. + */ + /* http://www.flickr.com/services/api/flickr.photos.getWithoutGeoData.html */ + $this->request("flickr.photos.getWithoutGeoData", $args); + return $this->parsed_response ? $this->parsed_response['photos'] : false; + } + + function photos_recentlyUpdated ($min_date, $extras = NULL, $per_page = NULL, $page = NULL) { + /* http://www.flickr.com/services/api/flickr.photos.recentlyUpdated.html */ + return $this->call('flickr.photos.recentlyUpdated', array('min_date' => $min_date, 'extras' => $extras, 'per_page' => $per_page, 'page' => $page)); + } + + function photos_removeTag ($tag_id) { + /* http://www.flickr.com/services/api/flickr.photos.removeTag.html */ + $this->request("flickr.photos.removeTag", array("tag_id"=>$tag_id), TRUE); + return $this->parsed_response ? true : false; + } + + function photos_search ($args = array()) { + /* This function strays from the method of arguments that I've + * used in the other functions for the fact that there are just + * so many arguments to this API method. What you'll need to do + * is pass an associative array to the function containing the + * arguments you want to pass to the API. For example: + * $photos = $f->photos_search(array("tags"=>"brown,cow", "tag_mode"=>"any")); + * This will return photos tagged with either "brown" or "cow" + * or both. See the API documentation (link below) for a full + * list of arguments. + */ + + /* http://www.flickr.com/services/api/flickr.photos.search.html */ + $this->request("flickr.photos.search", $args); + return $this->parsed_response ? $this->parsed_response['photos'] : false; + } + + function photos_setContentType ($photo_id, $content_type) { + /* http://www.flickr.com/services/api/flickr.photos.setContentType.html */ + return $this->call('flickr.photos.setContentType', array('photo_id' => $photo_id, 'content_type' => $content_type)); + } + + function photos_setDates ($photo_id, $date_posted = NULL, $date_taken = NULL, $date_taken_granularity = NULL) { + /* http://www.flickr.com/services/api/flickr.photos.setDates.html */ + $this->request("flickr.photos.setDates", array("photo_id"=>$photo_id, "date_posted"=>$date_posted, "date_taken"=>$date_taken, "date_taken_granularity"=>$date_taken_granularity), TRUE); + return $this->parsed_response ? true : false; + } + + function photos_setMeta ($photo_id, $title, $description) { + /* http://www.flickr.com/services/api/flickr.photos.setMeta.html */ + $this->request("flickr.photos.setMeta", array("photo_id"=>$photo_id, "title"=>$title, "description"=>$description), TRUE); + return $this->parsed_response ? true : false; + } + + function photos_setPerms ($photo_id, $is_public, $is_friend, $is_family, $perm_comment, $perm_addmeta) { + /* http://www.flickr.com/services/api/flickr.photos.setPerms.html */ + $this->request("flickr.photos.setPerms", array("photo_id"=>$photo_id, "is_public"=>$is_public, "is_friend"=>$is_friend, "is_family"=>$is_family, "perm_comment"=>$perm_comment, "perm_addmeta"=>$perm_addmeta), TRUE); + return $this->parsed_response ? true : false; + } + + function photos_setSafetyLevel ($photo_id, $safety_level = NULL, $hidden = NULL) { + /* http://www.flickr.com/services/api/flickr.photos.setSafetyLevel.html */ + return $this->call('flickr.photos.setSafetyLevel', array('photo_id' => $photo_id, 'safety_level' => $safety_level, 'hidden' => $hidden)); + } + + function photos_setTags ($photo_id, $tags) { + /* http://www.flickr.com/services/api/flickr.photos.setTags.html */ + $this->request("flickr.photos.setTags", array("photo_id"=>$photo_id, "tags"=>$tags), TRUE); + return $this->parsed_response ? true : false; + } + + /* Photos - Comments Methods */ + function photos_comments_addComment ($photo_id, $comment_text) { + /* http://www.flickr.com/services/api/flickr.photos.comments.addComment.html */ + $this->request("flickr.photos.comments.addComment", array("photo_id" => $photo_id, "comment_text"=>$comment_text), TRUE); + return $this->parsed_response ? $this->parsed_response['comment'] : false; + } + + function photos_comments_deleteComment ($comment_id) { + /* http://www.flickr.com/services/api/flickr.photos.comments.deleteComment.html */ + $this->request("flickr.photos.comments.deleteComment", array("comment_id" => $comment_id), TRUE); + return $this->parsed_response ? true : false; + } + + function photos_comments_editComment ($comment_id, $comment_text) { + /* http://www.flickr.com/services/api/flickr.photos.comments.editComment.html */ + $this->request("flickr.photos.comments.editComment", array("comment_id" => $comment_id, "comment_text"=>$comment_text), TRUE); + return $this->parsed_response ? true : false; + } + + function photos_comments_getList ($photo_id, $min_comment_date = NULL, $max_comment_date = NULL) { + /* http://www.flickr.com/services/api/flickr.photos.comments.getList.html */ + return $this->call('flickr.photos.comments.getList', array('photo_id' => $photo_id, 'min_comment_date' => $min_comment_date, 'max_comment_date' => $max_comment_date)); + } + + /* Photos - Geo Methods */ + function photos_geo_batchCorrectLocation ($lat, $lon, $accuracy, $place_id = NULL, $woe_id = NULL) { + /* http://www.flickr.com/services/api/flickr.photos.geo.batchCorrectLocation.html */ + return $this->call('flickr.photos.geo.batchCorrectLocation', array('lat' => $lat, 'lon' => $lon, 'accuracy' => $accuracy, 'place_id' => $place_id, 'woe_id' => $woe_id)); + } + + function photos_geo_correctLocation ($photo_id, $place_id = NULL, $woe_id = NULL) { + /* http://www.flickr.com/services/api/flickr.photos.geo.correctLocation.html */ + return $this->call('flickr.photos.geo.correctLocation', array('photo_id' => $photo_id, 'place_id' => $place_id, 'woe_id' => $woe_id)); + } + + function photos_geo_getLocation ($photo_id) { + /* http://www.flickr.com/services/api/flickr.photos.geo.getLocation.html */ + $this->request("flickr.photos.geo.getLocation", array("photo_id"=>$photo_id)); + return $this->parsed_response ? $this->parsed_response['photo'] : false; + } + + function photos_geo_getPerms ($photo_id) { + /* http://www.flickr.com/services/api/flickr.photos.geo.getPerms.html */ + $this->request("flickr.photos.geo.getPerms", array("photo_id"=>$photo_id)); + return $this->parsed_response ? $this->parsed_response['perms'] : false; + } + + function photos_geo_photosForLocation ($lat, $lon, $accuracy = NULL, $extras = NULL, $per_page = NULL, $page = NULL) { + /* http://www.flickr.com/services/api/flickr.photos.geo.photosForLocation.html */ + return $this->call('flickr.photos.geo.photosForLocation', array('lat' => $lat, 'lon' => $lon, 'accuracy' => $accuracy, 'extras' => $extras, 'per_page' => $per_page, 'page' => $page)); + } + + function photos_geo_removeLocation ($photo_id) { + /* http://www.flickr.com/services/api/flickr.photos.geo.removeLocation.html */ + $this->request("flickr.photos.geo.removeLocation", array("photo_id"=>$photo_id), TRUE); + return $this->parsed_response ? true : false; + } + + function photos_geo_setContext ($photo_id, $context) { + /* http://www.flickr.com/services/api/flickr.photos.geo.setContext.html */ + return $this->call('flickr.photos.geo.setContext', array('photo_id' => $photo_id, 'context' => $context)); + } + + function photos_geo_setLocation ($photo_id, $lat, $lon, $accuracy = NULL) { + /* http://www.flickr.com/services/api/flickr.photos.geo.setLocation.html */ + $this->request("flickr.photos.geo.setLocation", array("photo_id"=>$photo_id, "lat"=>$lat, "lon"=>$lon, "accuracy"=>$accuracy), TRUE); + return $this->parsed_response ? true : false; + } + + function photos_geo_setPerms ($is_public, $is_contact, $is_friend, $is_family, $photo_id) { + /* http://www.flickr.com/services/api/flickr.photos.geo.setPerms.html */ + return $this->call('flickr.photos.geo.setPerms', array('is_public' => $is_public, 'is_contact' => $is_contact, 'is_friend' => $is_friend, 'is_family' => $is_family, 'photo_id' => $photo_id)); + } + + /* Photos - Licenses Methods */ + function photos_licenses_getInfo () { + /* http://www.flickr.com/services/api/flickr.photos.licenses.getInfo.html */ + $this->request("flickr.photos.licenses.getInfo"); + return $this->parsed_response ? $this->parsed_response['licenses']['license'] : false; + } + + function photos_licenses_setLicense ($photo_id, $license_id) { + /* http://www.flickr.com/services/api/flickr.photos.licenses.setLicense.html */ + /* Requires Authentication */ + $this->request("flickr.photos.licenses.setLicense", array("photo_id"=>$photo_id, "license_id"=>$license_id), TRUE); + return $this->parsed_response ? true : false; + } + + /* Photos - Notes Methods */ + function photos_notes_add ($photo_id, $note_x, $note_y, $note_w, $note_h, $note_text) { + /* http://www.flickr.com/services/api/flickr.photos.notes.add.html */ + $this->request("flickr.photos.notes.add", array("photo_id" => $photo_id, "note_x" => $note_x, "note_y" => $note_y, "note_w" => $note_w, "note_h" => $note_h, "note_text" => $note_text), TRUE); + return $this->parsed_response ? $this->parsed_response['note'] : false; + } + + function photos_notes_delete ($note_id) { + /* http://www.flickr.com/services/api/flickr.photos.notes.delete.html */ + $this->request("flickr.photos.notes.delete", array("note_id" => $note_id), TRUE); + return $this->parsed_response ? true : false; + } + + function photos_notes_edit ($note_id, $note_x, $note_y, $note_w, $note_h, $note_text) { + /* http://www.flickr.com/services/api/flickr.photos.notes.edit.html */ + $this->request("flickr.photos.notes.edit", array("note_id" => $note_id, "note_x" => $note_x, "note_y" => $note_y, "note_w" => $note_w, "note_h" => $note_h, "note_text" => $note_text), TRUE); + return $this->parsed_response ? true : false; + } + + /* Photos - Transform Methods */ + function photos_transform_rotate ($photo_id, $degrees) { + /* http://www.flickr.com/services/api/flickr.photos.transform.rotate.html */ + $this->request("flickr.photos.transform.rotate", array("photo_id" => $photo_id, "degrees" => $degrees), TRUE); + return $this->parsed_response ? true : false; + } + + /* Photos - Upload Methods */ + function photos_upload_checkTickets ($tickets) { + /* http://www.flickr.com/services/api/flickr.photos.upload.checkTickets.html */ + if (is_array($tickets)) { + $tickets = implode(",", $tickets); + } + $this->request("flickr.photos.upload.checkTickets", array("tickets" => $tickets), TRUE); + return $this->parsed_response ? $this->parsed_response['uploader']['ticket'] : false; + } + + /* Photosets Methods */ + function photosets_addPhoto ($photoset_id, $photo_id) { + /* http://www.flickr.com/services/api/flickr.photosets.addPhoto.html */ + $this->request("flickr.photosets.addPhoto", array("photoset_id" => $photoset_id, "photo_id" => $photo_id), TRUE); + return $this->parsed_response ? true : false; + } + + function photosets_create ($title, $description, $primary_photo_id) { + /* http://www.flickr.com/services/api/flickr.photosets.create.html */ + $this->request("flickr.photosets.create", array("title" => $title, "primary_photo_id" => $primary_photo_id, "description" => $description), TRUE); + return $this->parsed_response ? $this->parsed_response['photoset'] : false; + } + + function photosets_delete ($photoset_id) { + /* http://www.flickr.com/services/api/flickr.photosets.delete.html */ + $this->request("flickr.photosets.delete", array("photoset_id" => $photoset_id), TRUE); + return $this->parsed_response ? true : false; + } + + function photosets_editMeta ($photoset_id, $title, $description = NULL) { + /* http://www.flickr.com/services/api/flickr.photosets.editMeta.html */ + $this->request("flickr.photosets.editMeta", array("photoset_id" => $photoset_id, "title" => $title, "description" => $description), TRUE); + return $this->parsed_response ? true : false; + } + + function photosets_editPhotos ($photoset_id, $primary_photo_id, $photo_ids) { + /* http://www.flickr.com/services/api/flickr.photosets.editPhotos.html */ + $this->request("flickr.photosets.editPhotos", array("photoset_id" => $photoset_id, "primary_photo_id" => $primary_photo_id, "photo_ids" => $photo_ids), TRUE); + return $this->parsed_response ? true : false; + } + + function photosets_getContext ($photo_id, $photoset_id) { + /* http://www.flickr.com/services/api/flickr.photosets.getContext.html */ + $this->request("flickr.photosets.getContext", array("photo_id" => $photo_id, "photoset_id" => $photoset_id)); + return $this->parsed_response ? $this->parsed_response : false; + } + + function photosets_getInfo ($photoset_id) { + /* http://www.flickr.com/services/api/flickr.photosets.getInfo.html */ + $this->request("flickr.photosets.getInfo", array("photoset_id" => $photoset_id)); + return $this->parsed_response ? $this->parsed_response['photoset'] : false; + } + + function photosets_getList ($user_id = NULL) { + /* http://www.flickr.com/services/api/flickr.photosets.getList.html */ + $this->request("flickr.photosets.getList", array("user_id" => $user_id)); + return $this->parsed_response ? $this->parsed_response['photosets'] : false; + } + + function photosets_getPhotos ($photoset_id, $extras = NULL, $privacy_filter = NULL, $per_page = NULL, $page = NULL, $media = NULL) { + /* http://www.flickr.com/services/api/flickr.photosets.getPhotos.html */ + return $this->call('flickr.photosets.getPhotos', array('photoset_id' => $photoset_id, 'extras' => $extras, 'privacy_filter' => $privacy_filter, 'per_page' => $per_page, 'page' => $page, 'media' => $media)); + } + + function photosets_orderSets ($photoset_ids) { + /* http://www.flickr.com/services/api/flickr.photosets.orderSets.html */ + if (is_array($photoset_ids)) { + $photoset_ids = implode(",", $photoset_ids); + } + $this->request("flickr.photosets.orderSets", array("photoset_ids" => $photoset_ids), TRUE); + return $this->parsed_response ? true : false; + } + + function photosets_removePhoto ($photoset_id, $photo_id) { + /* http://www.flickr.com/services/api/flickr.photosets.removePhoto.html */ + $this->request("flickr.photosets.removePhoto", array("photoset_id" => $photoset_id, "photo_id" => $photo_id), TRUE); + return $this->parsed_response ? true : false; + } + + /* Photosets Comments Methods */ + function photosets_comments_addComment ($photoset_id, $comment_text) { + /* http://www.flickr.com/services/api/flickr.photosets.comments.addComment.html */ + $this->request("flickr.photosets.comments.addComment", array("photoset_id" => $photoset_id, "comment_text"=>$comment_text), TRUE); + return $this->parsed_response ? $this->parsed_response['comment'] : false; + } + + function photosets_comments_deleteComment ($comment_id) { + /* http://www.flickr.com/services/api/flickr.photosets.comments.deleteComment.html */ + $this->request("flickr.photosets.comments.deleteComment", array("comment_id" => $comment_id), TRUE); + return $this->parsed_response ? true : false; + } + + function photosets_comments_editComment ($comment_id, $comment_text) { + /* http://www.flickr.com/services/api/flickr.photosets.comments.editComment.html */ + $this->request("flickr.photosets.comments.editComment", array("comment_id" => $comment_id, "comment_text"=>$comment_text), TRUE); + return $this->parsed_response ? true : false; + } + + function photosets_comments_getList ($photoset_id) { + /* http://www.flickr.com/services/api/flickr.photosets.comments.getList.html */ + $this->request("flickr.photosets.comments.getList", array("photoset_id"=>$photoset_id)); + return $this->parsed_response ? $this->parsed_response['comments'] : false; + } + + /* Places Methods */ + function places_find ($query) { + /* http://www.flickr.com/services/api/flickr.places.find.html */ + return $this->call('flickr.places.find', array('query' => $query)); + } + + function places_findByLatLon ($lat, $lon, $accuracy = NULL) { + /* http://www.flickr.com/services/api/flickr.places.findByLatLon.html */ + return $this->call('flickr.places.findByLatLon', array('lat' => $lat, 'lon' => $lon, 'accuracy' => $accuracy)); + } + + function places_getChildrenWithPhotosPublic ($place_id = NULL, $woe_id = NULL) { + /* http://www.flickr.com/services/api/flickr.places.getChildrenWithPhotosPublic.html */ + return $this->call('flickr.places.getChildrenWithPhotosPublic', array('place_id' => $place_id, 'woe_id' => $woe_id)); + } + + function places_getInfo ($place_id = NULL, $woe_id = NULL) { + /* http://www.flickr.com/services/api/flickr.places.getInfo.html */ + return $this->call('flickr.places.getInfo', array('place_id' => $place_id, 'woe_id' => $woe_id)); + } + + function places_getInfoByUrl ($url) { + /* http://www.flickr.com/services/api/flickr.places.getInfoByUrl.html */ + return $this->call('flickr.places.getInfoByUrl', array('url' => $url)); + } + + function places_getPlaceTypes () { + /* http://www.flickr.com/services/api/flickr.places.getPlaceTypes.html */ + return $this->call('flickr.places.getPlaceTypes', array()); + } + + function places_placesForBoundingBox ($bbox, $place_type = NULL, $place_type_id = NULL) { + /* http://www.flickr.com/services/api/flickr.places.placesForBoundingBox.html */ + return $this->call('flickr.places.placesForBoundingBox', array('bbox' => $bbox, 'place_type' => $place_type, 'place_type_id' => $place_type_id)); + } + + function places_placesForContacts ($place_type = NULL, $place_type_id = NULL, $woe_id = NULL, $place_id = NULL, $threshold = NULL, $contacts = NULL, $min_upload_date = NULL, $max_upload_date = NULL, $min_taken_date = NULL, $max_taken_date = NULL) { + /* http://www.flickr.com/services/api/flickr.places.placesForContacts.html */ + return $this->call('flickr.places.placesForContacts', array('place_type' => $place_type, 'place_type_id' => $place_type_id, 'woe_id' => $woe_id, 'place_id' => $place_id, 'threshold' => $threshold, 'contacts' => $contacts, 'min_upload_date' => $min_upload_date, 'max_upload_date' => $max_upload_date, 'min_taken_date' => $min_taken_date, 'max_taken_date' => $max_taken_date)); + } + + function places_placesForTags ($place_type_id, $woe_id = NULL, $place_id = NULL, $threshold = NULL, $tags = NULL, $tag_mode = NULL, $machine_tags = NULL, $machine_tag_mode = NULL, $min_upload_date = NULL, $max_upload_date = NULL, $min_taken_date = NULL, $max_taken_date = NULL) { + /* http://www.flickr.com/services/api/flickr.places.placesForTags.html */ + return $this->call('flickr.places.placesForTags', array('place_type_id' => $place_type_id, 'woe_id' => $woe_id, 'place_id' => $place_id, 'threshold' => $threshold, 'tags' => $tags, 'tag_mode' => $tag_mode, 'machine_tags' => $machine_tags, 'machine_tag_mode' => $machine_tag_mode, 'min_upload_date' => $min_upload_date, 'max_upload_date' => $max_upload_date, 'min_taken_date' => $min_taken_date, 'max_taken_date' => $max_taken_date)); + } + + function places_placesForUser ($place_type_id = NULL, $place_type = NULL, $woe_id = NULL, $place_id = NULL, $threshold = NULL, $min_upload_date = NULL, $max_upload_date = NULL, $min_taken_date = NULL, $max_taken_date = NULL) { + /* http://www.flickr.com/services/api/flickr.places.placesForUser.html */ + return $this->call('flickr.places.placesForUser', array('place_type_id' => $place_type_id, 'place_type' => $place_type, 'woe_id' => $woe_id, 'place_id' => $place_id, 'threshold' => $threshold, 'min_upload_date' => $min_upload_date, 'max_upload_date' => $max_upload_date, 'min_taken_date' => $min_taken_date, 'max_taken_date' => $max_taken_date)); + } + + function places_resolvePlaceId ($place_id) { + /* http://www.flickr.com/services/api/flickr.places.resolvePlaceId.html */ + $rsp = $this->call('flickr.places.resolvePlaceId', array('place_id' => $place_id)); + return $rsp ? $rsp['location'] : $rsp; + } + + function places_resolvePlaceURL ($url) { + /* http://www.flickr.com/services/api/flickr.places.resolvePlaceURL.html */ + $rsp = $this->call('flickr.places.resolvePlaceURL', array('url' => $url)); + return $rsp ? $rsp['location'] : $rsp; + } + + /* Prefs Methods */ + function prefs_getContentType () { + /* http://www.flickr.com/services/api/flickr.prefs.getContentType.html */ + $rsp = $this->call('flickr.prefs.getContentType', array()); + return $rsp ? $rsp['person'] : $rsp; + } + + function prefs_getGeoPerms () { + /* http://www.flickr.com/services/api/flickr.prefs.getGeoPerms.html */ + return $this->call('flickr.prefs.getGeoPerms', array()); + } + + function prefs_getHidden () { + /* http://www.flickr.com/services/api/flickr.prefs.getHidden.html */ + $rsp = $this->call('flickr.prefs.getHidden', array()); + return $rsp ? $rsp['person'] : $rsp; + } + + function prefs_getPrivacy () { + /* http://www.flickr.com/services/api/flickr.prefs.getPrivacy.html */ + $rsp = $this->call('flickr.prefs.getPrivacy', array()); + return $rsp ? $rsp['person'] : $rsp; + } + + function prefs_getSafetyLevel () { + /* http://www.flickr.com/services/api/flickr.prefs.getSafetyLevel.html */ + $rsp = $this->call('flickr.prefs.getSafetyLevel', array()); + return $rsp ? $rsp['person'] : $rsp; + } + + /* Reflection Methods */ + function reflection_getMethodInfo ($method_name) { + /* http://www.flickr.com/services/api/flickr.reflection.getMethodInfo.html */ + $this->request("flickr.reflection.getMethodInfo", array("method_name" => $method_name)); + return $this->parsed_response ? $this->parsed_response : false; + } + + function reflection_getMethods () { + /* http://www.flickr.com/services/api/flickr.reflection.getMethods.html */ + $this->request("flickr.reflection.getMethods"); + return $this->parsed_response ? $this->parsed_response['methods']['method'] : false; + } + + /* Tags Methods */ + function tags_getClusterPhotos ($tag, $cluster_id) { + /* http://www.flickr.com/services/api/flickr.tags.getClusterPhotos.html */ + return $this->call('flickr.tags.getClusterPhotos', array('tag' => $tag, 'cluster_id' => $cluster_id)); + } + + function tags_getClusters ($tag) { + /* http://www.flickr.com/services/api/flickr.tags.getClusters.html */ + return $this->call('flickr.tags.getClusters', array('tag' => $tag)); + } + + function tags_getHotList ($period = NULL, $count = NULL) { + /* http://www.flickr.com/services/api/flickr.tags.getHotList.html */ + $this->request("flickr.tags.getHotList", array("period" => $period, "count" => $count)); + return $this->parsed_response ? $this->parsed_response['hottags'] : false; + } + + function tags_getListPhoto ($photo_id) { + /* http://www.flickr.com/services/api/flickr.tags.getListPhoto.html */ + $this->request("flickr.tags.getListPhoto", array("photo_id" => $photo_id)); + return $this->parsed_response ? $this->parsed_response['photo']['tags']['tag'] : false; + } + + function tags_getListUser ($user_id = NULL) { + /* http://www.flickr.com/services/api/flickr.tags.getListUser.html */ + $this->request("flickr.tags.getListUser", array("user_id" => $user_id)); + return $this->parsed_response ? $this->parsed_response['who']['tags']['tag'] : false; + } + + function tags_getListUserPopular ($user_id = NULL, $count = NULL) { + /* http://www.flickr.com/services/api/flickr.tags.getListUserPopular.html */ + $this->request("flickr.tags.getListUserPopular", array("user_id" => $user_id, "count" => $count)); + return $this->parsed_response ? $this->parsed_response['who']['tags']['tag'] : false; + } + + function tags_getListUserRaw ($tag = NULL) { + /* http://www.flickr.com/services/api/flickr.tags.getListUserRaw.html */ + return $this->call('flickr.tags.getListUserRaw', array('tag' => $tag)); + } + + function tags_getRelated ($tag) { + /* http://www.flickr.com/services/api/flickr.tags.getRelated.html */ + $this->request("flickr.tags.getRelated", array("tag" => $tag)); + return $this->parsed_response ? $this->parsed_response['tags'] : false; + } + + function test_echo ($args = array()) { + /* http://www.flickr.com/services/api/flickr.test.echo.html */ + $this->request("flickr.test.echo", $args); + return $this->parsed_response ? $this->parsed_response : false; + } + + function test_login () { + /* http://www.flickr.com/services/api/flickr.test.login.html */ + $this->request("flickr.test.login"); + return $this->parsed_response ? $this->parsed_response['user'] : false; + } + + function urls_getGroup ($group_id) { + /* http://www.flickr.com/services/api/flickr.urls.getGroup.html */ + $this->request("flickr.urls.getGroup", array("group_id"=>$group_id)); + return $this->parsed_response ? $this->parsed_response['group']['url'] : false; + } + + function urls_getUserPhotos ($user_id = NULL) { + /* http://www.flickr.com/services/api/flickr.urls.getUserPhotos.html */ + $this->request("flickr.urls.getUserPhotos", array("user_id"=>$user_id)); + return $this->parsed_response ? $this->parsed_response['user']['url'] : false; + } + + function urls_getUserProfile ($user_id = NULL) { + /* http://www.flickr.com/services/api/flickr.urls.getUserProfile.html */ + $this->request("flickr.urls.getUserProfile", array("user_id"=>$user_id)); + return $this->parsed_response ? $this->parsed_response['user']['url'] : false; + } + + function urls_lookupGroup ($url) { + /* http://www.flickr.com/services/api/flickr.urls.lookupGroup.html */ + $this->request("flickr.urls.lookupGroup", array("url"=>$url)); + return $this->parsed_response ? $this->parsed_response['group'] : false; + } + + function urls_lookupUser ($url) { + /* http://www.flickr.com/services/api/flickr.photos.notes.edit.html */ + $this->request("flickr.urls.lookupUser", array("url"=>$url)); + return $this->parsed_response ? $this->parsed_response['user'] : false; + } +} + + +?> diff --git a/events/vendors/jquery-1.2.6.pack.js b/events/vendors/jquery-1.2.6.pack.js new file mode 100644 index 0000000..95dd013 --- /dev/null +++ b/events/vendors/jquery-1.2.6.pack.js @@ -0,0 +1,11 @@ +/* + * jQuery 1.2.6 - New Wave Javascript + * + * Copyright (c) 2008 John Resig (jquery.com) + * Dual licensed under the MIT (MIT-LICENSE.txt) + * and GPL (GPL-LICENSE.txt) licenses. + * + * $Date: 2008-05-24 14:22:17 -0400 (Sat, 24 May 2008) $ + * $Rev: 5685 $ + */ +eval(function(p,a,c,k,e,r){e=function(c){return(c35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--)r[e(c)]=k[c]||e(c);k=[function(e){return r[e]}];e=function(){return'\\w+'};c=1};while(c--)if(k[c])p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c]);return p}('(H(){J w=1b.4M,3m$=1b.$;J D=1b.4M=1b.$=H(a,b){I 2B D.17.5j(a,b)};J u=/^[^<]*(<(.|\\s)+>)[^>]*$|^#(\\w+)$/,62=/^.[^:#\\[\\.]*$/,12;D.17=D.44={5j:H(d,b){d=d||S;G(d.16){7[0]=d;7.K=1;I 7}G(1j d=="23"){J c=u.2D(d);G(c&&(c[1]||!b)){G(c[1])d=D.4h([c[1]],b);N{J a=S.61(c[3]);G(a){G(a.2v!=c[3])I D().2q(d);I D(a)}d=[]}}N I D(b).2q(d)}N G(D.1D(d))I D(S)[D.17.27?"27":"43"](d);I 7.6Y(D.2d(d))},5w:"1.2.6",8G:H(){I 7.K},K:0,3p:H(a){I a==12?D.2d(7):7[a]},2I:H(b){J a=D(b);a.5n=7;I a},6Y:H(a){7.K=0;2p.44.1p.1w(7,a);I 7},P:H(a,b){I D.P(7,a,b)},5i:H(b){J a=-1;I D.2L(b&&b.5w?b[0]:b,7)},1K:H(c,a,b){J d=c;G(c.1q==56)G(a===12)I 7[0]&&D[b||"1K"](7[0],c);N{d={};d[c]=a}I 7.P(H(i){R(c 1n d)D.1K(b?7.V:7,c,D.1i(7,d[c],b,i,c))})},1g:H(b,a){G((b==\'2h\'||b==\'1Z\')&&3d(a)<0)a=12;I 7.1K(b,a,"2a")},1r:H(b){G(1j b!="49"&&b!=U)I 7.4E().3v((7[0]&&7[0].2z||S).5F(b));J a="";D.P(b||7,H(){D.P(7.3t,H(){G(7.16!=8)a+=7.16!=1?7.76:D.17.1r([7])})});I a},5z:H(b){G(7[0])D(b,7[0].2z).5y().39(7[0]).2l(H(){J a=7;1B(a.1x)a=a.1x;I a}).3v(7);I 7},8Y:H(a){I 7.P(H(){D(7).6Q().5z(a)})},8R:H(a){I 7.P(H(){D(7).5z(a)})},3v:H(){I 7.3W(19,M,Q,H(a){G(7.16==1)7.3U(a)})},6F:H(){I 7.3W(19,M,M,H(a){G(7.16==1)7.39(a,7.1x)})},6E:H(){I 7.3W(19,Q,Q,H(a){7.1d.39(a,7)})},5q:H(){I 7.3W(19,Q,M,H(a){7.1d.39(a,7.2H)})},3l:H(){I 7.5n||D([])},2q:H(b){J c=D.2l(7,H(a){I D.2q(b,a)});I 7.2I(/[^+>] [^+>]/.11(b)||b.1h("..")>-1?D.4r(c):c)},5y:H(e){J f=7.2l(H(){G(D.14.1f&&!D.4n(7)){J a=7.6o(M),5h=S.3h("1v");5h.3U(a);I D.4h([5h.4H])[0]}N I 7.6o(M)});J d=f.2q("*").5c().P(H(){G(7[E]!=12)7[E]=U});G(e===M)7.2q("*").5c().P(H(i){G(7.16==3)I;J c=D.L(7,"3w");R(J a 1n c)R(J b 1n c[a])D.W.1e(d[i],a,c[a][b],c[a][b].L)});I f},1E:H(b){I 7.2I(D.1D(b)&&D.3C(7,H(a,i){I b.1k(a,i)})||D.3g(b,7))},4Y:H(b){G(b.1q==56)G(62.11(b))I 7.2I(D.3g(b,7,M));N b=D.3g(b,7);J a=b.K&&b[b.K-1]!==12&&!b.16;I 7.1E(H(){I a?D.2L(7,b)<0:7!=b})},1e:H(a){I 7.2I(D.4r(D.2R(7.3p(),1j a==\'23\'?D(a):D.2d(a))))},3F:H(a){I!!a&&D.3g(a,7).K>0},7T:H(a){I 7.3F("."+a)},6e:H(b){G(b==12){G(7.K){J c=7[0];G(D.Y(c,"2A")){J e=c.64,63=[],15=c.15,2V=c.O=="2A-2V";G(e<0)I U;R(J i=2V?e:0,2f=2V?e+1:15.K;i<2f;i++){J d=15[i];G(d.2W){b=D.14.1f&&!d.at.2x.an?d.1r:d.2x;G(2V)I b;63.1p(b)}}I 63}N I(7[0].2x||"").1o(/\\r/g,"")}I 12}G(b.1q==4L)b+=\'\';I 7.P(H(){G(7.16!=1)I;G(b.1q==2p&&/5O|5L/.11(7.O))7.4J=(D.2L(7.2x,b)>=0||D.2L(7.34,b)>=0);N G(D.Y(7,"2A")){J a=D.2d(b);D("9R",7).P(H(){7.2W=(D.2L(7.2x,a)>=0||D.2L(7.1r,a)>=0)});G(!a.K)7.64=-1}N 7.2x=b})},2K:H(a){I a==12?(7[0]?7[0].4H:U):7.4E().3v(a)},7b:H(a){I 7.5q(a).21()},79:H(i){I 7.3s(i,i+1)},3s:H(){I 7.2I(2p.44.3s.1w(7,19))},2l:H(b){I 7.2I(D.2l(7,H(a,i){I b.1k(a,i,a)}))},5c:H(){I 7.1e(7.5n)},L:H(d,b){J a=d.1R(".");a[1]=a[1]?"."+a[1]:"";G(b===12){J c=7.5C("9z"+a[1]+"!",[a[0]]);G(c===12&&7.K)c=D.L(7[0],d);I c===12&&a[1]?7.L(a[0]):c}N I 7.1P("9u"+a[1]+"!",[a[0],b]).P(H(){D.L(7,d,b)})},3b:H(a){I 7.P(H(){D.3b(7,a)})},3W:H(g,f,h,d){J e=7.K>1,3x;I 7.P(H(){G(!3x){3x=D.4h(g,7.2z);G(h)3x.9o()}J b=7;G(f&&D.Y(7,"1T")&&D.Y(3x[0],"4F"))b=7.3H("22")[0]||7.3U(7.2z.3h("22"));J c=D([]);D.P(3x,H(){J a=e?D(7).5y(M)[0]:7;G(D.Y(a,"1m"))c=c.1e(a);N{G(a.16==1)c=c.1e(D("1m",a).21());d.1k(b,a)}});c.P(6T)})}};D.17.5j.44=D.17;H 6T(i,a){G(a.4d)D.3Y({1a:a.4d,31:Q,1O:"1m"});N D.5u(a.1r||a.6O||a.4H||"");G(a.1d)a.1d.37(a)}H 1z(){I+2B 8J}D.1l=D.17.1l=H(){J b=19[0]||{},i=1,K=19.K,4x=Q,15;G(b.1q==8I){4x=b;b=19[1]||{};i=2}G(1j b!="49"&&1j b!="H")b={};G(K==i){b=7;--i}R(;i-1}},6q:H(b,c,a){J e={};R(J d 1n c){e[d]=b.V[d];b.V[d]=c[d]}a.1k(b);R(J d 1n c)b.V[d]=e[d]},1g:H(d,e,c){G(e=="2h"||e=="1Z"){J b,3X={30:"5x",5g:"1G",18:"3I"},35=e=="2h"?["5e","6k"]:["5G","6i"];H 5b(){b=e=="2h"?d.8f:d.8c;J a=0,2C=0;D.P(35,H(){a+=3d(D.2a(d,"57"+7,M))||0;2C+=3d(D.2a(d,"2C"+7+"4b",M))||0});b-=29.83(a+2C)}G(D(d).3F(":4j"))5b();N D.6q(d,3X,5b);I 29.2f(0,b)}I D.2a(d,e,c)},2a:H(f,l,k){J e,V=f.V;H 3E(b){G(!D.14.2k)I Q;J a=3P.54(b,U);I!a||a.52("3E")==""}G(l=="1y"&&D.14.1f){e=D.1K(V,"1y");I e==""?"1":e}G(D.14.2G&&l=="18"){J d=V.50;V.50="0 7Y 7W";V.50=d}G(l.1I(/4i/i))l=y;G(!k&&V&&V[l])e=V[l];N G(3P.54){G(l.1I(/4i/i))l="4i";l=l.1o(/([A-Z])/g,"-$1").3y();J c=3P.54(f,U);G(c&&!3E(f))e=c.52(l);N{J g=[],2E=[],a=f,i=0;R(;a&&3E(a);a=a.1d)2E.6h(a);R(;i<2E.K;i++)G(3E(2E[i])){g[i]=2E[i].V.18;2E[i].V.18="3I"}e=l=="18"&&g[2E.K-1]!=U?"2F":(c&&c.52(l))||"";R(i=0;i]*?)\\/>/g,H(b,a,c){I c.1I(/^(aK|4f|7E|aG|4T|7A|aB|3n|az|ay|av)$/i)?b:a+">"});J f=D.3k(d).3y(),1v=h.3h("1v");J e=!f.1h("",""]||!f.1h("",""]||f.1I(/^<(aq|22|am|ak|ai)/)&&[1,"<1T>",""]||!f.1h("<4F")&&[2,"<1T><22>",""]||(!f.1h("<22><4F>",""]||!f.1h("<7E")&&[2,"<1T><22><7q>",""]||D.14.1f&&[1,"1v<1v>",""]||[0,"",""];1v.4H=e[1]+d+e[2];1B(e[0]--)1v=1v.5T;G(D.14.1f){J g=!f.1h("<1T")&&f.1h("<22")<0?1v.1x&&1v.1x.3t:e[1]=="<1T>"&&f.1h("<22")<0?1v.3t:[];R(J j=g.K-1;j>=0;--j)G(D.Y(g[j],"22")&&!g[j].3t.K)g[j].1d.37(g[j]);G(/^\\s/.11(d))1v.39(h.5F(d.1I(/^\\s*/)[0]),1v.1x)}d=D.2d(1v.3t)}G(d.K===0&&(!D.Y(d,"3V")&&!D.Y(d,"2A")))I;G(d[0]==12||D.Y(d,"3V")||d.15)k.1p(d);N k=D.2R(k,d)});I k},1K:H(d,f,c){G(!d||d.16==3||d.16==8)I 12;J e=!D.4n(d),40=c!==12,1f=D.14.1f;f=e&&D.3X[f]||f;G(d.2j){J g=/5Q|4d|V/.11(f);G(f=="2W"&&D.14.2k)d.1d.64;G(f 1n d&&e&&!g){G(40){G(f=="O"&&D.Y(d,"4T")&&d.1d)7p"O a3 a1\'t 9V 9U";d[f]=c}G(D.Y(d,"3V")&&d.7i(f))I d.7i(f).76;I d[f]}G(1f&&e&&f=="V")I D.1K(d.V,"9T",c);G(40)d.9Q(f,""+c);J h=1f&&e&&g?d.4G(f,2):d.4G(f);I h===U?12:h}G(1f&&f=="1y"){G(40){d.6B=1;d.1E=(d.1E||"").1o(/7f\\([^)]*\\)/,"")+(3r(c)+\'\'=="9L"?"":"7f(1y="+c*7a+")")}I d.1E&&d.1E.1h("1y=")>=0?(3d(d.1E.1I(/1y=([^)]*)/)[1])/7a)+\'\':""}f=f.1o(/-([a-z])/9H,H(a,b){I b.2r()});G(40)d[f]=c;I d[f]},3k:H(a){I(a||"").1o(/^\\s+|\\s+$/g,"")},2d:H(b){J a=[];G(b!=U){J i=b.K;G(i==U||b.1R||b.4I||b.1k)a[0]=b;N 1B(i)a[--i]=b[i]}I a},2L:H(b,a){R(J i=0,K=a.K;i*",7).21();1B(7.1x)7.37(7.1x)}},H(a,b){D.17[a]=H(){I 7.P(b,19)}});D.P(["6N","4b"],H(i,c){J b=c.3y();D.17[b]=H(a){I 7[0]==1b?D.14.2G&&S.1c["5t"+c]||D.14.2k&&1b["5s"+c]||S.70=="6Z"&&S.1C["5t"+c]||S.1c["5t"+c]:7[0]==S?29.2f(29.2f(S.1c["4y"+c],S.1C["4y"+c]),29.2f(S.1c["2i"+c],S.1C["2i"+c])):a==12?(7.K?D.1g(7[0],b):U):7.1g(b,a.1q==56?a:a+"2X")}});H 25(a,b){I a[0]&&3r(D.2a(a[0],b,M),10)||0}J C=D.14.2k&&3r(D.14.5B)<8H?"(?:[\\\\w*3m-]|\\\\\\\\.)":"(?:[\\\\w\\8F-\\8E*3m-]|\\\\\\\\.)",6L=2B 4v("^>\\\\s*("+C+"+)"),6J=2B 4v("^("+C+"+)(#)("+C+"+)"),6I=2B 4v("^([#.]?)("+C+"*)");D.1l({6H:{"":H(a,i,m){I m[2]=="*"||D.Y(a,m[2])},"#":H(a,i,m){I a.4G("2v")==m[2]},":":{8D:H(a,i,m){I im[3]-0},3a:H(a,i,m){I m[3]-0==i},79:H(a,i,m){I m[3]-0==i},3o:H(a,i){I i==0},3S:H(a,i,m,r){I i==r.K-1},6D:H(a,i){I i%2==0},6C:H(a,i){I i%2},"3o-4u":H(a){I a.1d.3H("*")[0]==a},"3S-4u":H(a){I D.3a(a.1d.5T,1,"4l")==a},"8z-4u":H(a){I!D.3a(a.1d.5T,2,"4l")},6W:H(a){I a.1x},4E:H(a){I!a.1x},8y:H(a,i,m){I(a.6O||a.8x||D(a).1r()||"").1h(m[3])>=0},4j:H(a){I"1G"!=a.O&&D.1g(a,"18")!="2F"&&D.1g(a,"5g")!="1G"},1G:H(a){I"1G"==a.O||D.1g(a,"18")=="2F"||D.1g(a,"5g")=="1G"},8w:H(a){I!a.3R},3R:H(a){I a.3R},4J:H(a){I a.4J},2W:H(a){I a.2W||D.1K(a,"2W")},1r:H(a){I"1r"==a.O},5O:H(a){I"5O"==a.O},5L:H(a){I"5L"==a.O},5p:H(a){I"5p"==a.O},3Q:H(a){I"3Q"==a.O},5o:H(a){I"5o"==a.O},6A:H(a){I"6A"==a.O},6z:H(a){I"6z"==a.O},2s:H(a){I"2s"==a.O||D.Y(a,"2s")},4T:H(a){I/4T|2A|6y|2s/i.11(a.Y)},3T:H(a,i,m){I D.2q(m[3],a).K},8t:H(a){I/h\\d/i.11(a.Y)},8s:H(a){I D.3C(D.3O,H(b){I a==b.T}).K}}},6x:[/^(\\[) *@?([\\w-]+) *([!*$^~=]*) *(\'?"?)(.*?)\\4 *\\]/,/^(:)([\\w-]+)\\("?\'?(.*?(\\(.*?\\))?[^(]*?)"?\'?\\)/,2B 4v("^([:.#]*)("+C+"+)")],3g:H(a,c,b){J d,1t=[];1B(a&&a!=d){d=a;J f=D.1E(a,c,b);a=f.t.1o(/^\\s*,\\s*/,"");1t=b?c=f.r:D.2R(1t,f.r)}I 1t},2q:H(t,o){G(1j t!="23")I[t];G(o&&o.16!=1&&o.16!=9)I[];o=o||S;J d=[o],2o=[],3S,Y;1B(t&&3S!=t){J r=[];3S=t;t=D.3k(t);J l=Q,3j=6L,m=3j.2D(t);G(m){Y=m[1].2r();R(J i=0;d[i];i++)R(J c=d[i].1x;c;c=c.2H)G(c.16==1&&(Y=="*"||c.Y.2r()==Y))r.1p(c);d=r;t=t.1o(3j,"");G(t.1h(" ")==0)6M;l=M}N{3j=/^([>+~])\\s*(\\w*)/i;G((m=3j.2D(t))!=U){r=[];J k={};Y=m[2].2r();m=m[1];R(J j=0,3i=d.K;j<3i;j++){J n=m=="~"||m=="+"?d[j].2H:d[j].1x;R(;n;n=n.2H)G(n.16==1){J g=D.L(n);G(m=="~"&&k[g])1X;G(!Y||n.Y.2r()==Y){G(m=="~")k[g]=M;r.1p(n)}G(m=="+")1X}}d=r;t=D.3k(t.1o(3j,""));l=M}}G(t&&!l){G(!t.1h(",")){G(o==d[0])d.4s();2o=D.2R(2o,d);r=d=[o];t=" "+t.6v(1,t.K)}N{J h=6J;J m=h.2D(t);G(m){m=[0,m[2],m[3],m[1]]}N{h=6I;m=h.2D(t)}m[2]=m[2].1o(/\\\\/g,"");J f=d[d.K-1];G(m[1]=="#"&&f&&f.61&&!D.4n(f)){J p=f.61(m[2]);G((D.14.1f||D.14.2G)&&p&&1j p.2v=="23"&&p.2v!=m[2])p=D(\'[@2v="\'+m[2]+\'"]\',f)[0];d=r=p&&(!m[3]||D.Y(p,m[3]))?[p]:[]}N{R(J i=0;d[i];i++){J a=m[1]=="#"&&m[3]?m[3]:m[1]!=""||m[0]==""?"*":m[2];G(a=="*"&&d[i].Y.3y()=="49")a="3n";r=D.2R(r,d[i].3H(a))}G(m[1]==".")r=D.5m(r,m[2]);G(m[1]=="#"){J e=[];R(J i=0;r[i];i++)G(r[i].4G("2v")==m[2]){e=[r[i]];1X}r=e}d=r}t=t.1o(h,"")}}G(t){J b=D.1E(t,r);d=r=b.r;t=D.3k(b.t)}}G(t)d=[];G(d&&o==d[0])d.4s();2o=D.2R(2o,d);I 2o},5m:H(r,m,a){m=" "+m+" ";J c=[];R(J i=0;r[i];i++){J b=(" "+r[i].1F+" ").1h(m)>=0;G(!a&&b||a&&!b)c.1p(r[i])}I c},1E:H(t,r,h){J d;1B(t&&t!=d){d=t;J p=D.6x,m;R(J i=0;p[i];i++){m=p[i].2D(t);G(m){t=t.8r(m[0].K);m[2]=m[2].1o(/\\\\/g,"");1X}}G(!m)1X;G(m[1]==":"&&m[2]=="4Y")r=62.11(m[3])?D.1E(m[3],r,M).r:D(r).4Y(m[3]);N G(m[1]==".")r=D.5m(r,m[2],h);N G(m[1]=="["){J g=[],O=m[3];R(J i=0,3i=r.K;i<3i;i++){J a=r[i],z=a[D.3X[m[2]]||m[2]];G(z==U||/5Q|4d|2W/.11(m[2]))z=D.1K(a,m[2])||\'\';G((O==""&&!!z||O=="="&&z==m[5]||O=="!="&&z!=m[5]||O=="^="&&z&&!z.1h(m[5])||O=="$="&&z.6v(z.K-m[5].K)==m[5]||(O=="*="||O=="~=")&&z.1h(m[5])>=0)^h)g.1p(a)}r=g}N G(m[1]==":"&&m[2]=="3a-4u"){J e={},g=[],11=/(-?)(\\d*)n((?:\\+|-)?\\d*)/.2D(m[3]=="6D"&&"2n"||m[3]=="6C"&&"2n+1"||!/\\D/.11(m[3])&&"8q+"+m[3]||m[3]),3o=(11[1]+(11[2]||1))-0,d=11[3]-0;R(J i=0,3i=r.K;i<3i;i++){J j=r[i],1d=j.1d,2v=D.L(1d);G(!e[2v]){J c=1;R(J n=1d.1x;n;n=n.2H)G(n.16==1)n.4q=c++;e[2v]=M}J b=Q;G(3o==0){G(j.4q==d)b=M}N G((j.4q-d)%3o==0&&(j.4q-d)/3o>=0)b=M;G(b^h)g.1p(j)}r=g}N{J f=D.6H[m[1]];G(1j f=="49")f=f[m[2]];G(1j f=="23")f=6u("Q||H(a,i){I "+f+";}");r=D.3C(r,H(a,i){I f(a,i,m,r)},h)}}I{r:r,t:t}},4S:H(b,c){J a=[],1t=b[c];1B(1t&&1t!=S){G(1t.16==1)a.1p(1t);1t=1t[c]}I a},3a:H(a,e,c,b){e=e||1;J d=0;R(;a;a=a[c])G(a.16==1&&++d==e)1X;I a},5v:H(n,a){J r=[];R(;n;n=n.2H){G(n.16==1&&n!=a)r.1p(n)}I r}});D.W={1e:H(f,i,g,e){G(f.16==3||f.16==8)I;G(D.14.1f&&f.4I)f=1b;G(!g.24)g.24=7.24++;G(e!=12){J h=g;g=7.3M(h,H(){I h.1w(7,19)});g.L=e}J j=D.L(f,"3w")||D.L(f,"3w",{}),1H=D.L(f,"1H")||D.L(f,"1H",H(){G(1j D!="12"&&!D.W.5k)I D.W.1H.1w(19.3L.T,19)});1H.T=f;D.P(i.1R(/\\s+/),H(c,b){J a=b.1R(".");b=a[0];g.O=a[1];J d=j[b];G(!d){d=j[b]={};G(!D.W.2t[b]||D.W.2t[b].4p.1k(f)===Q){G(f.3K)f.3K(b,1H,Q);N G(f.6t)f.6t("4o"+b,1H)}}d[g.24]=g;D.W.26[b]=M});f=U},24:1,26:{},21:H(e,h,f){G(e.16==3||e.16==8)I;J i=D.L(e,"3w"),1L,5i;G(i){G(h==12||(1j h=="23"&&h.8p(0)=="."))R(J g 1n i)7.21(e,g+(h||""));N{G(h.O){f=h.2y;h=h.O}D.P(h.1R(/\\s+/),H(b,a){J c=a.1R(".");a=c[0];G(i[a]){G(f)2U i[a][f.24];N R(f 1n i[a])G(!c[1]||i[a][f].O==c[1])2U i[a][f];R(1L 1n i[a])1X;G(!1L){G(!D.W.2t[a]||D.W.2t[a].4A.1k(e)===Q){G(e.6p)e.6p(a,D.L(e,"1H"),Q);N G(e.6n)e.6n("4o"+a,D.L(e,"1H"))}1L=U;2U i[a]}}})}R(1L 1n i)1X;G(!1L){J d=D.L(e,"1H");G(d)d.T=U;D.3b(e,"3w");D.3b(e,"1H")}}},1P:H(h,c,f,g,i){c=D.2d(c);G(h.1h("!")>=0){h=h.3s(0,-1);J a=M}G(!f){G(7.26[h])D("*").1e([1b,S]).1P(h,c)}N{G(f.16==3||f.16==8)I 12;J b,1L,17=D.1D(f[h]||U),W=!c[0]||!c[0].32;G(W){c.6h({O:h,2J:f,32:H(){},3J:H(){},4C:1z()});c[0][E]=M}c[0].O=h;G(a)c[0].6m=M;J d=D.L(f,"1H");G(d)b=d.1w(f,c);G((!17||(D.Y(f,\'a\')&&h=="4V"))&&f["4o"+h]&&f["4o"+h].1w(f,c)===Q)b=Q;G(W)c.4s();G(i&&D.1D(i)){1L=i.1w(f,b==U?c:c.7d(b));G(1L!==12)b=1L}G(17&&g!==Q&&b!==Q&&!(D.Y(f,\'a\')&&h=="4V")){7.5k=M;1U{f[h]()}1V(e){}}7.5k=Q}I b},1H:H(b){J a,1L,38,5f,4m;b=19[0]=D.W.6l(b||1b.W);38=b.O.1R(".");b.O=38[0];38=38[1];5f=!38&&!b.6m;4m=(D.L(7,"3w")||{})[b.O];R(J j 1n 4m){J c=4m[j];G(5f||c.O==38){b.2y=c;b.L=c.L;1L=c.1w(7,19);G(a!==Q)a=1L;G(1L===Q){b.32();b.3J()}}}I a},6l:H(b){G(b[E]==M)I b;J d=b;b={8o:d};J c="8n 8m 8l 8k 2s 8j 47 5d 6j 5E 8i L 8h 8g 4K 2y 5a 59 8e 8b 58 6f 8a 88 4k 87 86 84 6d 2J 4C 6c O 82 81 35".1R(" ");R(J i=c.K;i;i--)b[c[i]]=d[c[i]];b[E]=M;b.32=H(){G(d.32)d.32();d.80=Q};b.3J=H(){G(d.3J)d.3J();d.7Z=M};b.4C=b.4C||1z();G(!b.2J)b.2J=b.6d||S;G(b.2J.16==3)b.2J=b.2J.1d;G(!b.4k&&b.4K)b.4k=b.4K==b.2J?b.6c:b.4K;G(b.58==U&&b.5d!=U){J a=S.1C,1c=S.1c;b.58=b.5d+(a&&a.2e||1c&&1c.2e||0)-(a.6b||0);b.6f=b.6j+(a&&a.2c||1c&&1c.2c||0)-(a.6a||0)}G(!b.35&&((b.47||b.47===0)?b.47:b.5a))b.35=b.47||b.5a;G(!b.59&&b.5E)b.59=b.5E;G(!b.35&&b.2s)b.35=(b.2s&1?1:(b.2s&2?3:(b.2s&4?2:0)));I b},3M:H(a,b){b.24=a.24=a.24||b.24||7.24++;I b},2t:{27:{4p:H(){55();I},4A:H(){I}},3D:{4p:H(){G(D.14.1f)I Q;D(7).2O("53",D.W.2t.3D.2y);I M},4A:H(){G(D.14.1f)I Q;D(7).4e("53",D.W.2t.3D.2y);I M},2y:H(a){G(F(a,7))I M;a.O="3D";I D.W.1H.1w(7,19)}},3N:{4p:H(){G(D.14.1f)I Q;D(7).2O("51",D.W.2t.3N.2y);I M},4A:H(){G(D.14.1f)I Q;D(7).4e("51",D.W.2t.3N.2y);I M},2y:H(a){G(F(a,7))I M;a.O="3N";I D.W.1H.1w(7,19)}}}};D.17.1l({2O:H(c,a,b){I c=="4X"?7.2V(c,a,b):7.P(H(){D.W.1e(7,c,b||a,b&&a)})},2V:H(d,b,c){J e=D.W.3M(c||b,H(a){D(7).4e(a,e);I(c||b).1w(7,19)});I 7.P(H(){D.W.1e(7,d,e,c&&b)})},4e:H(a,b){I 7.P(H(){D.W.21(7,a,b)})},1P:H(c,a,b){I 7.P(H(){D.W.1P(c,a,7,M,b)})},5C:H(c,a,b){I 7[0]&&D.W.1P(c,a,7[0],Q,b)},2m:H(b){J c=19,i=1;1B(i=0){J i=g.3s(e,g.K);g=g.3s(0,e)}c=c||H(){};J f="2P";G(d)G(D.1D(d)){c=d;d=U}N{d=D.3n(d);f="6g"}J h=7;D.3Y({1a:g,O:f,1O:"2K",L:d,1J:H(a,b){G(b=="1W"||b=="7J")h.2K(i?D("<1v/>").3v(a.4U.1o(/<1m(.|\\s)*?\\/1m>/g,"")).2q(i):a.4U);h.P(c,[a.4U,b,a])}});I 7},aL:H(){I D.3n(7.7I())},7I:H(){I 7.2l(H(){I D.Y(7,"3V")?D.2d(7.aH):7}).1E(H(){I 7.34&&!7.3R&&(7.4J||/2A|6y/i.11(7.Y)||/1r|1G|3Q/i.11(7.O))}).2l(H(i,c){J b=D(7).6e();I b==U?U:b.1q==2p?D.2l(b,H(a,i){I{34:c.34,2x:a}}):{34:c.34,2x:b}}).3p()}});D.P("7H,7G,7F,7D,7C,7B".1R(","),H(i,o){D.17[o]=H(f){I 7.2O(o,f)}});J B=1z();D.1l({3p:H(d,b,a,c){G(D.1D(b)){a=b;b=U}I D.3Y({O:"2P",1a:d,L:b,1W:a,1O:c})},aE:H(b,a){I D.3p(b,U,a,"1m")},aD:H(c,b,a){I D.3p(c,b,a,"3z")},aC:H(d,b,a,c){G(D.1D(b)){a=b;b={}}I D.3Y({O:"6g",1a:d,L:b,1W:a,1O:c})},aA:H(a){D.1l(D.60,a)},60:{1a:5Z.5Q,26:M,O:"2P",2T:0,7z:"4R/x-ax-3V-aw",7x:M,31:M,L:U,5Y:U,3Q:U,4Q:{2N:"4R/2N, 1r/2N",2K:"1r/2K",1m:"1r/4t, 4R/4t",3z:"4R/3z, 1r/4t",1r:"1r/as",4w:"*/*"}},4z:{},3Y:H(s){s=D.1l(M,s,D.1l(M,{},D.60,s));J g,2Z=/=\\?(&|$)/g,1u,L,O=s.O.2r();G(s.L&&s.7x&&1j s.L!="23")s.L=D.3n(s.L);G(s.1O=="4P"){G(O=="2P"){G(!s.1a.1I(2Z))s.1a+=(s.1a.1I(/\\?/)?"&":"?")+(s.4P||"7u")+"=?"}N G(!s.L||!s.L.1I(2Z))s.L=(s.L?s.L+"&":"")+(s.4P||"7u")+"=?";s.1O="3z"}G(s.1O=="3z"&&(s.L&&s.L.1I(2Z)||s.1a.1I(2Z))){g="4P"+B++;G(s.L)s.L=(s.L+"").1o(2Z,"="+g+"$1");s.1a=s.1a.1o(2Z,"="+g+"$1");s.1O="1m";1b[g]=H(a){L=a;1W();1J();1b[g]=12;1U{2U 1b[g]}1V(e){}G(i)i.37(h)}}G(s.1O=="1m"&&s.1Y==U)s.1Y=Q;G(s.1Y===Q&&O=="2P"){J j=1z();J k=s.1a.1o(/(\\?|&)3m=.*?(&|$)/,"$ap="+j+"$2");s.1a=k+((k==s.1a)?(s.1a.1I(/\\?/)?"&":"?")+"3m="+j:"")}G(s.L&&O=="2P"){s.1a+=(s.1a.1I(/\\?/)?"&":"?")+s.L;s.L=U}G(s.26&&!D.4O++)D.W.1P("7H");J n=/^(?:\\w+:)?\\/\\/([^\\/?#]+)/;G(s.1O=="1m"&&O=="2P"&&n.11(s.1a)&&n.2D(s.1a)[1]!=5Z.al){J i=S.3H("6w")[0];J h=S.3h("1m");h.4d=s.1a;G(s.7t)h.aj=s.7t;G(!g){J l=Q;h.ah=h.ag=H(){G(!l&&(!7.3f||7.3f=="68"||7.3f=="1J")){l=M;1W();1J();i.37(h)}}}i.3U(h);I 12}J m=Q;J c=1b.7s?2B 7s("ae.ac"):2B 7r();G(s.5Y)c.6R(O,s.1a,s.31,s.5Y,s.3Q);N c.6R(O,s.1a,s.31);1U{G(s.L)c.4B("ab-aa",s.7z);G(s.5S)c.4B("a9-5R-a8",D.4z[s.1a]||"a7, a6 a5 a4 5N:5N:5N a2");c.4B("X-9Z-9Y","7r");c.4B("9W",s.1O&&s.4Q[s.1O]?s.4Q[s.1O]+", */*":s.4Q.4w)}1V(e){}G(s.7m&&s.7m(c,s)===Q){s.26&&D.4O--;c.7l();I Q}G(s.26)D.W.1P("7B",[c,s]);J d=H(a){G(!m&&c&&(c.3f==4||a=="2T")){m=M;G(f){7k(f);f=U}1u=a=="2T"&&"2T"||!D.7j(c)&&"3e"||s.5S&&D.7h(c,s.1a)&&"7J"||"1W";G(1u=="1W"){1U{L=D.6X(c,s.1O,s.9S)}1V(e){1u="5J"}}G(1u=="1W"){J b;1U{b=c.5I("7g-5R")}1V(e){}G(s.5S&&b)D.4z[s.1a]=b;G(!g)1W()}N D.5H(s,c,1u);1J();G(s.31)c=U}};G(s.31){J f=4I(d,13);G(s.2T>0)3B(H(){G(c){c.7l();G(!m)d("2T")}},s.2T)}1U{c.9P(s.L)}1V(e){D.5H(s,c,U,e)}G(!s.31)d();H 1W(){G(s.1W)s.1W(L,1u);G(s.26)D.W.1P("7C",[c,s])}H 1J(){G(s.1J)s.1J(c,1u);G(s.26)D.W.1P("7F",[c,s]);G(s.26&&!--D.4O)D.W.1P("7G")}I c},5H:H(s,a,b,e){G(s.3e)s.3e(a,b,e);G(s.26)D.W.1P("7D",[a,s,e])},4O:0,7j:H(a){1U{I!a.1u&&5Z.9O=="5p:"||(a.1u>=7e&&a.1u<9N)||a.1u==7c||a.1u==9K||D.14.2k&&a.1u==12}1V(e){}I Q},7h:H(a,c){1U{J b=a.5I("7g-5R");I a.1u==7c||b==D.4z[c]||D.14.2k&&a.1u==12}1V(e){}I Q},6X:H(a,c,b){J d=a.5I("9J-O"),2N=c=="2N"||!c&&d&&d.1h("2N")>=0,L=2N?a.9I:a.4U;G(2N&&L.1C.2j=="5J")7p"5J";G(b)L=b(L,c);G(c=="1m")D.5u(L);G(c=="3z")L=6u("("+L+")");I L},3n:H(a){J s=[];G(a.1q==2p||a.5w)D.P(a,H(){s.1p(3u(7.34)+"="+3u(7.2x))});N R(J j 1n a)G(a[j]&&a[j].1q==2p)D.P(a[j],H(){s.1p(3u(j)+"="+3u(7))});N s.1p(3u(j)+"="+3u(D.1D(a[j])?a[j]():a[j]));I s.6s("&").1o(/%20/g,"+")}});D.17.1l({1N:H(c,b){I c?7.2g({1Z:"1N",2h:"1N",1y:"1N"},c,b):7.1E(":1G").P(H(){7.V.18=7.5D||"";G(D.1g(7,"18")=="2F"){J a=D("<"+7.2j+" />").6P("1c");7.V.18=a.1g("18");G(7.V.18=="2F")7.V.18="3I";a.21()}}).3l()},1M:H(b,a){I b?7.2g({1Z:"1M",2h:"1M",1y:"1M"},b,a):7.1E(":4j").P(H(){7.5D=7.5D||D.1g(7,"18");7.V.18="2F"}).3l()},78:D.17.2m,2m:H(a,b){I D.1D(a)&&D.1D(b)?7.78.1w(7,19):a?7.2g({1Z:"2m",2h:"2m",1y:"2m"},a,b):7.P(H(){D(7)[D(7).3F(":1G")?"1N":"1M"]()})},9G:H(b,a){I 7.2g({1Z:"1N"},b,a)},9F:H(b,a){I 7.2g({1Z:"1M"},b,a)},9E:H(b,a){I 7.2g({1Z:"2m"},b,a)},9D:H(b,a){I 7.2g({1y:"1N"},b,a)},9M:H(b,a){I 7.2g({1y:"1M"},b,a)},9C:H(c,a,b){I 7.2g({1y:a},c,b)},2g:H(k,j,i,g){J h=D.77(j,i,g);I 7[h.36===Q?"P":"36"](H(){G(7.16!=1)I Q;J f=D.1l({},h),p,1G=D(7).3F(":1G"),46=7;R(p 1n k){G(k[p]=="1M"&&1G||k[p]=="1N"&&!1G)I f.1J.1k(7);G(p=="1Z"||p=="2h"){f.18=D.1g(7,"18");f.33=7.V.33}}G(f.33!=U)7.V.33="1G";f.45=D.1l({},k);D.P(k,H(c,a){J e=2B D.28(46,f,c);G(/2m|1N|1M/.11(a))e[a=="2m"?1G?"1N":"1M":a](k);N{J b=a.6r().1I(/^([+-]=)?([\\d+-.]+)(.*)$/),2b=e.1t(M)||0;G(b){J d=3d(b[2]),2M=b[3]||"2X";G(2M!="2X"){46.V[c]=(d||1)+2M;2b=((d||1)/e.1t(M))*2b;46.V[c]=2b+2M}G(b[1])d=((b[1]=="-="?-1:1)*d)+2b;e.3G(2b,d,2M)}N e.3G(2b,a,"")}});I M})},36:H(a,b){G(D.1D(a)||(a&&a.1q==2p)){b=a;a="28"}G(!a||(1j a=="23"&&!b))I A(7[0],a);I 7.P(H(){G(b.1q==2p)A(7,a,b);N{A(7,a).1p(b);G(A(7,a).K==1)b.1k(7)}})},9X:H(b,c){J a=D.3O;G(b)7.36([]);7.P(H(){R(J i=a.K-1;i>=0;i--)G(a[i].T==7){G(c)a[i](M);a.7n(i,1)}});G(!c)7.5A();I 7}});J A=H(b,c,a){G(b){c=c||"28";J q=D.L(b,c+"36");G(!q||a)q=D.L(b,c+"36",D.2d(a))}I q};D.17.5A=H(a){a=a||"28";I 7.P(H(){J q=A(7,a);q.4s();G(q.K)q[0].1k(7)})};D.1l({77:H(b,a,c){J d=b&&b.1q==a0?b:{1J:c||!c&&a||D.1D(b)&&b,2u:b,41:c&&a||a&&a.1q!=9t&&a};d.2u=(d.2u&&d.2u.1q==4L?d.2u:D.28.5K[d.2u])||D.28.5K.74;d.5M=d.1J;d.1J=H(){G(d.36!==Q)D(7).5A();G(D.1D(d.5M))d.5M.1k(7)};I d},41:{73:H(p,n,b,a){I b+a*p},5P:H(p,n,b,a){I((-29.9r(p*29.9q)/2)+0.5)*a+b}},3O:[],48:U,28:H(b,c,a){7.15=c;7.T=b;7.1i=a;G(!c.3Z)c.3Z={}}});D.28.44={4D:H(){G(7.15.2Y)7.15.2Y.1k(7.T,7.1z,7);(D.28.2Y[7.1i]||D.28.2Y.4w)(7);G(7.1i=="1Z"||7.1i=="2h")7.T.V.18="3I"},1t:H(a){G(7.T[7.1i]!=U&&7.T.V[7.1i]==U)I 7.T[7.1i];J r=3d(D.1g(7.T,7.1i,a));I r&&r>-9p?r:3d(D.2a(7.T,7.1i))||0},3G:H(c,b,d){7.5V=1z();7.2b=c;7.3l=b;7.2M=d||7.2M||"2X";7.1z=7.2b;7.2S=7.4N=0;7.4D();J e=7;H t(a){I e.2Y(a)}t.T=7.T;D.3O.1p(t);G(D.48==U){D.48=4I(H(){J a=D.3O;R(J i=0;i7.15.2u+7.5V){7.1z=7.3l;7.2S=7.4N=1;7.4D();7.15.45[7.1i]=M;J b=M;R(J i 1n 7.15.45)G(7.15.45[i]!==M)b=Q;G(b){G(7.15.18!=U){7.T.V.33=7.15.33;7.T.V.18=7.15.18;G(D.1g(7.T,"18")=="2F")7.T.V.18="3I"}G(7.15.1M)7.T.V.18="2F";G(7.15.1M||7.15.1N)R(J p 1n 7.15.45)D.1K(7.T.V,p,7.15.3Z[p])}G(b)7.15.1J.1k(7.T);I Q}N{J n=t-7.5V;7.4N=n/7.15.2u;7.2S=D.41[7.15.41||(D.41.5P?"5P":"73")](7.4N,n,0,1,7.15.2u);7.1z=7.2b+((7.3l-7.2b)*7.2S);7.4D()}I M}};D.1l(D.28,{5K:{9l:9j,9i:7e,74:9g},2Y:{2e:H(a){a.T.2e=a.1z},2c:H(a){a.T.2c=a.1z},1y:H(a){D.1K(a.T.V,"1y",a.1z)},4w:H(a){a.T.V[a.1i]=a.1z+a.2M}}});D.17.2i=H(){J b=0,1S=0,T=7[0],3q;G(T)ao(D.14){J d=T.1d,4a=T,1s=T.1s,1Q=T.2z,5U=2k&&3r(5B)<9c&&!/9a/i.11(v),1g=D.2a,3c=1g(T,"30")=="3c";G(T.7y){J c=T.7y();1e(c.1A+29.2f(1Q.1C.2e,1Q.1c.2e),c.1S+29.2f(1Q.1C.2c,1Q.1c.2c));1e(-1Q.1C.6b,-1Q.1C.6a)}N{1e(T.5X,T.5W);1B(1s){1e(1s.5X,1s.5W);G(42&&!/^t(98|d|h)$/i.11(1s.2j)||2k&&!5U)2C(1s);G(!3c&&1g(1s,"30")=="3c")3c=M;4a=/^1c$/i.11(1s.2j)?4a:1s;1s=1s.1s}1B(d&&d.2j&&!/^1c|2K$/i.11(d.2j)){G(!/^96|1T.*$/i.11(1g(d,"18")))1e(-d.2e,-d.2c);G(42&&1g(d,"33")!="4j")2C(d);d=d.1d}G((5U&&(3c||1g(4a,"30")=="5x"))||(42&&1g(4a,"30")!="5x"))1e(-1Q.1c.5X,-1Q.1c.5W);G(3c)1e(29.2f(1Q.1C.2e,1Q.1c.2e),29.2f(1Q.1C.2c,1Q.1c.2c))}3q={1S:1S,1A:b}}H 2C(a){1e(D.2a(a,"6V",M),D.2a(a,"6U",M))}H 1e(l,t){b+=3r(l,10)||0;1S+=3r(t,10)||0}I 3q};D.17.1l({30:H(){J a=0,1S=0,3q;G(7[0]){J b=7.1s(),2i=7.2i(),4c=/^1c|2K$/i.11(b[0].2j)?{1S:0,1A:0}:b.2i();2i.1S-=25(7,\'94\');2i.1A-=25(7,\'aF\');4c.1S+=25(b,\'6U\');4c.1A+=25(b,\'6V\');3q={1S:2i.1S-4c.1S,1A:2i.1A-4c.1A}}I 3q},1s:H(){J a=7[0].1s;1B(a&&(!/^1c|2K$/i.11(a.2j)&&D.1g(a,\'30\')==\'93\'))a=a.1s;I D(a)}});D.P([\'5e\',\'5G\'],H(i,b){J c=\'4y\'+b;D.17[c]=H(a){G(!7[0])I;I a!=12?7.P(H(){7==1b||7==S?1b.92(!i?a:D(1b).2e(),i?a:D(1b).2c()):7[c]=a}):7[0]==1b||7[0]==S?46[i?\'aI\':\'aJ\']||D.71&&S.1C[c]||S.1c[c]:7[0][c]}});D.P(["6N","4b"],H(i,b){J c=i?"5e":"5G",4f=i?"6k":"6i";D.17["5s"+b]=H(){I 7[b.3y()]()+25(7,"57"+c)+25(7,"57"+4f)};D.17["90"+b]=H(a){I 7["5s"+b]()+25(7,"2C"+c+"4b")+25(7,"2C"+4f+"4b")+(a?25(7,"6S"+c)+25(7,"6S"+4f):0)}})})();',62,669,'|||||||this|||||||||||||||||||||||||||||||||||if|function|return|var|length|data|true|else|type|each|false|for|document|elem|null|style|event||nodeName|||test|undefined||browser|options|nodeType|fn|display|arguments|url|window|body|parentNode|add|msie|css|indexOf|prop|typeof|call|extend|script|in|replace|push|constructor|text|offsetParent|cur|status|div|apply|firstChild|opacity|now|left|while|documentElement|isFunction|filter|className|hidden|handle|match|complete|attr|ret|hide|show|dataType|trigger|doc|split|top|table|try|catch|success|break|cache|height||remove|tbody|string|guid|num|global|ready|fx|Math|curCSS|start|scrollTop|makeArray|scrollLeft|max|animate|width|offset|tagName|safari|map|toggle||done|Array|find|toUpperCase|button|special|duration|id|copy|value|handler|ownerDocument|select|new|border|exec|stack|none|opera|nextSibling|pushStack|target|html|inArray|unit|xml|bind|GET|isReady|merge|pos|timeout|delete|one|selected|px|step|jsre|position|async|preventDefault|overflow|name|which|queue|removeChild|namespace|insertBefore|nth|removeData|fixed|parseFloat|error|readyState|multiFilter|createElement|rl|re|trim|end|_|param|first|get|results|parseInt|slice|childNodes|encodeURIComponent|append|events|elems|toLowerCase|json|readyList|setTimeout|grep|mouseenter|color|is|custom|getElementsByTagName|block|stopPropagation|addEventListener|callee|proxy|mouseleave|timers|defaultView|password|disabled|last|has|appendChild|form|domManip|props|ajax|orig|set|easing|mozilla|load|prototype|curAnim|self|charCode|timerId|object|offsetChild|Width|parentOffset|src|unbind|br|currentStyle|clean|float|visible|relatedTarget|previousSibling|handlers|isXMLDoc|on|setup|nodeIndex|unique|shift|javascript|child|RegExp|_default|deep|scroll|lastModified|teardown|setRequestHeader|timeStamp|update|empty|tr|getAttribute|innerHTML|setInterval|checked|fromElement|Number|jQuery|state|active|jsonp|accepts|application|dir|input|responseText|click|styleSheets|unload|not|lastToggle|outline|mouseout|getPropertyValue|mouseover|getComputedStyle|bindReady|String|padding|pageX|metaKey|keyCode|getWH|andSelf|clientX|Left|all|visibility|container|index|init|triggered|removeAttribute|classFilter|prevObject|submit|file|after|windowData|inner|client|globalEval|sibling|jquery|absolute|clone|wrapAll|dequeue|version|triggerHandler|oldblock|ctrlKey|createTextNode|Top|handleError|getResponseHeader|parsererror|speeds|checkbox|old|00|radio|swing|href|Modified|ifModified|lastChild|safari2|startTime|offsetTop|offsetLeft|username|location|ajaxSettings|getElementById|isSimple|values|selectedIndex|runtimeStyle|rsLeft|_load|loaded|DOMContentLoaded|clientTop|clientLeft|toElement|srcElement|val|pageY|POST|unshift|Bottom|clientY|Right|fix|exclusive|detachEvent|cloneNode|removeEventListener|swap|toString|join|attachEvent|eval|substr|head|parse|textarea|reset|image|zoom|odd|even|before|prepend|exclude|expr|quickClass|quickID|uuid|quickChild|continue|Height|textContent|appendTo|contents|open|margin|evalScript|borderTopWidth|borderLeftWidth|parent|httpData|setArray|CSS1Compat|compatMode|boxModel|cssFloat|linear|def|webkit|nodeValue|speed|_toggle|eq|100|replaceWith|304|concat|200|alpha|Last|httpNotModified|getAttributeNode|httpSuccess|clearInterval|abort|beforeSend|splice|styleFloat|throw|colgroup|XMLHttpRequest|ActiveXObject|scriptCharset|callback|fieldset|multiple|processData|getBoundingClientRect|contentType|link|ajaxSend|ajaxSuccess|ajaxError|col|ajaxComplete|ajaxStop|ajaxStart|serializeArray|notmodified|keypress|keydown|change|mouseup|mousedown|dblclick|focus|blur|stylesheet|hasClass|rel|doScroll|black|hover|solid|cancelBubble|returnValue|wheelDelta|view|round|shiftKey|resize|screenY|screenX|relatedNode|mousemove|prevValue|originalTarget|offsetHeight|keyup|newValue|offsetWidth|eventPhase|detail|currentTarget|cancelable|bubbles|attrName|attrChange|altKey|originalEvent|charAt|0n|substring|animated|header|noConflict|line|enabled|innerText|contains|only|weight|font|gt|lt|uFFFF|u0128|size|417|Boolean|Date|toggleClass|removeClass|addClass|removeAttr|replaceAll|insertAfter|prependTo|wrap|contentWindow|contentDocument|iframe|children|siblings|prevAll|wrapInner|nextAll|outer|prev|scrollTo|static|marginTop|next|inline|parents|able|cellSpacing|adobeair|cellspacing|522|maxLength|maxlength|readOnly|400|readonly|fast|600|class|slow|1px|htmlFor|reverse|10000|PI|cos|compatible|Function|setData|ie|ra|it|rv|getData|userAgent|navigator|fadeTo|fadeIn|slideToggle|slideUp|slideDown|ig|responseXML|content|1223|NaN|fadeOut|300|protocol|send|setAttribute|option|dataFilter|cssText|changed|be|Accept|stop|With|Requested|Object|can|GMT|property|1970|Jan|01|Thu|Since|If|Type|Content|XMLHTTP|th|Microsoft|td|onreadystatechange|onload|cap|charset|colg|host|tfoot|specified|with|1_|thead|leg|plain|attributes|opt|embed|urlencoded|www|area|hr|ajaxSetup|meta|post|getJSON|getScript|marginLeft|img|elements|pageYOffset|pageXOffset|abbr|serialize|pixelLeft'.split('|'),0,{})) \ No newline at end of file diff --git a/events/vendors/jquery_flickr.js b/events/vendors/jquery_flickr.js new file mode 100644 index 0000000..1534df8 --- /dev/null +++ b/events/vendors/jquery_flickr.js @@ -0,0 +1,111 @@ +/* + * jQuery Flickr - jQuery plug-in + * Version 1.0, Released 2008.04.17 + * + * Copyright (c) 2008 Daniel MacDonald (www.projectatomic.com) + * Dual licensed GPL http://www.gnu.org/licenses/gpl.html + * and MIT http://www.opensource.org/licenses/mit-license.php + */ +(function($) { +$.fn.flickr = function(o){ +var s = { + api_key: null, // [string] required, see http://www.flickr.com/services/api/misc.api_keys.html + type: null, // [string] allowed values: 'photoset', 'search', default: 'flickr.photos.getRecent' + photoset_id: null, // [string] required, for type=='photoset' + text: null, // [string] for type=='search' free text search + user_id: null, // [string] for type=='search' search by user id + group_id: null, // [string] for type=='search' search by group id + tags: null, // [string] for type=='search' comma separated list + tag_mode: 'any', // [string] for type=='search' allowed values: 'any' (OR), 'all' (AND) + sort: 'relevance', // [string] for type=='search' allowed values: 'date-posted-asc', 'date-posted-desc', 'date-taken-asc', 'date-taken-desc', 'interestingness-desc', 'interestingness-asc', 'relevance' + thumb_size: 's', // [string] allowed values: 's' (75x75), 't' (100x?), 'm' (240x?) + size: null, // [string] allowed values: 'm' (240x?), 'b' (1024x?), 'o' (original), default: (500x?) + per_page: 100, // [integer] allowed values: max of 500 + page: 1, // [integer] see paging notes + attr: '', // [string] optional, attributes applied to thumbnail tag + api_url: null, // [string] optional, custom url that returns flickr JSON or JSON-P 'photos' or 'photoset' + params: '', // [string] optional, custom arguments, see http://www.flickr.com/services/api/flickr.photos.search.html + api_callback: '?', // [string] optional, custom callback in flickr JSON-P response + callback: null // [function] optional, callback function applied to entire
    + + // PAGING NOTES: jQuery Flickr plug-in does not provide paging functionality, but does provide hooks for a custom paging routine + // within the
      created by the plug-in, there are two hidden tags, + // input:eq(0): current page, input:eq(1): total number of pages, input:eq(2): images per page, input:eq(3): total number of images + + // SEARCH NOTES: when setting type to 'search' at least one search parameter must also be passed text, user_id, group_id, or tags + + // SIZE NOTES: photos must allow viewing original size for size 'o' to function, if not, default size is shown + }; + if(o) $.extend(s, o); + return this.each(function(){ + // create unordered list to contain flickr images + var list = $('
        ').appendTo(this); + var url = $.flickr.format(s); + $.getJSON(url, function(r){ + if (r.stat != "ok"){ + for (i in r){ + $('
      • ').text(i+': '+ r[i]).appendTo(list); + }; + } else { + if (s.type == 'photoset') r.photos = r.photoset; + // add hooks to access paging data + list.append(''); + list.append(''); + list.append(''); + list.append(''); + for (var i=0; i'+photo['title']+'
      • '); + }; + if (s.callback) s.callback(list); + }; + }); + }); +}; +// static function to format the flickr API url according to the plug-in settings +$.flickr = { + format: function(s){ + if (s.url) return s.url; + var url = 'http://api.flickr.com/services/rest/?format=json&jsoncallback='+s.api_callback+'&api_key='+s.api_key; + switch (s.type){ + case 'photoset': + url += '&method=flickr.photosets.getPhotos&photoset_id=' + s.photoset_id; + break; + case 'search': + url += '&method=flickr.photos.search&sort=' + s.sort; + if (s.user_id) url += '&user_id=' + s.user_id; + if (s.group_id) url += '&group_id=' + s.group_id; + if (s.tags) url += '&tags=' + s.tags; + if (s.tag_mode) url += '&tag_mode=' + s.tag_mode; + if (s.text) url += '&text=' + s.text; + break; + default: + url += '&method=flickr.photos.getRecent'; + }; + if (s.size == 'o') url += '&extras=original_format'; + url += '&per_page=' + s.per_page + '&page=' + s.page + s.params; + return url; + } +}; +})(jQuery); \ No newline at end of file diff --git a/external.php b/external.php new file mode 100644 index 0000000..b0e0d49 --- /dev/null +++ b/external.php @@ -0,0 +1,63 @@ + + + + + Elgg - Open Source Social Networking Engine. + + + + + + + + + +
        +
        + +
        +

        External Projects

        +

        The following is a list of various personal Elgg projects hosted elsewhere. These projects are not connected to the main Elgg project but they do use Elgg and build add-ons for the platform.

        +

        If you know of any others that you think should be listed here, please send details to dave@elgg.com.

        + +
        +
        +
        + +
        + + + + \ No newline at end of file diff --git a/features.php b/features.php new file mode 100644 index 0000000..5a6bcb5 --- /dev/null +++ b/features.php @@ -0,0 +1,82 @@ + + + + + Elgg - Open Source Social Networking Platform. + + + + + + + + + +
        +
        + +
        +

        Highlighed features

        +
        +

        Powerful Data Model
        + Elgg provides a powerful data model making the creation of different entities simple, yet flexible. +

        +

        Activity Streams
        + The granular activity stream API ensures your plugins can push the required content to your users. +

        +

        Plugin API
        + Use Elgg's powerful plugin API to build and add your required features. +

        +

        User Management
        + Elgg handles your user management and relationship requirements. +

        +

        Access controls
        + All objects in Elgg can have an access control level applied making granular access permissions possible. +

        +

        Web Services API
        + Expose functionality through the REST API by building a plugin and then either publish the API for other developers to build clients or provide your own. +

        +
        + +
        +

        Browse the plugins gallery to find other exciting features to add to your Elgg network.

        +
        +
        +
        + +
        + + + + \ No newline at end of file diff --git a/getelgg.php b/getelgg.php new file mode 100644 index 0000000..871b82e --- /dev/null +++ b/getelgg.php @@ -0,0 +1,32 @@ +total; + } else { + $count = 0; + } + if ($count) { + $row = mysql_fetch_object($result); + mysql_query("update plugins set downloads = downloads + 1 where url = '{$url}'"); + } else { + mysql_query("insert into plugins set downloads = 1, url = '{$url}'"); + } + // Go! + header("Location: {$download_base}{$url}"); + +?> diff --git a/getplugin.php b/getplugin.php new file mode 100644 index 0000000..ecdfcca --- /dev/null +++ b/getplugin.php @@ -0,0 +1,33 @@ +total; + } else { + $count = 0; + } + if ($count) { + $row = mysql_fetch_object($result); + mysql_query("update plugins set downloads = downloads + 1 where url = '{$url}'"); + } else { + mysql_query("insert into plugins set downloads = 1, url = '{$url}'"); + } + + // Go! + header("Location: {$download_base}{$url}"); + +?> diff --git a/globalfooter.php b/globalfooter.php new file mode 100644 index 0000000..40781d2 --- /dev/null +++ b/globalfooter.php @@ -0,0 +1,10 @@ +
        + \ No newline at end of file diff --git a/globalheader.php b/globalheader.php new file mode 100644 index 0000000..6de1364 --- /dev/null +++ b/globalheader.php @@ -0,0 +1,14 @@ + diff --git a/googlehostedservice.html b/googlehostedservice.html new file mode 100644 index 0000000..db51f0b --- /dev/null +++ b/googlehostedservice.html @@ -0,0 +1 @@ +googleffffffffcc2f3f34 \ No newline at end of file diff --git a/header.php b/header.php new file mode 100644 index 0000000..a7500f3 --- /dev/null +++ b/header.php @@ -0,0 +1,18 @@ +
        + +
        + diff --git a/header_internal.php b/header_internal.php new file mode 100644 index 0000000..b91604b --- /dev/null +++ b/header_internal.php @@ -0,0 +1,15 @@ +
        +
        +
        +
        +

        Elgg.org

        +
        +
        +
        +
        +

        A powerful open source social networking engine

        +
        +
        +
        +
        + diff --git a/header_new.php b/header_new.php new file mode 100644 index 0000000..19bdb0d --- /dev/null +++ b/header_new.php @@ -0,0 +1,15 @@ +
        + +
        + diff --git a/hosting.php b/hosting.php new file mode 100644 index 0000000..2225a8e --- /dev/null +++ b/hosting.php @@ -0,0 +1,73 @@ + + + + + Elgg - Open Source Social Networking Platform. + + + + + + + + + +
        +
        + +
        +

        Elgg hosting

        +

        + This page is a list of companies who specialise in Elgg hosting and is provided to help Elgg users looking for an appropriate hosting company. Neither Curverider Ltd or the Elgg project officially endorse the companies listed*, although they do help support Elgg.org through their related affiliate schemes. +

        +
        + Arvixe +

        For fast, secure and reliable Elgg Hosting, look no further than Arvixe for all your web hosting related needs.

        +
        +
        + + A2 graphic +

        A2 Hosting provides a range of options from a shared server right up to a dedicated hosting environment for your Elgg powered network.

        +
        +
        +
        +
        + +
        + + + + \ No newline at end of file diff --git a/images/a2hosting_mini_banner.gif b/images/a2hosting_mini_banner.gif new file mode 100644 index 0000000..f620da6 Binary files /dev/null and b/images/a2hosting_mini_banner.gif differ diff --git a/images/about_menu.png b/images/about_menu.png new file mode 100644 index 0000000..17680a6 Binary files /dev/null and b/images/about_menu.png differ diff --git a/images/api_reference.gif b/images/api_reference.gif new file mode 100644 index 0000000..696035f Binary files /dev/null and b/images/api_reference.gif differ diff --git a/images/arrow_blue.gif b/images/arrow_blue.gif new file mode 100644 index 0000000..9eeea1d Binary files /dev/null and b/images/arrow_blue.gif differ diff --git a/images/arrow_orange.gif b/images/arrow_orange.gif new file mode 100644 index 0000000..1e01719 Binary files /dev/null and b/images/arrow_orange.gif differ diff --git a/images/badge_campus.png b/images/badge_campus.png new file mode 100644 index 0000000..a3f1244 Binary files /dev/null and b/images/badge_campus.png differ diff --git a/images/badge_managed.png b/images/badge_managed.png new file mode 100644 index 0000000..f23a663 Binary files /dev/null and b/images/badge_managed.png differ diff --git a/images/badge_open_source.png b/images/badge_open_source.png new file mode 100644 index 0000000..16ef3d9 Binary files /dev/null and b/images/badge_open_source.png differ diff --git a/images/biz.jpg b/images/biz.jpg new file mode 100644 index 0000000..1a814fd Binary files /dev/null and b/images/biz.jpg differ diff --git a/images/bossie.gif b/images/bossie.gif new file mode 100644 index 0000000..4efc9f2 Binary files /dev/null and b/images/bossie.gif differ diff --git a/images/btn_download.png b/images/btn_download.png new file mode 100644 index 0000000..bccd6c8 Binary files /dev/null and b/images/btn_download.png differ diff --git a/images/bug_tracker.gif b/images/bug_tracker.gif new file mode 100644 index 0000000..fa99720 Binary files /dev/null and b/images/bug_tracker.gif differ diff --git a/images/bugs.gif b/images/bugs.gif new file mode 100644 index 0000000..627562b Binary files /dev/null and b/images/bugs.gif differ diff --git a/images/button_shadow.png b/images/button_shadow.png new file mode 100644 index 0000000..d947fd9 Binary files /dev/null and b/images/button_shadow.png differ diff --git a/images/curverider-logo.png b/images/curverider-logo.png new file mode 100644 index 0000000..4f7824b Binary files /dev/null and b/images/curverider-logo.png differ diff --git a/images/customer_logos.gif b/images/customer_logos.gif new file mode 100644 index 0000000..b6db519 Binary files /dev/null and b/images/customer_logos.gif differ diff --git a/images/docs.gif b/images/docs.gif new file mode 100644 index 0000000..eebc61d Binary files /dev/null and b/images/docs.gif differ diff --git a/images/elgg-supporters.gif b/images/elgg-supporters.gif new file mode 100644 index 0000000..8925615 Binary files /dev/null and b/images/elgg-supporters.gif differ diff --git a/images/elgg.png b/images/elgg.png new file mode 100644 index 0000000..b287552 Binary files /dev/null and b/images/elgg.png differ diff --git a/images/elgg_bg.jpg b/images/elgg_bg.jpg new file mode 100644 index 0000000..f677f4b Binary files /dev/null and b/images/elgg_bg.jpg differ diff --git a/images/elgg_small.png b/images/elgg_small.png new file mode 100644 index 0000000..7a7e01f Binary files /dev/null and b/images/elgg_small.png differ diff --git a/images/grouped_screenshots.gif b/images/grouped_screenshots.gif new file mode 100644 index 0000000..1d4672d Binary files /dev/null and b/images/grouped_screenshots.gif differ diff --git a/images/homepage_banner.jpg b/images/homepage_banner.jpg new file mode 100644 index 0000000..e4a57d3 Binary files /dev/null and b/images/homepage_banner.jpg differ diff --git a/images/latest_tweet_tail.gif b/images/latest_tweet_tail.gif new file mode 100644 index 0000000..4698aa1 Binary files /dev/null and b/images/latest_tweet_tail.gif differ diff --git a/images/leonard.jpg b/images/leonard.jpg new file mode 100644 index 0000000..8aa5973 Binary files /dev/null and b/images/leonard.jpg differ diff --git a/images/logo.png b/images/logo.png new file mode 100644 index 0000000..cf74132 Binary files /dev/null and b/images/logo.png differ diff --git a/images/mailing.gif b/images/mailing.gif new file mode 100644 index 0000000..59cbe12 Binary files /dev/null and b/images/mailing.gif differ diff --git a/images/mailing_list.gif b/images/mailing_list.gif new file mode 100644 index 0000000..79dae8f Binary files /dev/null and b/images/mailing_list.gif differ diff --git a/images/matt.jpg b/images/matt.jpg new file mode 100644 index 0000000..e1fe448 Binary files /dev/null and b/images/matt.jpg differ diff --git a/images/partner.gif b/images/partner.gif new file mode 100644 index 0000000..d8eb359 Binary files /dev/null and b/images/partner.gif differ diff --git a/images/people/biz_small.jpg b/images/people/biz_small.jpg new file mode 100644 index 0000000..fdc7ec1 Binary files /dev/null and b/images/people/biz_small.jpg differ diff --git a/images/people/brett.jpg b/images/people/brett.jpg new file mode 100644 index 0000000..1e22867 Binary files /dev/null and b/images/people/brett.jpg differ diff --git a/images/people/dave-mini-old.jpg b/images/people/dave-mini-old.jpg new file mode 100644 index 0000000..d960d55 Binary files /dev/null and b/images/people/dave-mini-old.jpg differ diff --git a/images/people/dave-mini.jpg b/images/people/dave-mini.jpg new file mode 100644 index 0000000..bb78f7e Binary files /dev/null and b/images/people/dave-mini.jpg differ diff --git a/images/people/dave.jpg b/images/people/dave.jpg new file mode 100644 index 0000000..5f603c3 Binary files /dev/null and b/images/people/dave.jpg differ diff --git a/images/people/jim.jpg b/images/people/jim.jpg new file mode 100644 index 0000000..b01cb87 Binary files /dev/null and b/images/people/jim.jpg differ diff --git a/images/people/leonard_small.jpg b/images/people/leonard_small.jpg new file mode 100644 index 0000000..c815f90 Binary files /dev/null and b/images/people/leonard_small.jpg differ diff --git a/images/people/matthew_small.jpg b/images/people/matthew_small.jpg new file mode 100644 index 0000000..90bd1aa Binary files /dev/null and b/images/people/matthew_small.jpg differ diff --git a/images/people/pete-mini.jpg b/images/people/pete-mini.jpg new file mode 100644 index 0000000..f31601a Binary files /dev/null and b/images/people/pete-mini.jpg differ diff --git a/images/people/sasan_small.jpg b/images/people/sasan_small.jpg new file mode 100644 index 0000000..c49d0b9 Binary files /dev/null and b/images/people/sasan_small.jpg differ diff --git a/images/people/stan_small.jpg b/images/people/stan_small.jpg new file mode 100644 index 0000000..ea91903 Binary files /dev/null and b/images/people/stan_small.jpg differ diff --git a/images/sample.jpg b/images/sample.jpg new file mode 100644 index 0000000..21a14a0 Binary files /dev/null and b/images/sample.jpg differ diff --git a/images/sasan.jpg b/images/sasan.jpg new file mode 100644 index 0000000..e8dcf2f Binary files /dev/null and b/images/sasan.jpg differ diff --git a/images/screenshots.gif b/images/screenshots.gif new file mode 100644 index 0000000..bf29504 Binary files /dev/null and b/images/screenshots.gif differ diff --git a/images/services/keetup.jpg b/images/services/keetup.jpg new file mode 100644 index 0000000..b08e110 Binary files /dev/null and b/images/services/keetup.jpg differ diff --git a/images/services/keetup.png b/images/services/keetup.png new file mode 100644 index 0000000..04123bc Binary files /dev/null and b/images/services/keetup.png differ diff --git a/images/spacer.gif b/images/spacer.gif new file mode 100644 index 0000000..5bfd67a Binary files /dev/null and b/images/spacer.gif differ diff --git a/images/stan.jpg b/images/stan.jpg new file mode 100644 index 0000000..ec16521 Binary files /dev/null and b/images/stan.jpg differ diff --git a/index.php b/index.php new file mode 100644 index 0000000..debbf7e --- /dev/null +++ b/index.php @@ -0,0 +1,74 @@ + + + + + Elgg - Open Source Social Networking Engine. + + + + + + + + +
        +
        +
        + +
        +
        +

        Introducing a powerful open source
        social networking engine

        +

        Providing you with the core components you need
        to build out socially aware applications

        +
        + +
        +
        +
        +
        +

        Elgg is an award-winning social networking engine, delivering the building blocks that enable businesses, schools, universities and associations to create their own fully-featured social networks and applications. Organizations with networks powered by Elgg include:

        + + + + +
        + +
        +
        +

        Hosting

        +

        Looking for a provider to host your network built on the open source engine? Find companies who specialise in Elgg hosting.

        +
        + +
        +

        Giving back

        +

        There are several ways you can help out the Elgg project. The options range from bug reporting and patch submission to joining the supporters scheme or buying a services listing.

        +
        + +
        +

        Elgg on Twitter

        +

          + +
          +
          +
          +
          +
          + + +
          + + + + + + diff --git a/index_old.php b/index_old.php new file mode 100644 index 0000000..a329e5d --- /dev/null +++ b/index_old.php @@ -0,0 +1,77 @@ + + + + + Elgg - Open Source Social Networking Platform. + + + + + + + + + +
          +
          + +
          +

          Get started with one of these options

          +
          + Download the open source code and start developing your own social network +
          + +
          + Create your own hosted social network in minutes at elgg.com, leaving the technical stuff to us +
          + +
          + Have your social networking vision built out for you with Elgg Campus +
          +
          +
          +
          + +
          +

          Elgg is an award-winning social networking engine, delivering the building blocks that enable businesses, schools, universities, groups and associations to create their own fully-featured social network.

          + +

          The Elgg engine powers social networks for many leading organizations around the world.

          + +
          + +
          +
          +

          Hosting

          +

          Looking for a provider to host your network built on the open source software? Find companies who specialise in Elgg hosting.

          +
          + +
          +

          Elgg Partners

          +

          Find an accredited Elgg Partner to help you design and build your network based on the open source Elgg software.

          +
          + +
          +

          Elgg on Twitter

          +

            + +
            +
            +
            +
            +
            + + +
            + + + + + + diff --git a/involved.php b/involved.php new file mode 100644 index 0000000..f4899bd --- /dev/null +++ b/involved.php @@ -0,0 +1,61 @@ + + + + + Elgg - Open Source Social Networking Platform. + + + + + + + + + +
            +
            + +
            +

            Get involved

            +

            Elgg is continually being developed and enhanced by an active and growing community of organizations, developers and enthusiasts world wide. There are lots of ways to get involved, whether you're a developer contributing plugins, a designer contributing themes, or a user who just wants to spread the word. We also welcome contributions from bug-fixers through to those generous enough to help new users get started.

            +

            The Elgg community pages are a great place to start.

            +
            +
            +
            + +
            + + + + \ No newline at end of file diff --git a/license.php b/license.php new file mode 100644 index 0000000..bac25e1 --- /dev/null +++ b/license.php @@ -0,0 +1,61 @@ + + + + + Elgg - Open Source Social Networking Engine. + + + + + + + + + +
            +
            + +
            +

            License

            +

            Elgg is free to download and use. It is dual licensed under the terms of the GNU General Public License v2 as published by the Free Software Foundation and the MIT License.

            +

            If you have any questions please contact Curverider Ltd info@curverider.co.uk.

            +
            +
            +
            + +
            + + + + diff --git a/news/index.php b/news/index.php new file mode 100644 index 0000000..afb6a59 --- /dev/null +++ b/news/index.php @@ -0,0 +1,5 @@ + \ No newline at end of file diff --git a/news/weblog/index.php b/news/weblog/index.php new file mode 100644 index 0000000..afb6a59 --- /dev/null +++ b/news/weblog/index.php @@ -0,0 +1,5 @@ + \ No newline at end of file diff --git a/news/weblog/rss/index.php b/news/weblog/rss/index.php new file mode 100644 index 0000000..0883f44 --- /dev/null +++ b/news/weblog/rss/index.php @@ -0,0 +1,5 @@ + \ No newline at end of file diff --git a/partners.php b/partners.php new file mode 100644 index 0000000..585e900 --- /dev/null +++ b/partners.php @@ -0,0 +1,63 @@ + + + + + Elgg - Open Source Social Networking Engine. + + + + + + + + + +
            +
            + +
            +

            Elgg Partners

            +

            + Elgg Partners offer consulting, hosting, training and development services for Elgg. If you're building or running your own Elgg implementation and require help, we recommend using an accredited Elgg Partner so you can be sure you're getting the expert advice and support that will help you get the most out of your Elgg network. +

            +
            +

            Colombia - Nivel Siete

            +

            Nivel +Nivel Siete was founded in 2002 in Colombia, South America, and has delivered e-Learning and Web solutions to more than 130 Higher Education and Corporate customers across 10 countries. In order to provide world-class levels of service, the company partners with leading solution providers such as Elgg, Moodle and Typo3 and offers robust, SaaS-based solutions. Nivel Siete provides a range of standard packages as well as unique Social e-Learning offerings tailored to the needs of customers. www.nivel7.net

            +
            +
            +
            +
            + +
            + + + + \ No newline at end of file diff --git a/plugins.php b/plugins.php new file mode 100644 index 0000000..c85f13b --- /dev/null +++ b/plugins.php @@ -0,0 +1,138 @@ + + + + + + + Elgg.org - Plugins + + + + + + +
            + + + + + +
            + + +
            +

            Plugins

            +

            Most of the end user functionality in Elgg comes from plugins.

            +

            If you downloaded the full Elgg bundle it will come with a selection of plugins pre-loaded. If you downloaded the core engine, you can find a list of available plugins below. + We've also listed some extras that both sets of users might find useful.

            +
            +
            +
            + + + +
            + + + + + + + +
            +

            Basic elements

            +
              +
            • Blogs A blogging engine for Elgg.
              Zip | Tarball
            • +
            • Files This is a full blown file repository accomodating any file type.
              Zip | Tarball
            • +
            • Pages This plugin provides users and groups with collaborative wiki like functionality. Combined will Elgg's powerful access controls, this is a killer plugin.
              Zip | Tarball
            • +
            • Bookmarks This social bookmarking plugin lets users bookmark and share both internally and external content.
              Zip | Tarball
            • +
            • Messages This plugin lets your users send private messages to each other.
              Zip | Tarball
            • + +
            +
            +

            Extras

            +
              +
            • Messageboard A simple messageboard for user and group profiles.
              Zip | Tarball
            • +
            • Walled Garden This plugin turns your Elgg site into a walled garden. This means that only those registered on the site can access any of the content.
              Zip | Tarball
            • +
            • Coppa Required your users to agree to an age limit before registration.
              Zip | Tarball
            • +
            • Captcha Registration captcha for Elgg.
              Zip | Tarball
            • +
            • LDAP (untested) LDAP support for Elgg.
              Zip | Tarball
            • +
            +
            +

            Contributing plugins

            +

            There are many excellent plugins contributed by the Elgg community. We welcome your contribution - head over to the Elgg community to get started.

            +

            Below are some links to tutorials for building Elgg plugins and Elgg standards.

            +

            Tutorials

            + +
            +
            + + + + + + + \ No newline at end of file diff --git a/powering.php b/powering.php new file mode 100644 index 0000000..ddca0e4 --- /dev/null +++ b/powering.php @@ -0,0 +1,100 @@ + + + + + Elgg - Open Source Social Networking Platform. + + + + + + + + + +
            +
            + +
            +

            Elgg powers networks for a wide range of organizations including the following:

            +
            +
              +
            • Oxfam
            • +
            • Royal College of British Architects
            • +
            • Australian Government
            • +
            • British Government
            • +
            • Federal Canadian Government
            • +
            • MITRE
            • +
            • New Zealand Ministry of Education
            • +
            • State of Ohio, USA
            • +
            • The World Bank
            • +
            • UNESCO
            • +
            • United Nations Development Programme
            • +
            • Canadian Employment and Immigration Union
            • +
            • Tides Canada
            • +
            • Aerospace
            • +
            • NASA
            • +
            • The Executive Lounge
            • +
            • Hedgehogs.net
            • +
            • Hill and Knowlton
            • +
            • Institute of Executive Coaching
            • +
            • Interactive Games & Entertainment Association
            • +
            • Live Out There
            • +
            • UnltdWorld
            • +
            • Wiley Publishing
            • +
            • Harvard University Extension School
            • +
            • Saugus School District
            • +
            • Stanford University
            • +
            • Think Global School
            • +
            • University of Brighton
            • +
            • University of Calgary, Grid Research Centre
            • +
            • Universite Lille 1
            • +
            • University of Nebraska-Lincoln
            • +
            • Johns Hopkins University
            • +
            • Oregon State University
            • +
            • Great Ormond Street Hospital
            • +
            • University of Florida
            • +
            +
            + +
            +
            +
            +
            + +
            + + + + \ No newline at end of file diff --git a/previous.php b/previous.php new file mode 100644 index 0000000..d7c8523 --- /dev/null +++ b/previous.php @@ -0,0 +1,72 @@ + + + + + Elgg - Open Source Social Networking Engine. + + + + + + + + + +
            +
            + +
            +

            Previous releases and security updates

            +

            V1.7.3 - Security Update - released September 2, 2010 Download

            +

            V1.7.2 - released August 25, 2010 Download

            +

            V1.7.1 - released April 21, 2010 Download

            +

            V1.6.3 - Security Update - released September 2 2010 Download

            +

            V1.6.2 - Security Update - released April 2010 Download

            +

            V1.7 - released March 2010 Download

            +

            V1.6.1 - released September 2009 Download

            +

            V1.6 - released August 2009 Download

            + +

            Unsupported releases

            +

            These versions of Elgg are no longer supported and are not safe to use!

            +

            V1.5.1 - Security Update - released April 2010 Download

            +

            V1.5 - released March 2009 Download

            +

            V1.2 - released December 2008 Download

            +

            V1.1 - released October 2008 Download

            +

            V1.0 - released August 2008 Download

            + + +
            +
            +
            + +
            + + + + diff --git a/requirements.php b/requirements.php new file mode 100644 index 0000000..87bfb40 --- /dev/null +++ b/requirements.php @@ -0,0 +1,76 @@ + + + + + Elgg - Open Source Social Networking Platform. + + + + + + + + + +
            +
            + +
            +

            Requirements

            +

            Elgg runs on a combination of the Apache web server, MySQL database system and the PHP interpreted scripting language. This is the most popular web server environment in the world.

            +

            Due to Elgg's advanced functionality, there are some extra configuration requirements:

            +

            The Apache web server needs to be installed with the following modules:

            +
              +
            • mod_rewrite
            • +
            • PHP 5
            • +
            • MySQL 5+ is needed for data storage
            • +
            • PHP 5.2+ needs to be installed as an Apache module (not in CGI mode or safe mode) with the following libraries: +
                +
              • GD (for graphics processing, eg user icon rescaling and Captcha)
              • +
              • JSON (for API functionality)
              • +
              • XML (not installed/compiled by default on all systems)
              • +
              • Multibyte String support (for internationalisation)
              • +
              +
            • +
            +

            It is recommended that you increase the memory available to PHP threads beyond the standard 8 or 12M, and increase the maximum uploaded filesize (which defaults to 2M). By default, these settings have been set for you in the .htaccess file in the base Elgg directory.

            +
            +
            +
            + +
            + + + + \ No newline at end of file diff --git a/screenshots/activity.gif b/screenshots/activity.gif new file mode 100644 index 0000000..7cfc108 Binary files /dev/null and b/screenshots/activity.gif differ diff --git a/screenshots/activity.jpg b/screenshots/activity.jpg new file mode 100644 index 0000000..d8726b3 Binary files /dev/null and b/screenshots/activity.jpg differ diff --git a/screenshots/blog.gif b/screenshots/blog.gif new file mode 100644 index 0000000..5416c80 Binary files /dev/null and b/screenshots/blog.gif differ diff --git a/screenshots/blog.jpg b/screenshots/blog.jpg new file mode 100644 index 0000000..5304bad Binary files /dev/null and b/screenshots/blog.jpg differ diff --git a/screenshots/box icon.png b/screenshots/box icon.png new file mode 100644 index 0000000..245101a Binary files /dev/null and b/screenshots/box icon.png differ diff --git a/screenshots/box-icon.jpg b/screenshots/box-icon.jpg new file mode 100644 index 0000000..5f4c670 Binary files /dev/null and b/screenshots/box-icon.jpg differ diff --git a/screenshots/embed.jpg b/screenshots/embed.jpg new file mode 100644 index 0000000..0588530 Binary files /dev/null and b/screenshots/embed.jpg differ diff --git a/screenshots/files.gif b/screenshots/files.gif new file mode 100644 index 0000000..0b708a7 Binary files /dev/null and b/screenshots/files.gif differ diff --git a/screenshots/files.jpg b/screenshots/files.jpg new file mode 100644 index 0000000..2757dc6 Binary files /dev/null and b/screenshots/files.jpg differ diff --git a/screenshots/groups.gif b/screenshots/groups.gif new file mode 100644 index 0000000..73f04a2 Binary files /dev/null and b/screenshots/groups.gif differ diff --git a/screenshots/groups.jpg b/screenshots/groups.jpg new file mode 100644 index 0000000..a472b79 Binary files /dev/null and b/screenshots/groups.jpg differ diff --git a/screenshots/mediaembed.gif b/screenshots/mediaembed.gif new file mode 100644 index 0000000..d550e2d Binary files /dev/null and b/screenshots/mediaembed.gif differ diff --git a/screenshots/notifications.gif b/screenshots/notifications.gif new file mode 100644 index 0000000..efe82fd Binary files /dev/null and b/screenshots/notifications.gif differ diff --git a/screenshots/notifications.jpg b/screenshots/notifications.jpg new file mode 100644 index 0000000..a0ce676 Binary files /dev/null and b/screenshots/notifications.jpg differ diff --git a/screenshots/profile.gif b/screenshots/profile.gif new file mode 100644 index 0000000..eb4995d Binary files /dev/null and b/screenshots/profile.gif differ diff --git a/screenshots/profile.jpg b/screenshots/profile.jpg new file mode 100644 index 0000000..3e803d3 Binary files /dev/null and b/screenshots/profile.jpg differ diff --git a/screenshots/thewire.gif b/screenshots/thewire.gif new file mode 100644 index 0000000..b459cf3 Binary files /dev/null and b/screenshots/thewire.gif differ diff --git a/screenshots/thewire.jpg b/screenshots/thewire.jpg new file mode 100644 index 0000000..607edb0 Binary files /dev/null and b/screenshots/thewire.jpg differ diff --git a/screenshots/widgets.gif b/screenshots/widgets.gif new file mode 100644 index 0000000..9126db2 Binary files /dev/null and b/screenshots/widgets.gif differ diff --git a/screenshots/widgets.jpg b/screenshots/widgets.jpg new file mode 100644 index 0000000..905d7b9 Binary files /dev/null and b/screenshots/widgets.jpg differ diff --git a/scripts/AC_RunActiveContent.js b/scripts/AC_RunActiveContent.js new file mode 100644 index 0000000..a5c408b --- /dev/null +++ b/scripts/AC_RunActiveContent.js @@ -0,0 +1,292 @@ +//v1.7 +// Flash Player Version Detection +// Detect Client Browser type +// Copyright 2005-2007 Adobe Systems Incorporated. All rights reserved. +var isIE = (navigator.appVersion.indexOf("MSIE") != -1) ? true : false; +var isWin = (navigator.appVersion.toLowerCase().indexOf("win") != -1) ? true : false; +var isOpera = (navigator.userAgent.indexOf("Opera") != -1) ? true : false; + +function ControlVersion() +{ + var version; + var axo; + var e; + + // NOTE : new ActiveXObject(strFoo) throws an exception if strFoo isn't in the registry + + try { + // version will be set for 7.X or greater players + axo = new ActiveXObject("ShockwaveFlash.ShockwaveFlash.7"); + version = axo.GetVariable("$version"); + } catch (e) { + } + + if (!version) + { + try { + // version will be set for 6.X players only + axo = new ActiveXObject("ShockwaveFlash.ShockwaveFlash.6"); + + // installed player is some revision of 6.0 + // GetVariable("$version") crashes for versions 6.0.22 through 6.0.29, + // so we have to be careful. + + // default to the first public version + version = "WIN 6,0,21,0"; + + // throws if AllowScripAccess does not exist (introduced in 6.0r47) + axo.AllowScriptAccess = "always"; + + // safe to call for 6.0r47 or greater + version = axo.GetVariable("$version"); + + } catch (e) { + } + } + + if (!version) + { + try { + // version will be set for 4.X or 5.X player + axo = new ActiveXObject("ShockwaveFlash.ShockwaveFlash.3"); + version = axo.GetVariable("$version"); + } catch (e) { + } + } + + if (!version) + { + try { + // version will be set for 3.X player + axo = new ActiveXObject("ShockwaveFlash.ShockwaveFlash.3"); + version = "WIN 3,0,18,0"; + } catch (e) { + } + } + + if (!version) + { + try { + // version will be set for 2.X player + axo = new ActiveXObject("ShockwaveFlash.ShockwaveFlash"); + version = "WIN 2,0,0,11"; + } catch (e) { + version = -1; + } + } + + return version; +} + +// JavaScript helper required to detect Flash Player PlugIn version information +function GetSwfVer(){ + // NS/Opera version >= 3 check for Flash plugin in plugin array + var flashVer = -1; + + if (navigator.plugins != null && navigator.plugins.length > 0) { + if (navigator.plugins["Shockwave Flash 2.0"] || navigator.plugins["Shockwave Flash"]) { + var swVer2 = navigator.plugins["Shockwave Flash 2.0"] ? " 2.0" : ""; + var flashDescription = navigator.plugins["Shockwave Flash" + swVer2].description; + var descArray = flashDescription.split(" "); + var tempArrayMajor = descArray[2].split("."); + var versionMajor = tempArrayMajor[0]; + var versionMinor = tempArrayMajor[1]; + var versionRevision = descArray[3]; + if (versionRevision == "") { + versionRevision = descArray[4]; + } + if (versionRevision[0] == "d") { + versionRevision = versionRevision.substring(1); + } else if (versionRevision[0] == "r") { + versionRevision = versionRevision.substring(1); + if (versionRevision.indexOf("d") > 0) { + versionRevision = versionRevision.substring(0, versionRevision.indexOf("d")); + } + } + var flashVer = versionMajor + "." + versionMinor + "." + versionRevision; + } + } + // MSN/WebTV 2.6 supports Flash 4 + else if (navigator.userAgent.toLowerCase().indexOf("webtv/2.6") != -1) flashVer = 4; + // WebTV 2.5 supports Flash 3 + else if (navigator.userAgent.toLowerCase().indexOf("webtv/2.5") != -1) flashVer = 3; + // older WebTV supports Flash 2 + else if (navigator.userAgent.toLowerCase().indexOf("webtv") != -1) flashVer = 2; + else if ( isIE && isWin && !isOpera ) { + flashVer = ControlVersion(); + } + return flashVer; +} + +// When called with reqMajorVer, reqMinorVer, reqRevision returns true if that version or greater is available +function DetectFlashVer(reqMajorVer, reqMinorVer, reqRevision) +{ + versionStr = GetSwfVer(); + if (versionStr == -1 ) { + return false; + } else if (versionStr != 0) { + if(isIE && isWin && !isOpera) { + // Given "WIN 2,0,0,11" + tempArray = versionStr.split(" "); // ["WIN", "2,0,0,11"] + tempString = tempArray[1]; // "2,0,0,11" + versionArray = tempString.split(","); // ['2', '0', '0', '11'] + } else { + versionArray = versionStr.split("."); + } + var versionMajor = versionArray[0]; + var versionMinor = versionArray[1]; + var versionRevision = versionArray[2]; + + // is the major.revision >= requested major.revision AND the minor version >= requested minor + if (versionMajor > parseFloat(reqMajorVer)) { + return true; + } else if (versionMajor == parseFloat(reqMajorVer)) { + if (versionMinor > parseFloat(reqMinorVer)) + return true; + else if (versionMinor == parseFloat(reqMinorVer)) { + if (versionRevision >= parseFloat(reqRevision)) + return true; + } + } + return false; + } +} + +function AC_AddExtension(src, ext) +{ + if (src.indexOf('?') != -1) + return src.replace(/\?/, ext+'?'); + else + return src + ext; +} + +function AC_Generateobj(objAttrs, params, embedAttrs) +{ + var str = ''; + if (isIE && isWin && !isOpera) + { + str += ' '; + } + str += ''; + } + else + { + str += ' + + + + Elgg - Open Source Social Networking Platform. + + + + + + + + + +
            +
            + +
            +

            Elgg services

            +
            +

            Curverider Ltd

            +

            Curverider +Curverider Ltd, the company behind Elgg, offer consultation and development help with the core Elgg engine. If you would like some support, guidance or tutoring on best practice for Elgg then get in touch services@elgg.com.

            +
            +
            +
            +

            Colombia - Nivel Siete Official Elgg partner

            +

            Nivel +Nivel Siete was founded in 2002 in Colombia, South America, and has delivered e-Learning and Web solutions to more than 130 Higher Education and Corporate customers across 10 countries. In order to provide world-class levels of service, the company partners with leading solution providers such as Elgg, Moodle and Typo3 and offers robust, SaaS-based solutions. Nivel Siete provides a range of standard packages as well as unique Social e-Learning offerings tailored to the needs of customers. www.nivel7.net

            +
            +

            Listings

            +
            +

            KeetupKeetup Development
            + We are professional Elgg developers specializing in plugins, themes and social networking advice. We also advice companies on Elgg implementations.
            + Keetup development website | Keetup Elgg community profile

            +
            +

            -------------------

            +

            + Sample + This is a sample listing. You get 20 words, a link and 40 * 40 icon. ($150 per 30 day listing fee* which goes directly towards core Elgg development)
            + sample company

            +
            +
            +
            +
            +
            + +
            + + + + \ No newline at end of file diff --git a/style.css b/style.css new file mode 100644 index 0000000..1806ec0 --- /dev/null +++ b/style.css @@ -0,0 +1,368 @@ +/* Elgg.org */ + +/* *************************************** + RESET +*************************************** */ +html, body, div, span, applet, object, iframe, h1, h2, h3, h4, h5, h6, p, blockquote, pre, a, abbr, acronym, address, big, cite, code, del, dfn, em, font, img, ins, kbd, q, s, samp, small, strike, strong, sub, sup, tt, var, dl, dt, dd, ol, ul, li, fieldset, form, label, legend, table, caption, tbody, tfoot, thead, tr, th, td { +margin: 0;padding: 0;border: 0;outline: 0;font-weight: inherit;font-style: inherit;font-size: 100%;font-family: inherit;vertical-align: baseline;} +img {border-width:0; border-color:transparent;} +ol, ul {list-style:none outside none;} +em, i {font-style:italic;} +table {border-collapse: collapse;border-spacing: 0;} +:focus {outline:0 none; -moz-outline-style: none;} +pre, code {font-family:Monaco,"Courier New",Courier,monospace;} + +/*----------------------------- + GLOBAL/SHARED CONTENT +-----------------------------*/ +body {background-color: #ffffff;text-decoration: none;color: #666666;font-family: Arial, sans-serif;font-size: 0.9em;line-height: 150%;} + +h1{font-family: Helvetica, Arial, sans-serif; font-size: 1.8em; line-height:115%; font-weight: normal;} +h2{font-family: Helvetica, Arial, sans-serif; font-size: 1.2em; line-height: 135%; font-weight: normal;} + +p {line-height:130%;color: #666666;} +li {line-height:125%;} +a {text-decoration: none;color:#e74815;} +a:hover {color:black;} + +.header_color, +.header_color a {color:#00acf7;} /* light blue */ +.header_color a:hover {text-decoration: underline;} +.accent_color {color:#e74815;} /* orange */ + +a.title, a.bottom_title:visited {color:#00acf7;font-size:1.1em;} +a.title:hover, a.bottom_title:active {color:#e74815;font-size:1.1em;} + +a.bottom, a.bottom:visited {color:#959797;font-size:1em;} +a.bottom:hover, div#bottom a.bottom:active {color:#00acf7;font-size:1em;} + +.divider {border-top:1px solid #cccccc;margin:20px 0 10px 0;} +small {font-size:90%;color:#999999;} + +.clearfloat:after { + content: "."; + display: block; + height: 0; + clear: both; + visibility: hidden; +} + +/*----------------------------- + GLOBAL HEADER #00acf7 +-----------------------------*/ +#globalheader_wrapper {background-color:#00acf7; width: 100%;height: 30px;margin-left: auto;margin-right: auto;} +#globalheader {position:relative;width: 970px;margin-left: auto;margin-right: auto;} +#globalheader ul {float:right;font-size: 0.9em; margin: 4px 0 0 0px;} +#globalheader li { + display:inline;list-style-type:none; + padding: 0 0 0 15px; + +} +.header {color: white;} +#globalheader li a { + -webkit-border-radius: 10px; + -moz-border-radius: 10px; + padding:2px 9px; +} +#globalheader li a:hover { + background-color: #027bb3; + color:white; +} +.header.selected { + color: #333333; + font-weight: normal; + background-color: white; + +} + + +/*----------------------------- + HEADER +-----------------------------*/ +#header_wrapper {width:100%;height:auto;margin:0 auto;} +#header {width:970px;height: auto;text-align:right;margin-left: auto;margin-right: auto;padding-bottom:20px;} +#header_wrapper2 {vertical-align:top;width: 100%;height: 120px;margin-left: auto;margin-right: auto;} +#header2 {width: 970px;height: 120px;text-align: right;margin-left: auto;margin-right: auto;} + +#container_right {float:right;} +#container_left {float:left;} + +#logo {float:left;text-align:left;margin-left:-5px;margin-top:10px;} +#logo_internal {float:left;text-align:left;margin-top:10px;} +#logo span {display:block;font-size:1.4em;padding:10px 0 0 10px;} + +#tag {margin-top:10px;margin-bottom:15px;} +#tag p {line-height:270%;} +#tag .strapline {font-size:2.0em;} +#header2 #tag .strapline {font-size:1.6em;} +#header2 #tag {margin-top:33px;} + +#download_btn {width:252px;text-align:center;} +#header #download_btn { } +#download_btn p {line-height:420%;} +#download_btn p a.download:link, a.download:visited {display:block; width:252px; height:57px; background-image: url('images/btn_download.png'); background-position:top left;} +#download_btn p a.download:hover, a.download:focus {background-position:left 116px;} +#download_btn p a.download:active {background-position:left 116px;} +#download_btn p a {outline:none;font-size:1.7em;font-weight:normal;color:white;} + + +/*----------------------------- + FOOTER #95ddfc +-----------------------------*/ +#footer_wrapper {background-color:#00acf7; vertical-align:top;width: 100%;margin-left: auto;margin-right: auto;} +#footer {position: relative;width: 970px;height: 110px;text-align: right;margin:0 auto;} +#footer_right {position:absolute;top:28px; right:0px;} +#footer_right span {color:#0d7aac; font-size:0.9em;} +#footer_right span.text {color: #0d7aac; font-size:0.9em;} +#footer_right p {font-size:0.9em;color:#48c5fe;} +#footer_right a {color:#48c5fe;} +#footer_right a:hover {text-decoration: underline;color:black;} + + +/*----------------------------- + CONTENT WRAPPER +-----------------------------*/ +#content_wrapper {width: 100%;margin:0 auto;} +.content {width: 970px;margin:0 auto;} +.content p, .content li, .content pre {/* font-size: 0.9em; */} +p.leader {font-size:1.2em;} + +/*----------------------------- + HOME +-----------------------------*/ +#container_strapline { + text-align:right; + width: auto; + float:right; +} +#container_strapline #tag { + margin-top:51px; +} +#homepage .features_left, +#homepage .features_right { + font-size:1.2em; +} + +#box_wrapper { + padding:12px 26px 26px; + background-color: #e3f7fb; + -webkit-border-radius: 12px; + -moz-border-radius: 12px; +} +#box_wrapper h1 { + text-align: center; + font-weight: normal; + color:#333333; + margin-bottom:10px; +} +#threecolbox { + width:274px; + height:274px; + float:left; +} +#threecolbox.left { + margin-right:46px; +} +#threecolbox.middle { + margin-right:46px; +} +#threecolbox.right { + margin-right:0; +} +#bottom2 #threecolbox { + width:292px; + height:auto; + margin-bottom:40px; +} +h2.latest_tweet { + background-color:#EEEEEE; + margin-left:-10px; + margin-top:5px; + padding:5px 10px; + -webkit-border-radius: 9px; + -moz-border-radius: 9px; +} +.latest_tweet_tail { + background-image: url(images/latest_tweet_tail.gif); + background-position: -10px top; + background-repeat: no-repeat; + display:block; + height:13px; +} +.latest_tweet ul li a { + color:#999999; +} +.latest_tweet ul li a:hover { + color:#666666; + text-decoration: underline; +} + +#top_left {float:left;width:470px;margin-right:15px;} +#top_right {float:right;width:470px;margin-left:15px;} +#top_right h1 {margin-bottom:10px;} +li.leader { + height:115px; +} +div.button { + cursor: pointer; + height:65px; + width:180px; + border:1px solid #666666; + color:white; + display:block; + font:bold 16px Arial,Sans-serif; + padding:12px; + text-align:center; + vertical-align:middle; + text-decoration:none; + letter-spacing: 0.05em; + text-shadow:-1px -1px 0px #000000; + background-color: #E74815; + background-image:url(images/button_shadow.png); + background-repeat: repeat-x; + background-position: left -12px; + -webkit-border-radius: 12px; + -moz-border-radius: 12px; + -webkit-box-shadow: 0 2px 10px rgba(0,0,0,0.4); + -moz-box-shadow: 0 2px 10px rgba(0,0,0,0.4); + box-shadow: 0 2px 10px rgba(0,0,0,0.4); +} +div.button:hover { + background-position: left -32px; +} +div.button a { + color:white; + display:table-cell; + height:65px; + vertical-align:middle; +} +.features_left div.button { + background-color:#00ACF7; +} +.button_arrow { + margin-bottom: 7px; + width:208px; + text-align: center; +} + + +ul.features_left {float:left;width:230px;margin-top:10px;} +ul.features_right {float:right;width:230px;margin-top:10px;} +ul.features_left li {padding-right:15px;} + +div#top_right ul.features_bottom {float:left;margin-top:0px;font-size:0.8em;margin-left:0;padding-left:0;} +div#top_right ul.features_bottom li {list-style-type:none;display:list-item;margin-bottom:10px;margin-left:0;padding-left:0;} + +.display {margin-bottom:20px;} +#bottom { + margin-top:45px; + padding-bottom:35px; + margin-bottom:20px; + border-bottom:1px solid #dddddd; +} +/* +.bottom_left { + width: 425px; + float: left; + padding:10px 15px 15px 15px; + background-color:#e8e9e9; + min-height:85px; + margin:15px 0 45px 0; + -moz-border-radius:8px; + -webkit-border-radius:8px; + -webkit-box-shadow: 0 2px 5px rgba(0, 0, 0, 0.45); + -moz-box-shadow: 0 2px 5px rgba(0, 0, 0, 0.45); +} +.bottom_right { + width: 440px; + float: right; + padding:10px 15px 15px 15px; + background-color:#e8e9e9; + min-height:85px; + margin:15px 0 45px 0; + -moz-border-radius:8px; + -webkit-border-radius:8px; + -webkit-box-shadow: 0 2px 5px rgba(0, 0, 0, 0.45); + -moz-box-shadow: 0 2px 5px rgba(0, 0, 0, 0.45); +} +.bottom_right p, +.bottom_left p { + font-size:1em; +} +#bottom h1 {margin-bottom:5px;} +*/ + + +/*----------------------------- + INTERNAL PAGES +-----------------------------*/ +#page_contents {float:left;width:740px;min-height:400px;margin-left:30px;margin-bottom:40px;} +#page_contents h1 {margin-top:20px;} +#page_contents h1:first-child {margin-top:0;} +#page_contents p {margin-bottom:9px;} +#mid_left {float:left;width:350px;margin-top:20px;} +#mid_right {float:right;width:350px;margin-top:20px;} + + +/*----------------------------- + ABOUT +-----------------------------*/ +ul.team {margin-bottom:9px;} +ul.team li {padding-bottom:5px;} +ul.team li span {font-weight: bold;} +.award {border:1px solid #cccccc;padding:6px;margin-top:20px;-moz-border-radius:8px;-webkit-border-radius:8px;} +.award_badge {float:left;width:110px;height:87px;display:block;margin-right:20px;margin-top:-25px;} +.award_text {padding:25px 0 0 0;} +ul.advisors li {display:list-item;text-align:left;list-style-type:none; vertical-align:top;float:left; width:320px;margin:0px 0px 3px 0;} +ul.advisors li span.left_ad {float:left;margin: 0 0 10px 0px;} +ul.advisors li span.right_ad {width:260px;float:right;line-height:120%;} +.right_ad span {font-weight: bold;} + +ul.list_style li {list-style: disc; list-style-position: inside;padding-bottom:5px;} +ul.list_style ul.list_style {padding-top:5px;} +ul.list_style ul.list_style li {padding-left:20px;list-style:circle;list-style-position: inside;} + + +/*----------------------------- + HOSTING / SERVICES +-----------------------------*/ +.hosting_company {margin:20px 20px 0 0px;padding:7px; background: #eeeeee; -webkit-border-radius: 6px; -moz-border-radius: 6px;} +#page_contents .hosting_company p {margin:4px 0 0 0;} +#page_contents .continent {font-weight: bold; margin:10px 0 0 0;} +.sidebar_box {margin-top:30px; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border:1px solid #cccccc; + padding:6px; + +} +.sidebar_box p {margin-bottom:9px;} +.sidebar_box h2 { + color:#333333; +} +.sidebar_box .list_style {margin-bottom:8px;} +.subhead {font-weight:bold;} +.partners {margin:20px 20px 0 0px;padding:7px 7px 10px 7px; background: #eeeeee; -webkit-border-radius: 6px; -moz-border-radius: 6px;} + + +/*----------------------------- + SIDEBAR MENU +-----------------------------*/ +#sidebar_menu {float:left;width:200px;margin-bottom:40px;} +#sidebar_menu ul li {padding:2px 0 3px 0;} +#sidebar_menu a.aboutmenu:link, a.aboutmenu:visited {display:block; width:180px; height:22px; font-weight:bold;background:#dedede; color: #777777;-moz-border-radius:8px;-webkit-border-radius:8px;} +#sidebar_menu a.aboutmenu:hover, a.aboutmenu:focus {background:#00acf7;color: #FFFFFF;} +#sidebar_menu a.aboutmenu:active {background-position:bottom;color: #FFFFFF;} +#sidebar_menu a {outline:none;font-size:1em;font-weight:bold;text-decoration:none;text-decoration: none;padding:5px 0 0 10px;} +#sidebar_menu .selected {background:#00acf7;color: #FFFFFF;} +/* +Supporters table +*/ +.supporters_list {margin:20px 0 40px 0;font-size:0.9em;} +.supporters_list h2 {font-weight:bold;} +.supporters_list table, th, td{border:1px solid #ccc;} +.supporters_list table {width:100%;border-collapse:collapse;} +.supporters_list th{background-color:#ddd;text-align:left;} +.supporters_list td {padding:2px;width:25%;} +.supporters_list .user td {padding:2px;width:33%;} +.supporters_list .odd {background-color:#efefef;} \ No newline at end of file diff --git a/style2.css b/style2.css new file mode 100644 index 0000000..97230c3 --- /dev/null +++ b/style2.css @@ -0,0 +1,365 @@ +/* Elgg.org */ + +/* *************************************** + RESET +*************************************** */ +html, body, div, span, applet, object, iframe, h1, h2, h3, h4, h5, h6, p, blockquote, pre, a, abbr, acronym, address, big, cite, code, del, dfn, em, font, img, ins, kbd, q, s, samp, small, strike, strong, sub, sup, tt, var, dl, dt, dd, ol, ul, li, fieldset, form, label, legend, table, caption, tbody, tfoot, thead, tr, th, td { +margin: 0;padding: 0;border: 0;outline: 0;font-weight: inherit;font-style: inherit;font-size: 100%;font-family: inherit;vertical-align: baseline;} +img {border-width:0; border-color:transparent;} +ol, ul {list-style:none outside none;} +em, i {font-style:italic;} +table {border-collapse: collapse;border-spacing: 0;} +:focus {outline:0 none; -moz-outline-style: none;} +pre, code {font-family:Monaco,"Courier New",Courier,monospace;} + +/*----------------------------- + GLOBAL/SHARED CONTENT +-----------------------------*/ +body {background-color: #ffffff;text-decoration: none;color: #666666;font-family: Arial, sans-serif;font-size: 0.9em;line-height: 150%;} + +h1{font-family: Helvetica, Arial, sans-serif; font-size: 1.8em; line-height:115%; font-weight: normal;} +h2{font-family: Helvetica, Arial, sans-serif; font-size: 1.2em; line-height: 135%; font-weight: normal;} + +p {line-height:130%;color: #666666;} +li {line-height:125%;} +a {text-decoration: none;color:#e74815;} +a:hover {color:black;} + +.header_color, +.header_color a {color:#00acf7;} /* light blue */ +.header_color a:hover {text-decoration: underline;} +.accent_color {color:#e74815;} /* orange */ + +a.title, a.bottom_title:visited {color:#00acf7;font-size:1.1em;} +a.title:hover, a.bottom_title:active {color:#e74815;font-size:1.1em;} + +a.bottom, a.bottom:visited {color:#959797;font-size:1em;} +a.bottom:hover, div#bottom a.bottom:active {color:#00acf7;font-size:1em;} + +.divider {border-top:1px solid #cccccc;margin:20px 0 10px 0;} +small {font-size:90%;color:#999999;} + +.clearfloat:after { + content: "."; + display: block; + height: 0; + clear: both; + visibility: hidden; +} + +/*----------------------------- + GLOBAL HEADER #00acf7 +-----------------------------*/ +#globalheader_wrapper {background-color:#00acf7; width: 100%;height: 30px;margin-left: auto;margin-right: auto;} +#globalheader {position:relative;width: 970px;margin-left: auto;margin-right: auto;} +#globalheader ul {float:right;font-size: 0.9em; margin: 4px 0 0 0px;} +#globalheader li { + display:inline;list-style-type:none; + padding: 0 0 0 15px; + +} +.header {color: white;} +#globalheader li a { + -webkit-border-radius: 10px; + -moz-border-radius: 10px; + padding:2px 9px; +} +#globalheader li a:hover { + background-color: #027bb3; + color:white; +} +.header.selected { + color: #333333; + font-weight: normal; + background-color: white; + +} + + +/*----------------------------- + HEADER +-----------------------------*/ +#header_wrapper {width:100%;height:250px;margin:0;padding:0;position:relative;} +#header {width:970px;height: auto;text-align:right;margin-left: 0;padding-bottom:20px;background:#000;opacity:0.8;} +#header_wrapper2 {vertical-align:top;width: 100%;height: 120px;margin-left: auto;margin-right: auto;} +#header2 {width: 970px;height: 120px;text-align: right;margin-left: auto;margin-right: auto;} + +#container_right {float:right;} +#container_left {float:left;} + +#logo {float:left;text-align:left;margin-left:-5px;margin-top:10px;} +#logo_internal {float:left;text-align:left;margin-top:10px;} +#logos span {display:block;font-size:1.4em;padding:10px 0 0 10px;} + +#tag {margin-top:10px;margin-bottom:15px;background:#000;opacity:0.8;padding:5px;} +#tag p {line-height:270%;color:white;} +#header2 #tag .strapline {font-size:1.6em;} +#header2 #tag {margin-top:33px;} + +#download_btn {width:352px;text-align:center;float:right;} +#header #download_btn { } +#download_btn p {line-height:420%;} +#download_btn p a.download:link, a.download:visited {display:block; width:252px; height:57px; background-image: url('images/btn_download.png'); background-position:top left;} +#download_btn p a.download:hover, a.download:focus {background-position:left 116px;} +#download_btn p a.download:active {background-position:left 116px;} +#download_btn p a {outline:none;font-size:1.7em;font-weight:normal;color:white;} + + +/*----------------------------- + FOOTER #95ddfc +-----------------------------*/ +#footer_wrapper {background-color:#00acf7; vertical-align:top;width: 100%;margin-left: auto;margin-right: auto;} +#footer {position: relative;width: 970px;height: 110px;text-align: right;margin:0 auto;} +#footer_right {position:absolute;top:28px; right:0px;} +#footer_right span {color:#0d7aac; font-size:0.9em;} +#footer_right span.text {color: #0d7aac; font-size:0.9em;} +#footer_right p {font-size:0.9em;color:#48c5fe;} +#footer_right a {color:#48c5fe;} +#footer_right a:hover {text-decoration: underline;color:black;} + + +/*----------------------------- + CONTENT WRAPPER +-----------------------------*/ +#content_wrapper {width: 100%;margin:0 auto;} +.content {width: 970px;margin:0 auto;} +.content p, .content li, .content pre {/* font-size: 0.9em; */} +p.leader {font-size:1.2em;} + +/*----------------------------- + HOME +-----------------------------*/ +#container_strapline { + text-align:right; + width: auto; + float:right; +} +#container_strapline #tag { + margin-top:4px; + width:400px; +} +#homepage #tag .strapline {font-size:2.2em; line-height:1.2em; font-weight: bold; color:#ff5822; text-shadow:6px 4px 6px black;} +#homepage #tag {background: none; width:620px;opacity:1;} +#homepage #tag p {margin-bottom:17px;} +#homepage #tag p.strap {font-size:1.2em; line-height:1.2em; text-shadow:4px 3px 4px black;} + +#homepage .features_left, +#homepage .features_right { + font-size:1.2em; +} + +#box_wrapper { + padding:12px 26px 26px; + background-image: url(images/homepage_banner.jpg); + background-repeat: no-repeat; + background-color: #333333; + margin-top:27px; + height:250px; + position:relative; +} +#box_wrapper h1 { + text-align: center; + font-weight: normal; + color:#333333; + margin-bottom:10px; +} +#threecolbox { + width:274px; + height:274px; + float:left; +} +#threecolbox.left { + margin-right:46px; +} +#threecolbox.middle { + margin-right:46px; +} +#threecolbox.right { + margin-right:0; +} +#bottom2 #threecolbox { + width:292px; + height:auto; + margin-bottom:40px; +} +h2.latest_tweet { + background-color:#EEEEEE; + margin-left:-10px; + margin-top:5px; + padding:5px 10px; + -webkit-border-radius: 9px; + -moz-border-radius: 9px; +} +.latest_tweet_tail { + background-image: url(images/latest_tweet_tail.gif); + background-position: -10px top; + background-repeat: no-repeat; + display:block; + height:13px; +} +.latest_tweet ul li a { + color:#999999; +} +.latest_tweet ul li a:hover { + color:#666666; + text-decoration: underline; +} + +#top_left {float:left;width:470px;margin-right:15px;} +#top_right {float:right;width:470px;margin-left:15px;} +#top_right h1 {margin-bottom:10px;} +li.leader { + height:115px; +} +div.button { + cursor: pointer; + height:65px; + width:180px; + border:1px solid #666666; + color:white; + display:block; + font:bold 16px Arial,Sans-serif; + padding:12px; + text-align:center; + vertical-align:middle; + text-decoration:none; + letter-spacing: 0.05em; + text-shadow:-1px -1px 0px #000000; + background-color: #E74815; + background-image:url(images/button_shadow.png); + background-repeat: repeat-x; + background-position: left -12px; + -webkit-border-radius: 12px; + -moz-border-radius: 12px; + -webkit-box-shadow: 0 2px 10px rgba(0,0,0,0.4); + -moz-box-shadow: 0 2px 10px rgba(0,0,0,0.4); + box-shadow: 0 2px 10px rgba(0,0,0,0.4); +} +div.button:hover { + background-position: left -32px; +} +div.button a { + color:white; + display:table-cell; + height:65px; + vertical-align:middle; +} +.features_left div.button { + background-color:#00ACF7; +} +.button_arrow { + margin-bottom: 7px; + width:208px; + text-align: center; +} + + +ul.features_left {float:left;width:230px;margin-top:10px;} +ul.features_right {float:right;width:230px;margin-top:10px;} +ul.features_left li {padding-right:15px;} + +div#top_right ul.features_bottom {float:left;margin-top:0px;font-size:0.8em;margin-left:0;padding-left:0;} +div#top_right ul.features_bottom li {list-style-type:none;display:list-item;margin-bottom:10px;margin-left:0;padding-left:0;} + +.display {margin-bottom:20px;} +#bottom { + margin-top:36px; + padding-bottom:35px; + margin-bottom:20px; + border-bottom:1px solid #dddddd; +} +/* +.bottom_left { + width: 425px; + float: left; + padding:10px 15px 15px 15px; + background-color:#e8e9e9; + min-height:85px; + margin:15px 0 45px 0; + -moz-border-radius:8px; + -webkit-border-radius:8px; + -webkit-box-shadow: 0 2px 5px rgba(0, 0, 0, 0.45); + -moz-box-shadow: 0 2px 5px rgba(0, 0, 0, 0.45); +} +.bottom_right { + width: 440px; + float: right; + padding:10px 15px 15px 15px; + background-color:#e8e9e9; + min-height:85px; + margin:15px 0 45px 0; + -moz-border-radius:8px; + -webkit-border-radius:8px; + -webkit-box-shadow: 0 2px 5px rgba(0, 0, 0, 0.45); + -moz-box-shadow: 0 2px 5px rgba(0, 0, 0, 0.45); +} +.bottom_right p, +.bottom_left p { + font-size:1em; +} +#bottom h1 {margin-bottom:5px;} +*/ + + +/*----------------------------- + INTERNAL PAGES +-----------------------------*/ +#page_contents {float:left;width:740px;min-height:400px;margin-left:30px;margin-bottom:40px;} +#page_contents h1 {margin-top:20px;} +#page_contents h1:first-child {margin-top:0;} +#page_contents p {margin-bottom:9px;} +#mid_left {float:left;width:350px;margin-top:20px;} +#mid_right {float:right;width:350px;margin-top:20px;} + + +/*----------------------------- + ABOUT +-----------------------------*/ +ul.team {margin-bottom:9px;} +ul.team li {padding-bottom:5px;} +ul.team li span {font-weight: bold;} +.award {border:1px solid #cccccc;padding:6px;margin-top:20px;-moz-border-radius:8px;-webkit-border-radius:8px;} +.award_badge {float:left;width:110px;height:87px;display:block;margin-right:20px;margin-top:-25px;} +.award_text {padding:25px 0 0 0;} +ul.advisors li {display:list-item;text-align:left;list-style-type:none; vertical-align:top;float:left; width:320px;margin:0px 0px 3px 0;} +ul.advisors li span.left_ad {float:left;margin: 0 0 10px 0px;} +ul.advisors li span.right_ad {width:260px;float:right;line-height:120%;} +.right_ad span {font-weight: bold;} + +ul.list_style li {list-style: disc; list-style-position: inside;padding-bottom:5px;} +ul.list_style ul.list_style {padding-top:5px;} +ul.list_style ul.list_style li {padding-left:20px;list-style:circle;list-style-position: inside;} + + +/*----------------------------- + HOSTING / SERVICES +-----------------------------*/ +.hosting_company {margin:20px 20px 0 0px;padding:7px; background: #eeeeee; -webkit-border-radius: 6px; -moz-border-radius: 6px;} +#page_contents .hosting_company p {margin:4px 0 0 0;} +#page_contents .continent {font-weight: bold; margin:10px 0 0 0;} +.sidebar_box {margin-top:30px; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border:1px solid #cccccc; + padding:6px; + +} +.sidebar_box p {margin-bottom:9px;} +.sidebar_box h2 { + color:#333333; +} +.sidebar_box .list_style {margin-bottom:8px;} +.subhead {font-weight:bold;} +.partners {margin:20px 20px 0 0px;padding:7px 7px 10px 7px; background: #eeeeee; -webkit-border-radius: 6px; -moz-border-radius: 6px;} + + +/*----------------------------- + SIDEBAR MENU +-----------------------------*/ +#sidebar_menu {float:left;width:200px;margin-bottom:40px;} +#sidebar_menu ul li {padding:2px 0 3px 0;} +#sidebar_menu a.aboutmenu:link, a.aboutmenu:visited {display:block; width:180px; height:22px; font-weight:bold;background:#dedede; color: #777777;-moz-border-radius:8px;-webkit-border-radius:8px;} +#sidebar_menu a.aboutmenu:hover, a.aboutmenu:focus {background:#00acf7;color: #FFFFFF;} +#sidebar_menu a.aboutmenu:active {background-position:bottom;color: #FFFFFF;} +#sidebar_menu a {outline:none;font-size:1em;font-weight:bold;text-decoration:none;text-decoration: none;padding:5px 0 0 10px;} +#sidebar_menu .selected {background:#00acf7;color: #FFFFFF;} diff --git a/supporter.php b/supporter.php new file mode 100644 index 0000000..43b6da2 --- /dev/null +++ b/supporter.php @@ -0,0 +1,144 @@ + + + + + Elgg - Open Source Social Networking Platform. + + + + + + + + + +
            +
            + +
            +

            Elgg Supporters

            +
            +
            + + + + +
            Choose your level
            + + + +
            +
            +


            + Are you an individual or organization would uses and likes Elgg? If so, then consider becoming an official supporter of the Elgg project. For only $50 per year for individuals and $150 per year for organizations, you can help the Elgg project.
            +

            +

            Elgg supporters are listed below unless requested not to be. If you would like to become an Elgg supporter, please read the disclaimer located in the lefthand sidebar, then subscribe via PayPal and then send an email to supporters@elgg.org confirming the date you subscribed and the relevant details for your level (these can be found on the tables below). Once all the details have been received, we will add you to the appropriate list. Thanks for your support!

            +
            +

            Organization Supporters

            + + + + + + + + + + + + + + + + + + + + + + + + + +
            NameOrganization URLOrganization NameCommunity Profile
            Irene Ilinahttp://www.skadate.comSkaDate Dating Software LLC
            Fabrice Collettehttp://www.meleze-conseil.comMélèze ConseilVisit
            Paul Stewarthttp://arckinteractive.comArck Interactive LLC
            +
            +
            +

            Individual Supporters

            + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
            NameWebsiteCommunity Profile
            Ben Werdullerhttp://benwerd.comVisit
            Mark Bridgeswww.activityseeker.comVisit
            Per Jensenhttp://www.me4real.com/Visit
            Dhrup ChandFBFKids.ComVisit
            Torsten Wesolekcommunity-software-24.comVisit
            +
            +
            +
            +
            + +
            + + + + \ No newline at end of file