cover photo

Hubzilla Development

M. Dent
@Mario Vavti

I saw the "remove item" stuff.  Looks good!  There is a means to "update" items that are in the cart  - with deletion happening when an item is updated to quantity 0.  But I can see some utility to deleting all instances of a SKU as well.  I didn't examine it fully, but I got the sense of what you have.  Given "how things work now," it's a reasonable approach.

Just a few things to keep in mind, though:

There are some instances where deleting all instances of a SKU in an order will be undesirable.  For example - in the case of a SKU with customizable options (color, size, engraved text, or other custom options) and multiple "versions" of that SKU are desired (eg, ordering 4 items of the same SKU with different size/color/text on each).  In those cases, a customer may want to delete one "version" of the ordered item and keep the others.

The choice to have every item on it's own line was a pragmatic decision at this stage to reduce coding/debugging to get a workable system out as quickly as I was able - but at least SOME of the update code exists already.  An update to a quantity of 0 will remove the line-item from the order.

Additional orders for the same SKU can be aggregated using the before_additem hooks to check to see if there is an item with that SKU in the order already and doing and UPDATE instead of an ADD.  This should be done using the cart_order_before_additem_$itemtype hook - because some types of items should not be aggregated (see notes above) so you don't want to apply it to ALL items of the same SKU, just those of itemtypes for which it is appropriate.
M. Dent
I've got other obligations until early afternoon today, but here's some code snippets I used.... I was just beginning work on the "remove" aspect of the catalog that you added, so I don't have any progress there.  But I did get the cart_post_update hook and a hook to update the quantity done - as well as code in the order template to allow updating orders there.

Not that you have to do it this way.... but if you haven't started these parts or are stuck, this might be helpful.


function cart_post_update_item () {

        $orderhash = cart_getorderhash(false);
        if (!orderhash) {
                notice (t("Order Not Found").EOL);

        $order = cart_loadorder($orderhash);

        foreach ($order["items"] as $item) {
          if ($item["item_confirmed"]) {

function cart_updateitem_qty_hook(&$hookdata) {
        //POSTVAR qty-$item_id
        if(!is_array($item)) {return;}
        $hookdata["iteminfo"]["item_qty"]=isset($_POST[$postvar]) ? preg_replace('[^0-9\.]','',$_POST[$postvar]) : intval($item["item_qty"]);


                <table class="w-100">
                                <th width=10%>Qty</th>
                                <th width=50%>Description</th>
                                <th width=20% style="text-align:right;">Price each {{if $currencysymbol}}({{$currencysymbol}}){{/if}}</th>
                                <th width=20% style="text-align:right;">Extended</th>
                        <form method="post">
                                <input type="hidden" name="cart_posthook" value="update_item">

                        {{foreach $items as $item}}
                                        {{if $order_checkedout}}{{$item.item_qty}}
                                        <input type="text" name="qty-{{$}}" value="{{$item.item_qty}}" size=4>
                                <td style="text-align:right;">{{$item.item_price}}</td>
                                <td style="text-align:right;">{{$item.extended}}</td>
                        {{if !$order_checkedout}}
                                <td colspan=4><button class="btn btn-outline border-0" type="submit" name="Submit" title="Update Cart">Update</button></td>
                                <th style="text-align:right;">Subtotal</th>
                                <td style="text-align:right;">{{$totals.Subtotal}}</td>


                                <td>{{if $item.order_qtty}}<i class="fa fa-shopping-cart"></i> {{$item.order_qtty}}{{/if}}</td>
                                        {{if $item.order_qtty}}
                                        <form method="post">
                                                <input type="hidden" name="cart_posthook" value="update_item">
                                                <button class="btn btn-outline-danger btn-outline border-0" type="submit" name="qty-{{$}}" value=0 title="Remove from cart"><i class="fa fa-remove"></i></button>

I think I was debugging the catalog stuff when I finally called it quits and went to bed.

Like I said, these are only starting points.  As long as the functionality is there, we can refactor in the future if needed.
Mario Vavti
Have just seen this. I had already checked in something. I will see what i need to adjust...
Mario Vavti
I am afraid i'll have to postpone more work on this to after the RC :no_mouth: - need to study the code way more...
Perhaps you can have a look at what i did so far:

What is your suggestion regarding a link to the purchased item (in case the item is a digital download). I guess the easiest way to implement this would be to provide an item link in the SKU and show it after the item is fulfilled.

I possibly found a type in cart.php on line 1737. cart_after_fullfill_finishorder() should probably be cart_after_fulfill_finishorder().

Mario Vavti
@M. Dent i wonder what your plans with $session_orderhash and $query_orderhash are.
As it's implemented now in cart_getorderhash(), after adding an item to the cart it will not look to the DB again. Hence, if ordering from two different browsers (respectively sessions), they don't actually know from each other.
Is this behaviour intended?

!Hubzilla Development
M. Dent
Actually, they should know about each other.  Here's what the flow is currently.  I see some issues (described below) which I will fix this morning.

1) If there is a QUERY variable "cart" use that as the orderhash
2) If there is no QUERY variable "cart" - use the session variable as the orderhash
3) a) If we have an order hash ---> Check to make sure that the order associated with the orderhash:
     1) exists
     2) belongs to the observer
     3) has not been checked out.
    b) If we do not have an order hash (no query / no session) grab the first order for this buyer that is not checked out & set the session variable.

With the current implementation, if there is only one "store" on the server the two browser scenario isn't a problem.  The second browser will grab the currently open order from the database.  If there is more than one store, it may or may not depending on if it happens to grab the order for the current "store."  That's problem #1.

Problem #2 is, currently, if the get/session order is invalid, it will not probe the database but return null or a new order hash.

Problem #3 is that currently if using the "cart" query variable, the orderhash isn't updated in the session, so on the off chance a customer has more than one valid open order in a given store, it's possible to start the checkout process on one cart and be dropped into a different cart part way through.

Those should be fairly easy fixes - and you should have a merge request for them soon.

Problem #4 (similar to #3) is that because the session variable isn't set when using the query variable, it may be possible to have two separate open orders created by the same customer with no ability to switch from one cart to another.  It would be a rare occurance, but is (currently) possible.  As long as this is possible, it remains a little harder to solve.  The goal is to make this impossible. (which the fixes for the above should do).

Problem #5 has to do with trying to have 2 different users/profiles using the same browser session.  But Hubzilla doesn't currently seem to handle that gracefully, so I'm not sure that scenario is fixable.

The $query_orderhash is intended to allow things like direct links to abandoned carts or the ability to start the checkout/update process on an abandoned cart on the outside chance of multiple open orders for the same customer.

Only kind of related:  I wanted to ask/talk about the removeitem functions you added which I will do in a separate thread.
M. Dent
getorderhash updates included in recent PR (that replaces the PR I submitted overnight - I really need to NOT submit PR's at 2:30 AM... nothing good ever comes of it).

M. Dent
Mike has spoken for himself regarding his role in Hubzilla development - but this may provide a view from another mature developer of a major project who was "Benevolent Dictator For Life" that has removed himself from that role:

M. Dent
In putting together the PAYPAL integration for the CART plugin, I discovered more about the depth of the security consciousness of the devs (OK, let's be honest, probably Mike!). -  They (he?) thought of everything, it seems.  Including "Content-Security-Policy" headers.

In the case of PAYPAL (and other payment processors), there's a need to modify the CSP to allow the checkout.js script from PAYPAL to run (optimally [according to them] it should be loaded from THEIR server).  This is something that numerous others do as well (eg. STRIPE - a creditcard processor)].  But as is, the Content-Security-Policy breaks loading of off-site scripts.

One solution is to weaken security and turn off Content-Security-Policy headers in .htconfig.php, as the comment indicates:

// These lines set additional security headers to be sent with all responses
// You may wish to set transport_security_header to 0 if your server already sends
// this header. content_security_policy may need to be disabled if you wish to
// run the piwik analytics plugin or include other offsite resources on a page

It seems, thought, that the list of things that may require disabling is only likely to grow, and I really like the CSP restrictions.

There are a several ways to make it so the CSP can be manipulated - but it seems to me that the best solution is one that allows addon authors to change the string in a context dependent manner rather than needing to directly manipulate the string (and possibly remove or corrupt something important).  

As a proposal, I suggest a hook based solution - which would allow the inclusion through a registered hook or by using the Hook::insert() function for inclusion in narrowly contexts (eg., only scripts from a certain offsite host are only permitted in pages originating with a specific plugin).

Anyway, here's the proposed code for initial review/consideration.  If there are better implementations - that'd be great - this is just a first stab.  If it looks OK as is, I'll submit a Merge Request.

FILE: boot.php

        if(App::$config['system']['content_security_policy']) {
                $cspsettings = Array (
                        'script-src' => Array ("'self'","'unsafe-inline'","'unsafe-eval'"),
                        'style-src' => Array ("'self'","'unsafe-inline'")

                // Legitimate CSP directives (cxref:
                        "default-src", "script-src", "style-src",
                        "img-src", "connect-src", "font-src",
                        "object-src", "media-src", 'frame-src',
                        'sandbox', 'report-uri', 'child-src',
                        'form-action', 'frame-ancestors', 'plugin-types'
                $cspheader = "Content-Security-Policy:";
                foreach ($cspsettings as $cspdirective => $csp) {
                        if (!in_array($cspdirective,$validcspdirectives)) {
                                logger("INVALID CSP DIRECTIVE: ".$cspdirective,LOGGER_NORMAL);
                        $cspsetpolicy = implode(' ',$cspsettingsarray);
                        if ($cspsetpolicy) {
                                $cspheader .= " ".$cspdirective." ".$cspsetpolicy.";";
                //Original CSP Header
                //header("Content-Security-Policy: script-src 'self' 'unsafe-inline' 'unsafe-eval'; style-src 'self' 'unsafe-inline'");
M. Dent
Good point... of course, I read this literally 10 seconds after submitting the Merge Request.   I'll resubmit.

Perhaps switching to DEBUG or even TRACE?  Or just drop it entirely?
Mike Macgirvin
If you've already submitted - leave it. Feel sorry for the person that triggers it.
M. Dent
Knowing my luck..... it'll be me! LOL
  last edited: Thu, 12 Jul 2018 08:21:31 -0400  
poVoqpoVoq wrote the following post Thu, 12 Jul 2018 08:12:58 -0400
Actually, looking at it a bit closer this is not a server wide thing, but a per channel setting... thus really only for individual app passwords etc.

Would be nice though if Hubzilla would also support OpenID Connect provision. That way HubZilla could act as a identity management (already very nice with all the profile settings) for various other webservices provided by the hub-server. And given the easy to use nomadic identities this would link together multiple servers with one ID.

I think this Drupal plugin provides a similar functionality, so maybe a good starting point for someone looking into this?

@Mike Macgirvin Am I right in assuming the following: Through Zot Hubzilla provides a sort of SSO across multiple servers, thus if you have a cloned channel on a server you automatically log into the site when visiting. Thus if that server would provide SSO through OpenID Connect, one would also automatically log into any other non-hubzilla webservices on that server, right? That would make for a really easy to use and convenient multi-server SSO solution :)

!Hubzilla Development

Seems like this kind of OpenID Connect provision would be a really useful feature to have in Hubzilla for SSO.

It's a bit above my head to implement such a core feature, but given the existing OAuth2 server in Hubzilla it might not be that hard to do?
Mike Macgirvin
The existing OAuth2 server implements OpenIDConnect.
  last edited: Thu, 12 Jul 2018 10:30:26 -0400  
That's great!

But what I don't see is a way for the main administrator to generate a general id&token to configure other sites.

What seems possible is to create these as a channel owner in the settings page. But if I would then configure my (for examble) Wordpress page to have a nice "Log in with Hubzilla" button using OpenID Connect then only the channel owner would be able to use it, but none of the other users of my hub I think.

Or am I missing something?

Max Kostikov
 Königsberg, Russia,  last edited: Wed, 11 Jul 2018 06:55:32 -0400  
!Hubzilla Support Forum !Hubzilla Development
I just found an issue with links in Hubzilla comments.
If I press on name in redirects to user channel but shows me a banner "channel not found".
Lets say Mario Vavti name in comment have link

but if I press on it adds after & its HTML analogue amp; and brokes URL


But for example for Mike Macgirvin it works.
I didn't saw such behaviour before. May be latest commits broke redirection.
Mario Vavti
  last edited: Thu, 12 Jul 2018 15:34:18 -0400  
@Mike Macgirvin i still see this issue between two dev sites:
Have not found yet a way to reliably duplicate but it definitely happens sometimes...

EDIT: possibly nginx behaves different from apache?
Mario Vavti
@Max Kostikov i plan to release an RC next week if nothing blows up meanwhile...
Max Kostikov
It would be great!
BTW me and my Hubzilla friends opened few tickets in issue tracker on Framagit. I hope you will have time to check it.
Mike, Mario and other guys involved - many thanks for Hubzilla!

  last edited: Wed, 11 Jul 2018 09:07:13 -0400  
!Hubzilla Development
I just saw Mike's post about Zot6, denim, zap and vassal. Does that mean that those new apps will replace hubzilla in terms of priority, development etc (i read zot6 will be backported to hubzilla which usually suggest that thats the case)?
Or at least shift the focus to those new apps instead of hubzilla? Is there a point to actively work and improve on hubzilla and promote it if in few weeks/months we might be switching to new thing?
Mike Macgirvin
You mean turn all the extra features etc. into apps?


similar to what it is now but with more explanations etc

  last edited: Thu, 12 Jul 2018 12:34:57 -0400  
Hubzilla is a platform and develop could code for that platform all kind of things... I mean it should work like it did for other cms systems as well... all this plugins that come up after a while for WP...
But for some reasons this does not happen for Hubzilla.... Now the new apps of Mike might be an other try to spread the best parts of Hubzilla out in the world  again -  in the hope  this new apps catch fire among developers.
Mike Macgirvin
I've brought all the recent addon/app work to the red/hubzilla tree. I will also try to (where possible) get some of the Zot6 code moved over so that it can start to be integrated. There are some major unresolvable conflicts - most notably Daemon/Notifier; but I'll do what I can to keep Hubzilla moving forward and not let it lag.

M. Dent
Submitted a merge request to addons/dev to integrate a PayPal payments interface to the cart system.  Various updates to the rudimentary administration tools and (you guessed it) more hooks for custom additions.  Hopefully I can do some basic docs.  To use, you need to set up Paypal API Keys (Client/Secret) for the REST API.  (see for instructions)

In order to use the PAYPAL checkout flow, CONTENT-SECURITY-POLICY headers must be disabled in .htconfig.php  (Would love a hookable architecture for CSP so that plugins can add items rather than needing to disable the policy entirely - any takers?)

@Mario Vavti @Andrew Manning  @Mike Macgirvin
M. Dent
Ok, I have some other things to do but should be able to get a patch submitted before the weekend.
Mike Macgirvin
I've already patched but haven't committed yet. I'll push it  later today.
M. Dent
Wow! awesome, thanks!
Andrew Manning
I was trying to make a few Cards to see how one might combine existing Hubzilla tools to create a voting mechanism where people can choose from multiple options, and I discovered that once you vote you cannot revoke your choice like you can a like/dislike. I selected "Agree" then "Disagree" then "Abstain" and all three were recorded with my name, but I was unable to reverse those selections.
Mike Macgirvin
There's DB support for truly federated polls (the structures will work cross-platform with poll mechanisms in Diaspora, StatusNet and ActivityPub). There's no code support at this time. If anybody reading this want's to take it on, I'd suggest that the ActivityStreams format may be the ideal storage format for Hubzilla because it will map directly to Zot6 and ActivityPub.

Code exists in the consensus tools (implemented in the Like module) to undo (e.g. delete) all previous votes when making a new selection. This has worked fine in the past and hasn't changed in years so would require further investigation.

Hello Hubzillians,

Thanks to everybody, we now have enough names to start a poll so this is what we did.
Here is the link.
Poll stays open until 03-08-2018
Thank you.

Max Kostikov
 Königsberg, Russia,  last edited: Sun, 01 Jul 2018 16:25:41 -0400  
!Hubzilla Development
I'm use Hubzilla with latest PHP 7.2 release under FreeBSD environment (H2O HTTP/2 web-server + PHP-FPM).
It works quite fast but I think it can be faster with PHP opcache.
Perhaps experienced Hubzilla hub owners have any recommendations on opcache settings?
 from Diaspora
Czy ten wpis jest widoczny na Hubzilli?
!Hubzilla Development

Ta linijka dziwnie wygląda na Diasporze.
Max Kostikov
  last edited: Thu, 12 Jul 2018 15:26:52 -0400  
Well, let me publish my results on #PHP opcache usage with #Hubzilla.
As I wrote above I'm use PHP 7.2 in #FreeBSD 11.2 environment.
I installed php72-opcache package and changed only two parameters vs default configuration

root@beta:/usr/local/www/ # cat /usr/local/etc/php/ext-10-opcache.ini

After about a week of usage I might say that 64Mb memory buffer for opcache is more that enough not only for Hubzilla, but for other stuff that I have on same server (e.g. Roundcube, my own blog based on #Bludit flatfile #CMS and phpMyAdmin).
Memory consumption is remains less than 50Mb with cache hit rate about 99.96%.


Here is scripts usage visualisation.


And about performance. I didn't run special benchmarks but subjectively page load speed was dramatically increased. So I can recommend to use opcache for Hubzilla.

Hello, !Hubzilla Development

Can it be that Hubzilla posts with expiration date do not send delete notifications, or send some not understood by diaspora?

Yesterday I created an expiring post in Hubzilla, which was automatically deleted today. But I can still see my post in Hubzilla profile from diaspora account. diaspora developers say diaspora respects post deletions, from their answer I figured there shouldn't be any delays.

If Hubzilla doesn't send deletion notifications for expired posts to other networks, does it make this feature useful only for private posts? Public posts will gain little from it, outside of Hubzilla. If this can't be fixed, perhaps, this feature could be available only when the post permission is set to anything but "public" (or show warning if it's switched to "public")?
Andrew Manning
With Zot6, Zap, Denim, Red, and Mule in various phases of development I'm spread a bit thin at the moment.

It's always comforting to have a slightly insane person at the helm. Or actively redesigning the ships upon which we are all sailing. Right?
Mike Macgirvin
It's almost like you haven't been listening for the last two years. I'm on a different ship in a different bloody ocean. If you think I'm steering Hubzilla, you're seriously mistaken. Last couple of weeks was the first time in over a year that I've touched Hubzilla code since Mario has been mostly offline and a couple of urgent issues needed to be dealt with.
Thank you for your work, Mike (and all the Hubzilla devs).
Every fix improves the software!
!Hubzilla Development How to connect activitypub site e.g. for commenting? I tried insert url in textbox "add contact" as result "Remote channel or protocol unavailable." In mastodon all work.
hubzilla ver. 3.4.1
Mike Macgirvin
I've probed several urls on that site with a number of discovery formats and content-types and I can find no evidence of any ActivityPub, ActivityStreams, or even Webfinger services. Without any of these we can't make a connection. The only way I can figure to debug these is for them to make a connection in this direction so we have presumably valid ActivityPub URLs to work with. If you want to talk to somebody on the Plume side, we need an actor document that is served with an ActivityPub or ActivityStreams content-type. I can't find one. I've tried (discovered in one of the HTML documents returned)

The last example is using webfinger. All the others were requests for anything with content-types

application/ld+json; profile=""

using the HTTP Accept header. This was ignored in each case and an HTML document was returned which provided no additional discovery mechanisms in the header or body.

KLW's channel
I have installed the themes from
No themes show up on the webpage.
I used ./util/add_theme_repo



KLW's channel
This is the page /admin/themes, when logged in as administrator user:


Andrew Manning
Many thanks to massimiliano and the #Disroot community for creating and sharing their new Hubzilla #app for #Android. I was able to compile and install from the source code with no trouble at all (git clone, open in Android Studio, Build, install generated APK). This is an exciting addition that I personally have been seeking for a long time. I tried several times over the years to get an Android app online, but I just didn't have the time and expertise to get the job done. Now I am happy to study the #AndHub source and hopefully to contribute where I can to improve it.

disroot / AndHub
Hubzilla Android app
@Massimiliano you're the man!
Grant Stephenson
What I wonder is how hard it will be to make a html 5 app for the librem 5 (currently stuck on ios till that comes out)
@mrjive you can try SailfishX. Still lacks many features but very promising.
Haakon Meland Eriksen (Els Mussols)
@Hubzilla Development+ Local problem or code issue? Els Mussols is running version 3.4.1, version_tag 3.4.1 server_role pro commit 3fc955abf. The issue: sourcing has stopped. My channel MoodleNet Fan sources two ActivityPub feeds, the items show up in /network but are not sourced into the fan channel. Any ideas?

Max Kostikov
 Königsberg, Russia,  last edited: Sat, 23 Jun 2018 10:40:26 -0400  
!Hubzilla Support Forum
I subscribed on !Hubzilla Development forum but for unknown reason I doesn't recieve updates in my own hub network stream.
At my side latest message looks like


but really there is a lot of new posts


How can I figure out what is wrong and fix it?
Mike Macgirvin
If any of these were my posts/comments I had a delivery bug on my server for 2-3 days and resent a bunch of stuff once I discovered it.
Max Kostikov
It related on Hubzilla Development forum posts only. With Hubzilla Support Forum located on other hub I have not any issues.
 from Diaspora
Quiza no han tenido tiempo, no han querido o no han podido responderte.

Haakon Meland Eriksen (Els Mussols)
@Hubzilla Development+ What feedback can we give MoodleNet so they choose a decentralized architecture that works? :-)
Doug Belshaw 🇪🇺☠️✊Doug Belshaw 🇪🇺☠️✊ wrote the following post Fri, 22 Jun 2018 08:32:22 -0400
Haakon Meland Eriksen (Els Mussols)
Extended architecture document v 0.1

MoodleNet architecture options


MoodleNet is a new open social media platform for educators, focused on professional development and open content. It sustainably empowers communities of educators to share and learn from each other to improve the quality of education, and will be an integral part of the Moodle ecosystem. There are broadly three approaches we can take to building o...
Mike Macgirvin
How this is resolved ultimately depends on how the Moodle community reacts to authoritarianism.
Haakon Meland Eriksen (Els Mussols)
They have already voiced their dislike. I think decentralized is unfamiliar to Moodle, they seem to believe they need "some" centralized glue to make MoodleNet work, rather than winning hearts by being truely decentralized.

Lasantha Ranaweera
  last edited: Tue, 19 Jun 2018 06:25:57 -0400  
Hi !Hubzilla Development,

First of all sorry about my limited knowledge in Hubzilla.

We are thinking to use Hubzilla as our enterprise social media platform inside in our organisation. Currently our user profiles are exist in KeyCloack server ( which acts as identity provider for various services in the organisation. So the question we have right now is whether we can reuse existing user profiles in our identify provider to login to the hubzilla or not. Even if we managed to reuse the existing user profiles we may have to create channels for the users hubzilla.  So I am thinking which is the best approach implement this.

Does Hubzilla API support for for account, profile and channel creation ?
Waitman Gobble
ok here it is. i think i had to modify the hubzilla code to get image uploading to work, but this was quite some time ago and maybe that works now? if not i should have the bits laying around here somewhere. i haven't used this for awhile so it might need some tweaking.


class HubZilla {

private $auth;public $page;public $reponse;public $form_url;public $post_title;public $post_channel;public $post_status;public $new_email;public $new_pwd;public $new_uname;public $follow_url;public $machine;public $uinfo;public $msg_subject;public $msg_txt;public $msg_screen_name;public $filename;public $lat;public $long;public function __construct($user=null,$pass=null,$form_url=null){ if (!$user||!$pass||!$form_url) { $this->response = 'Error loading, not authorized.'; } else { $this->auth = base64_encode($user.':'.$pass); $this->form_url = $form_url; $this->page = '/account/verify_credentials'; $this->qp(); }}private function qp(){ if (!$this->auth||!$this->form_url) { $this->response = 'Error, not authorized.'; } else { if ($this->filename != '') { $postdata = http_build_query( array( 'title'=>$this->post_title, 'channel'=>$this->post_channel, 'status'=>$this->post_status, 'media'=>base64_encode(file_get_contents($this->filename)), 'media_name'=>basename($this->filename), ) ); } else { $postdata = http_build_query( array( 'title'=>$this->post_title, 'channel'=>$this->post_channel, 'status'=>$this->post_status, 'new_email'=>$this->new_email, 'new_password'=>$this->new_pwd, 'new_uname'=>$this->new_uname, 'follow_url'=>$this->follow_url, 'machine'=>$this->machine, 'uinfo'=>$this->uinfo, 'text' => $this->msg_txt, 'screen_name' => $this->msg_screen_name, 'title' => $this->msg_subject, 'lat' => $this->lat, 'long' => $this->long ) ); }

/* at the moment no verify_peer or cn check, todo - needs a ca */

$opts = array( 'http' => array( 'method' => 'POST', 'header' => [ 'Content-type: application/x-www-form-urlencoded', 'Content-length: '.strlen($postdata), 'Authorization: Basic '.$this->auth ], 'content' => $postdata ), 'ssl' => array( 'verify_peer' => false, 'ciphers' => 'HIGH:!SSLv2:!SSLv3' ) ); $ctx = stream_context_create($opts); $form = file_get_contents($this->form_url.$this->page, false, $ctx); $this->response = $form;

/* remove ghosts */

} } public function __toString() { return $this->response; } public function status_update($title,$channel,$status,$path=null) { if ($path) { $this->filename = $path; $this->page = '/statuses/mediap'; $this->qp(); $status .= $this->response; } $this->post_title=$title; $this->post_channel=$channel; $this->post_status=$status; $this->page = '/statuses/update'; $this->qp(); return $this->response; } public function status_show($channel) { $this->post_channel=$channel; $this->page = '/statuses/user_timeline'; $this->qp(); return $this->response; } public function create_account($email,$pwd,$uname) { $this->new_email = $email; $this->new_pwd = $pwd; $this->new_uname = $uname; $this->page = '/accounts/create'; $this->qp(); return $this->response; } public function follow_request($url) { $this->follow_url = $url; $this->page = '/follow/request'; $this->qp(); return $this->response; } public function up_about($machine) { $this->machine = $machine; $this->page = '/up/about'; $this->qp(); return $this->response; } public function show_about($user) { $this->uinfo = $user; $this->page = '/show/about'; $this->qp(); return $this->response; } public function send_message($subject,$txt,$screen_name) { $this->msg_subject = $subject; $this->msg_txt = $txt; $this->msg_screen_name = $screen_name; $this->page = '/direct_messages/new'; $this->qp(); return $this->response; } public function send_reply($id,$uri,$subject,$txt,$screen_name) { $this->msg_subject = $subject; $this->msg_txt = $txt; $this->msg_screen_name = $screen_name; $this->page = '/direct_messages/new?replyto='.urlencode($id).'&uri='.urlencode($uri); $this->qp(); return $this->response; } public function inbox() { $this->page = '/direct_messages'; $this->qp(); return $this->response; } public function conversation($uri) { $this->page = '/direct_messages/conversation?uri='.urlencode($uri); $this->qp(); return $this->response; } public function send_file($path) { $this->filename = $path; $this->page = '/statuses/mediap'; $this->qp(); return $this->response; } public function set_geo($lat,$long) { $this->lat = $lat; $this->long = $long; }


$uri = '[zrl=][/zrl]';

/* example 1, log in as admin and create account */
$test = new HubZilla('','password',$url);
echo $test->create_account('','password','dummy7');

/* example 2, log in as created user and post status update */
$test = new HubZilla('','password',$url);
$test->status_update('another test','dummy7','This is another test');

/* example 3, log in as created user and update about */

$machine = array();
$test = new HubZilla('','password',$url);

/* example 4, log in as created user and get 'about' from other local users */

$test = new HubZilla('','password',$url);
echo $test->show_about('dummy7')."\n";
echo $test->show_about('waitman')."\n";

/* example 5, log in as created user and view status */

$test = new HubZilla('','password',$url);
echo $test->status_show('dummy7');

/* example 6, log in as created user and connect to admin */
$test = new HubZilla('','password',$url);
echo $test->follow_request('');

/* example 7, upload image */

$test = new HubZilla('','password',$url);
echo $test->send_file('X206-0.jpg')."\n";

/* example 8, status post with image - also set geo coord */

$test = new HubZilla('','password',$url);
echo $test->status_update('test with photo','dummy6','This is a test with photo.','X206-0.jpg');

/* example 9, get direct message inbox */

$test = new HubZilla('','password',$url);
$js= $test->inbox();
$inbox = json_decode($js,true);

foreach ($inbox as $k=>$v)
$msg = $test->conversation($v['parent_mid']);
$jr = json_decode($msg,true);
foreach ($jr as $jk=>$jm)
$id = $jm['id'];
$uid = $jm['uid'];
$parent_mid = $jm['parent_mid'];
$sender = $jm['sender_screen_name'];
$recipient = $jm['recipient_screen_name'];
$date = date('m/d/Y g:i a',strtotime($jm['created_at']));

$message = $jm['text']; echo "Message Id: ".$id."\n"."UID: ".$uid."\n"."Parent Mid: ".$parent_mid."\n". "From: ".$sender."\n"."To: ".$recipient."\n"."Date: ".$date."\n".$message."\n"; echo "---------------------------------------------------\n"; }


/* example 10, send direct message */
$test = new HubZilla('','password',$url);
echo $test->send_message('A test subject','Hey there, this is totally like a test.','waitman');

/* example 11, send direct message reply */
$test = new HubZilla('','password',$url);

/* use previous subject */
echo $test->send_reply(33,'','','a test reply.','waitman');

/* change the subject */
echo $test->send_reply(33,'','A New Subject','a test reply.','waitman');
Waitman Gobble
oops, i haven't actually noticed that happening before on a code paste. :)
Lasantha Ranaweera
Thanks @Waitman.

Lasantha Ranaweera
  last edited: Tue, 19 Jun 2018 02:40:41 -0400  
Hi !Hubzilla Development,
I want to authenticate Hubzilla with external authentication provider like KeyCloak. Basically I don't want to create accounts in Hubzilla server and just want to use trusted tokens issued by third party to login to the system. Does Hubzilla support OAuth2 and OpenID Connect? Any documentation will be greatly appreciated.
  last edited: Sat, 14 Jul 2018 09:30:47 -0400  
I am also trying to get this to work, but with Hubzilla as the provider/server. My test case is a Wordpress installation with this plugin:

With the /authorize, /token and /logout I get already quite far, but it seems to be not fully working yet.

If I am logged into my Hubzilla account and click on the OpenID button in Wordpress, I get redirected to a "accept/reject" page on Hubzilla (but with an "unkown application" notice). If I click on accept however I get a json response
client_secret    "blablarandomstring"
error    "invalid_client"
error_description    "No client id supplied"

Edit: if I supply a random client ID in Wordpress, I get the following error on WP: "ERROR: This client is invalid or must authenticate using a client secret"
(I know I can create this per channel, but I am trying to create a instance wide login mechanism, not an individual app login).

If I am not logged in on Hubzilla it shows the login screen, but on login it redirects to a 404 page despite what appears to be close to the expected redirect url by wordpress (

I also think that one of the possible reasons it doesn't work is that normally OpenID Connect also expect a user info endpoint, something like this:
Any idea what could this be in the case of Hubzilla?

Anyways... help much apprechiated :)
poVoq hat Lasantha Ranaweeras Beitrag mit ⋕OpenIDConnect verschlagwortet
poVoq hat Lasantha Ranaweeras Beitrag mit ⋕SSO verschlagwortet