*/}}
Browse Source

Experimental entry improvements and etc

YimingWu 1 year ago
parent
commit
c85b56be22
2 changed files with 144 additions and 39 deletions
  1. 143 38
      index.php
  2. 1 1
      translations.md

+ 143 - 38
index.php

@@ -48,6 +48,7 @@ class LA{
     protected $MastodonPreferredLang;
     protected $HostURL;
     protected $GalleryStep;
+    protected $AllowLanguageChoices;
     
     protected $Redirect;
     protected $Translations;
@@ -195,9 +196,6 @@ class LA{
                       'RewriteCond %{HTTP_HOST} !=localhost'.PHP_EOL.
                       'RewriteCond %{REQUEST_URI}  !^.*(jpg|png|gif)$'.PHP_EOL.
                       'RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]'.PHP_EOL.PHP_EOL);
-        fwrite($conf, 'RewriteCond %{HTTP_HOST} !^www\.'.PHP_EOL.
-                      'RewriteCond %{HTTP_HOST} !=localhost'.PHP_EOL.
-                      'RewriteRule ^(.*)$ https://www.%{HTTP_HOST}%{REQUEST_URI} [L,R=301]'.PHP_EOL.PHP_EOL);
         fwrite($conf,'<Files ~ "\.md$">'.PHP_EOL.'deny from all'.PHP_EOL.'</Files>'.PHP_EOL);
         fflush($conf);fclose($conf);
     }
@@ -270,6 +268,7 @@ class LA{
         fwrite($conf,'- HostURL = '.$this->HostURL.PHP_EOL);
         fwrite($conf,'- APubID = '.$this->APubID.PHP_EOL);
         fwrite($conf,'- GalleryStep = '.$this->GalleryStep.PHP_EOL);
+        fwrite($conf,'- AllowLanguageChoices = '.$this->AllowLanguageChoices.PHP_EOL);
         fflush($conf);fclose($conf);
         $conf = fopen('la_redirect.md','w');
         fwrite($conf,$this->DisplayRedirectConfig());fflush($conf);fclose($conf);
@@ -780,7 +779,10 @@ animation:anim_loading 1s linear infinite;}
 .wscroll:target{display:block;} .post_ref .wscroll{display:none !important;}
 .wayback_link{display:inline;}
 .imd{object-fit:cover;width:100%;}
-.center_exp .imd{width:60%;}
+.center_exp .post>.imd,.center_exp .p_row{width:60%;}
+.center_exp .p_thumb img,.center_exp .p_thumb video{max-height:3rem;}
+.center_exp .p_thumb{max-height:3rem;filter:opacity(40%);}
+.center_exp .p_thumb:hover{filter:unset;}
 #here_buttons{display:contents;}
 .here_buttons_inner{position:absolute;margin:auto;top:0;left:0;right:0;bottom:0;max-height:100%;max-width:100%;}
 .here_btn{position:absolute;z-index:110;transform:translate(-50%,-50%);
@@ -805,7 +807,7 @@ width:2em;height:2em;display:block;border:1px solid %black%;background-color:rgb
 .inquiry_buttons{right:35%;}
 .table_top{left:calc(-50% - 1.7em);width:calc(154% + 0.5em);}
 .post_dummy > *{width:80%;max-width:55rem;}
-.center_exp .imd{width:80%;}
+.center_exp .post>.imd,.center_exp .p_row{width:80%;max-width:55rem;}
 .here_btn{width:1.5em;height:1.5em;}
 }
 
@@ -862,6 +864,10 @@ border-radius:unset;box-shadow:unset;font-size:1.3rem;text-shadow:unset;}
 table img{max-width:30vw !important;}
 .product_ref{width:100%;display:block;}
 .post_dummy > *{width:100%;max-width:25rem;}
+.center_exp .post>.imd,.center_exp .p_row{width:100%;max-width:25rem;}
+.center_exp .post .p_thumb img,.center_exp .post .p_thumb video{max-height:2rem;}
+.center_exp .p_thumb{height:2rem;filter:opacity(40%);}
+.center_exp .p_thumb:hover{filter:unset;}
 .sticky_title{top:0;}
 .small_footer{position:relative;}
 #upload_selector{width:100%;}
@@ -944,7 +950,7 @@ blockquote{border-left:2px solid black;}
 ";
         $this->style=preg_replace('/%highlight_white%/','#5b3607',$this->style);
         $this->style=preg_replace('/%highlight_slice%/','#734307',$this->style);
-        $this->style=preg_replace('/%grayslice%/','#1a1002',$this->style);
+        $this->style=preg_replace('/%grayslice%/','#442c0b',$this->style);
         $this->style=preg_replace('/%post_white%/','#2d2110',$this->style);
         $this->style=preg_replace('/%white%/','#231a0d',$this->style);
         $this->style=preg_replace('/%black%/','#f8ca9b',$this->style);
@@ -1541,8 +1547,8 @@ blockquote{border-left:2px solid black;}
                 foreach($matches as $ma){ $th['interesting'][] = $ma[1]; }
             }
         }
-        if(preg_match('/\{\s*REVERSED\s*(\s+.*?)?\}/imu',$first_post['content'],$m)){ $th['reversed'] = 'm';
-            if(isset($m[1])&&preg_match('/$\s*(y|m|d)/iu',$m[1],$ma)){ $th['reversed']=$ma[0]; }
+        if(preg_match('/\{\s*REVERSED(\s+.*?)?\}/imu',$first_post['content'],$m)){ $th['reversed'] = 'm';
+            if(isset($m[1])&&preg_match('/^\s*(y|m|d|p)/iu',$m[1],$ma)){ $th['reversed']=$ma[1]; }
         }
     }
     function IsInterestingPost(&$p){
@@ -1639,6 +1645,7 @@ blockquote{border-left:2px solid black;}
                 if($mo=='y'&&$this_y!=$last_y){ if(isset($ch[0])){$chunks[]=$ch;$ch=[];} $n['restart']=$this_y; }
                 if($mo=='m'&&$this_m!=$last_m){ if(isset($ch[0])){$chunks[]=$ch;$ch=[];} $n['restart']=$this_y.'/'.$this_m; }
                 if($mo=='d'&&$this_d!=$last_d){ if(isset($ch[0])){$chunks[]=$ch;$ch=[];} $n['restart']=$this_y.'/'.$this_m.'/'.$this_d; }
+                if($mo=='p'){ if(isset($ch[0])){$chunks[]=$ch;$ch=[];} }
                 $ch[]=$n; $last_id=$this_id; $last_y=$this_y; $last_m=$this_m; $last_d=$this_d;
             }if(isset($ch[0])){$chunks[]=$ch;} if(isset($chunks[0])){$use_chunks=array_reverse($chunks);}
             $final[]=&$first_post;
@@ -2204,7 +2211,6 @@ blockquote{border-left:2px solid black;}
         $finger = ["subject"=>"acct:".$name.'@'.$without_protocol,
                    "links"=>[["rel"=>"self", "type"=>"application/activity+json", "href"=>$host."?apub_actor=1"]]];
         fwrite($f, "<?php header('Content-Type: application/json'); echo '".json_encode($finger, JSON_UNESCAPED_SLASHES)."'; ?>"); fclose($f);
-        
         if(!file_exists('.well-known/apub_public_key.pem') || !file_exists('.well-known/apub_private_key.php')){
             $res = openssl_pkey_new();
             $this->APubPublicKey = openssl_pkey_get_details($res)['key'];
@@ -2215,7 +2221,10 @@ blockquote{border-left:2px solid black;}
             fwrite($f, "<?php exit; ?>".PHP_EOL.PHP_EOL.$this->APubPrivateKey); fclose($f);
         }
     }
-    
+    function APubInit(){
+        $kf = file_get_contents('.well-known/apub_private_key.php'); if($kf===false) return;
+        preg_match("/(-----BEGIN PRIVATE KEY-----[\s\S]*)/",$kf,$ma); $this->APubPrivateKey=$ma[1];
+    }
     function APubEnsureInfo(){
         if(!isset($this->APubID) || !isset($this->HostURL)) return;
         if(!file_exists('.well-known/apub_public_key.pem')){$this->APubEnsureWebfinger($this->APubID, $this->HostURL);}
@@ -2264,6 +2273,75 @@ blockquote{border-left:2px solid black;}
         $obj['orderedItems'] = $items; $obj["totalItems"] = sizeof($items);
         return json_encode($obj, JSON_UNESCAPED_SLASHES);
     }
+    function APubDeliver($body,$target){
+        $head_digest = base64_encode(hash("sha256",$body,true));
+        $body_digest = "SHA-256=".$head_digest;
+        // rfc standards require the timezone be declared as GMT and PHP's built-in formats all say UTC
+        // so we gotta do it manually
+        $d = new DateTimeImmutable("now", new DateTimeZone('Asia/Shanghai'));
+        $d=$d->setTimezone(new DateTimeZone('UTC'));
+        $date=$d->format("D, d M Y H:i:s")." GMT";
+        $data = "(request-target): post ".parse_url($target,PHP_URL_PATH)
+                ."\nhost: ".parse_url($target,PHP_URL_HOST)
+                ."\ndate: $date"
+                ."\ndigest: $body_digest";
+        if (openssl_sign($data, $signature, $this->APubPrivateKey, OPENSSL_ALGO_SHA256) === FALSE) {
+            http_response_code(500); die('unable to sign');
+        }
+        $signature =  base64_encode($signature);
+        $keyid =      'keyId="'.$this->HostURL.'?apub_actor=1#main-key"';
+        $algo =       'algorithm="rsa-sha256"';
+        $headers =    'headers="(request-target) host date digest"';
+        $signature =  "signature=\"$signature\"";
+        $h = array(
+            'Content-Type: application/activity+json',
+            'Accept: application/activity+json',
+            //"Content-Length: ".strlen($body),
+            "Host: ". parse_url($target,PHP_URL_HOST),
+            "Date: $date",
+            "Digest: $body_digest",
+            "Signature: $keyid,$algo,$headers,$signature"
+        );
+        $ch = curl_init($target);
+        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
+        curl_setopt($ch, CURLOPT_POSTFIELDS, $body);
+        curl_setopt($ch, CURLOPT_HTTPHEADER, $h);
+        curl_setopt($ch, CURLOPT_USERAGENT, "laMDWiki APub");
+        $result = curl_exec($ch);
+        curl_close($ch); echo "<pre>";
+        print_r($body); echo "\n\n".$target."\n\n";
+        print_r($result); echo "\n\n"; print_r($h);
+        echo "\n\n"; print_r(curl_getinfo($ch)); echo "</pre>"; exit;
+        return $result;
+    }
+    function APubTestDeliver(){
+        $this->APubInit();
+        $obj=[];
+        $obj['published']=gmdate("Y-m-d\TH:i:s\Z");
+        $obj['id']=""; //<-------------------
+        $obj['url']=$this->HostURL.""; //<-------------------
+        $obj['type']='Note';
+		$obj['attributedTo']=$this->HostURL."?apub_actor=1";
+		$tag=[]; $tag['type']='Mention'; $tag['name']="@chengdulittlea"; $tag['href']="https://mastodon.art/users/chengdulittlea";
+		$obj['tag']=[$tag];
+		// must have cc to have notification in mastodon.
+		$obj['cc']=["https://mastodon.art/users/chengdulittlea"];
+		$obj['content']="<p>@chengdulittlea Hello activitypub from laMDWiki!</p>";
+		$obj['to']="https://www.w3.org/ns/activitystreams#Public";
+		$obj['inReplyTo']=""; //<-------------------
+        $arr=[];
+        $arr['@context']="https://www.w3.org/ns/activitystreams";
+        $arr['id']=""; //<-------------------
+		$arr['actor']=$this->HostURL."?apub_actor=1";
+		$arr['type']="Create";
+		$arr['to']="https://www.w3.org/ns/activitystreams#Public";
+        $arr['object']=$obj;
+        $this->APubDeliver(json_encode($arr),"https://mastodon.example/inbox"); //<-------------------
+    }
+    function APubProcessInbox(){
+        $r = file_get_contents('php://input');
+        file_put_contents('postdump.txt',$r);
+    }
     
     function MakeRSS(){
         $this->ReadPosts();$this->ReadImages();
@@ -2446,7 +2524,15 @@ blockquote{border-left:2px solid black;}
             $this->APubEnsureInfo(); header('Content-Type: application/json'); header('Cache-Control no-store, no-cache, must-revalidate');
             echo $this->APubMakeOutbox(); exit;
         }
+        if(isset($_GET['apub_inbox'])){
+            $this->APubProcessInbox();
+            http_response_code(202); exit;
+        }
         if($this->LoggedIn){
+            if(isset($_GET['TestAPubDeliver'])){
+                $this->APubTestDeliver();
+            }
+        
             $this->DoUpload();
             
             if(isset($_POST['settings_button'])){
@@ -2476,11 +2562,12 @@ blockquote{border-left:2px solid black;}
                 if(isset($_POST['settings_exp_album'])) $this->ExpAlbum=$_POST['settings_exp_album'];
                 if(isset($_POST['settings_exp_navigation'])) $this->ExpNavigation=$_POST['settings_exp_navigation'];
                 if(isset($_POST['settings_exp_footer'])) $this->ExpFooter=$_POST['settings_exp_footer'];
+                if(isset($_POST['settings_allow_language'])) $this->AllowLanguageChoices=True; else $this->AllowLanguageChoices=False;
                 if(isset($_POST['settings_mastodon_token'])) $this->MastodonToken=$_POST['settings_mastodon_token'];
                 if(isset($_POST['settings_mastodon_url'])) $this->MastodonURL=$_POST['settings_mastodon_url'];
                 if(isset($_POST['settings_mastodon_lang'])) $this->MastodonPreferredLang=$_POST['settings_mastodon_lang'];
                 if(isset($_POST['settings_host_url'])) $this->HostURL=$_POST['settings_host_url'];
-                if(isset($_POST['settings_apub_id']) && isset($this->HostURL)) { 
+                if(isset($_POST['settings_apub_id']) && isset($this->HostURL)) {
                     $this->APubID=$_POST['settings_apub_id'];
                     $this->APubEnsureWebfinger($this->APubID,$this->HostURL);
                 }
@@ -2678,8 +2765,8 @@ blockquote{border-left:2px solid black;}
         $html = preg_replace("/(<a[^>]*href=[\'\"])((.*?:\/\/).*?)([\'\"][^>]*)(>)(.*?)(<\/a>)/u",
                              "$1$2$4 target='_blank'$5$6<sup>↗</sup>$7",$html);
         $html = preg_replace("/<p>\s*\@.*?<\/p>/mu","",$html);
-        $html = preg_replace("/\{\s*(INTERESTING|HEADER|FOOTER)\s+(.*?)\}/imu","",$html);
-        $html = preg_replace("/\{\s*(REVERSED|NO_TIME|NO_TITLE)\s*\}/imu","",$html);
+        $html = preg_replace("/\{\s*(REVERSED|INTERESTING|HEADER|FOOTER)\s+(.*?)\}/imu","",$html);
+        $html = preg_replace("/\{\s*(NO_TIME|NO_TITLE)\s*\}/imu","",$html);
         $html = preg_replace("/\{\s*WIDE\s*\}/imu","",$html,-1,$rep_count); if($rep_count){$print_wide=true;}
         $images = []; $images_noclick = []; $images_orig_src_list = [];
         $html = preg_replace_callback(
@@ -2709,8 +2796,10 @@ blockquote{border-left:2px solid black;}
                         }
                         if($this->InHereMode){
                             $click = "<div class='imd'>"."<a href='?here=".$im['file']."' class='original_img'>".
-                                        $media_start.$orig_src.$media_end."></a></div>";
-                            return $click;
+                                        $media_start.($original?$orig_src:$src).$media_end."></a></div>";
+                            $ret=""; if($keep) { $ret = $click; }
+                            else { $images[] = $click; }
+                            return $ret;
                         }else{
                             $click ="<div class='imd'><a href='?show_image={$im['name']}' target='_blank' onclick='event.preventDefault();'>".
                                 $media_start.($original?$orig_src:$src).$media_end.$dataset."></a></div>";
@@ -2724,7 +2813,7 @@ blockquote{border-left:2px solid black;}
                     },$html,-1,$count);
         $html = preg_replace('/<p>\s*<\/p>/u',"", $html); if($html==""){$html="<p>&nbsp;</p>";}
         if(sizeof($images)){
-            if(sizeof($images)==1){$html.= $images[0]; }
+            if((!$this->InHereMode) && sizeof($images)==1){$html.= $images[0]; }
             else{
                 $html.="<div class='p_row'>";
                 foreach($images as $img){
@@ -3022,11 +3111,13 @@ blockquote{border-left:2px solid black;}
         <a class='hidden_on_desktop'
             href='javascript:toggle_mobile_show(document.getElementById("mobile_nav"))'><b class='round_btn'>
                 <?=$this->InExperimentalMode?$this->T($this->ExpShortTitle):$this->T($this->HereShortTitle)?></b></a>
-        <a <?=$this->HereNumber==1?"class='gray'":("href=".$this->HereLinkFromNumber($this->HereNumber-1))?>>←</a>
-        <span><?=$this->HereNumber.'/'.sizeof($this->VisitedHere);?></span>
-        <span class='round_btn'>
-            <a href='<?=$this->HereNumber==sizeof($this->VisitedHere)?"?random_here=1":$this->HereLinkFromNumber($this->HereNumber+1);?>'>→</a>
-            <a href='?random_here=1'><?=$this->T("随机")?></a></span><span class='hidden_m'></span>
+        <?php if(!$this->InExperimentalMode){ ?>
+            <a <?=$this->HereNumber==1?"class='gray'":("href=".$this->HereLinkFromNumber($this->HereNumber-1))?>>←</a>
+            <span><?=$this->HereNumber.'/'.sizeof($this->VisitedHere);?></span>
+            <span class='round_btn'>
+                <a href='<?=$this->HereNumber==sizeof($this->VisitedHere)?"?random_here=1":$this->HereLinkFromNumber($this->HereNumber+1);?>'>→</a>
+                <a href='?random_here=1'><?=$this->T("随机")?></a></span><span class='hidden_m'></span>
+        <?php } ?>
         <ul class='hidden_m' id='mobile_nav' style='text-align:center;'>
         <li class='smaller hidden_on_desktop'>&nbsp;</li>
         <li class='hidden_on_desktop block_m'><a href='index.php'><?=$this->T('主页')?></a></li>
@@ -3035,12 +3126,14 @@ blockquote{border-left:2px solid black;}
         }else if($this->InHereMode && isset($this->HereNavigation) && ($p = &$this->GetPost($this->HereNavigation))!=NULL){
             echo $this->GenerateSinglePost($p, false, false, false, false);
         } ?>
-        <li class='smaller hidden_on_desktop'>&nbsp;</li>
-        <?php if($this->LanguageAppendix=='zh'){ ?>
-            <li class='smaller invert_a gray'><a href='<?=$this->GetRedirect().'&set_language=en'?>'><b>汉语</b>/English</a></li>
-        <?php }else { ?>
-            <li class='smaller invert_a gray'><a href='<?=$this->GetRedirect().'&set_language=zh'?>'>汉语/<b>English</b></a></li>
-            <li class='smaller invert_a gray'><a id='translate_button' target='_blank'>&nbsp;Google Translate&nbsp;</a></li>
+        <?php if($this->AllowLanguageChoices){ ?>
+            <li class='smaller hidden_on_desktop'>&nbsp;</li>
+            <?php if($this->LanguageAppendix=='zh'){ ?>
+                <li class='smaller invert_a gray'><a href='<?=$this->GetRedirect().'&set_language=en'?>'><b>汉语</b>/English</a></li>
+            <?php }else { ?>
+                <li class='smaller invert_a gray'><a href='<?=$this->GetRedirect().'&set_language=zh'?>'>汉语/<b>English</b></a></li>
+                <li class='smaller invert_a gray'><a id='translate_button' target='_blank'>&nbsp;Google Translate&nbsp;</a></li>
+            <?php } ?>
         <?php } ?>
         </ul>
     <?php
@@ -3235,7 +3328,7 @@ blockquote{border-left:2px solid black;}
     }
     
     function MakeRecentPosts($search_term=NULL, $category=NULL){?>
-        <div class='center' id='div_center'>
+        <div class='center' id='div_center'><div><br /></div>
             <h2><?=isset($search_term)?$this->T('搜索'):
                                 (isset($category)?("<span class='gray'>".$this->T('分类')."</span> ".
                                     ($category=='none'?$this->T('未分类'):$this->T($category))):($this->T('最近')).
@@ -3319,9 +3412,9 @@ blockquote{border-left:2px solid black;}
         $has_ref = isset($p['refs'])&&isset($p['refs'][0]); ?>
         <div class='center_exp post_dummy smaller'>
         <hr />
-        <h3<?=$has_ref?"":" class='gray'"?>><?=$this->T('链接')?></h3>
-        <?php
-            if($has_ref){ ?>
+        <?php if(!$this->InExperimentalMode){ ?>
+            <h3<?=$has_ref?"":" class='gray'"?>><?=$this->T('链接')?></h3>
+            <?php if($has_ref){ ?>
                 <div class='smaller'><?=sizeof($p['refs'])?> <?=$this->T('个引用:')?></div>
                 <ul><?php $count_product=0;
                 foreach(array_reverse($p['refs']) as &$pr){
@@ -3332,7 +3425,7 @@ blockquote{border-left:2px solid black;}
             <?php if($count_product){ ?> <span class='smaller'><?=$this->T('和').' '.$count_product.' '.$this->T('个商品')?></span> <?php }
                 }else{ ?>
                 <div class='gray smaller'><?=$this->T('没有帖子链接到这里。')?></div>
-            <?php } ?>
+            <?php } }?>
         <div style='margin-bottom:4rem;'>&nbsp;</div>
         </div>
     <?php
@@ -3638,7 +3731,7 @@ blockquote{border-left:2px solid black;}
     function MakePostSection(&$post){
         $this->Anchors = [];
         if(isset($this->TagID)){ ?><style><?=$this->CssNumberID($this->TagID);?>{display:block;}</style><?php } ?>
-        <div class='center' id='div_center'>
+        <div class='center' id='div_center'><div><br /></div>
             <h2 class='hidden_on_print'>
             <?php $th=NULL; $is_thread = isset($post['tid']['count'])&&$post['tid']['count']>1;
                 $is_wide = (isset($post['wide'])&&$post['wide']) || ($is_thread && isset($post['tid']['wide']) && $post['tid']['wide']);
@@ -3700,7 +3793,7 @@ blockquote{border-left:2px solid black;}
     function MakePostSectionExp(&$post){
         $this->Anchors = []; $is_thread = isset($post['tid']);
         ?>
-        <div class='center_exp' id='div_center'>
+        <div class='center_exp' id='div_center'><div><br /></div>
             <ul>
             <?php $is_reversed=false;
                 if($is_thread){ $th = &$post['tid'];$use_arr = $th['arr']; $is_reversed=$this->IsReversedThread($th); $hinted=false;
@@ -4048,7 +4141,7 @@ blockquote{border-left:2px solid black;}
         <script>
         document.title+=" | <?=$this->T('画廊')?>";
         </script>
-        <div class='center_wide' id='div_center' style='position:relative;'>
+        <div class='center_wide' id='div_center' style='position:relative;'><div><br /></div>
             <h2><?=(isset($name) && ($gal=$this->GetGallery($name))!=NULL)?
                                     ("<span class='gray album_hint'>".$this->T('相册').":</span>".$this->T($name)):
                                     ($_GET['gallery']=='trash'?$this->T('垃圾桶'):$this->T('画廊'))?></h2>
@@ -4217,7 +4310,7 @@ blockquote{border-left:2px solid black;}
     }
     
     function MakeGalleryLeft(){?>
-        <div class='left hidden_m gallery_left' id='div_left'>
+        <div class='left hidden_m gallery_left' id='div_left'><div><br /></div>
             <h2><?=$this->T('相册')?></h2>
             <div>
                 <span class='gray smaller bold'><?=$this->T('精选')?><hr>  </span>
@@ -4369,7 +4462,10 @@ blockquote{border-left:2px solid black;}
                     <tr><td><?=$this->T('脚注')?><?=isset($this->ExpFooter)?"<a href='?post=".$this->ExpFooter."'>→</a>":""?></td>
                         <td><input type="text" form="settings_form" id='settings_exp_footer' name='settings_exp_footer'
                         value='<?=$this->ExpFooter?>'/></td></tr>
-                        
+                    <tr><td><?=$this->T('允许选择语言')?>
+                        <td><input type="checkbox" id="settings_allow_language" name="settings_allow_language"
+                        form="settings_form" <?=$this->AllowLanguageChoices?"checked":""?>/></td></tr>
+                       
                     <tr><td class='smaller gray'>&nbsp;</td></tr>
                     <tr><td class='smaller gray'><?=$this->T('管理员')?></td><td class='smaller'>
                         <a href='index.php?logout=true'><?=$this->T('登出')?></a></td></tr>
@@ -4428,6 +4524,10 @@ blockquote{border-left:2px solid black;}
             <input class='button' form="settings_form3" type="submit" name='settings_save_translation'
                 value='<?=$this->T('保存翻译')?>' />
             <p>&nbsp;</p>
+            <p class='smaller gray'><?=$this->T('ActivityPub 测试:')?></p>
+            <ul>
+                <li><a href='index.php?TestAPubDeliver=1'><?=$this->T('测试发送')?></a></li></ui>
+            </ui>
             <p class='smaller gray'><?=$this->T('当心!下列操作将立即执行:')?></p>
             <ul>
                 <li><a href='index.php?rewrite_styles=true'><?=$this->T('重新写入默认CSS')?></a></li>
@@ -4453,7 +4553,11 @@ blockquote{border-left:2px solid black;}
         $exptitle = isset($this->HereDisplayTitle)?('"'.trim($this->T($this->ChoosePartsByLanguage($this->HereDisplayTitle))).'"'):NULL;
         if(!isset($exptitle)) $exptitle=$this->InExperimentalMode?$this->T($this->ExpTitle):$this->T($this->HereTitle);?>
         <div class='small_footer exp_h_f exp_f'><div>
-            <b><?=$exptitle?></b> ©<?=$this->T($this->DisplayName)?>
+            <?php if($this->InExperimentalMode){ ?>
+                <b><?=$exptitle?></b>
+            <?php }else{ ?>
+                <b><?=$exptitle?></b> ©<?=$this->T($this->DisplayName)?>
+            <?php }?>
             <?=isset($this->HereMainImage)?("<a class='invert_a' href='?here=images/".$this->HereMainImage['name']."'>".$this->T("看全图")."</a>"):""; ?>
             <div class='wayback_link gray clean_a invert_a hidden_on_print'><br class="hidden_on_desktop" />
             <?php if($this->InExperimentalMode && isset($this->ExpFooter) && ($p = &$this->GetPost($this->ExpFooter,true))!=NULL){
@@ -5118,6 +5222,7 @@ blockquote{border-left:2px solid black;}
     function DoIdentifyExperimental(){
         if(isset($this->ExpHost) && $this->ExpHost && preg_match('/'.preg_quote($this->ExpHost).'/u', $_SERVER['HTTP_HOST'])){
             $this->InExperimentalMode=True; $this->InHereMode=True;
+            if(!$this->AllowLanguageChoices){ $this->LanguageAppendix='en'; }
         }
         if(isset($this->HereHost) && $this->HereHost && preg_match('/'.preg_quote($this->HereHost).'/u', $_SERVER['HTTP_HOST'])){
             $this->InHereMode=True;

+ 1 - 1
translations.md

@@ -179,7 +179,7 @@
 - 远程 | Remote
 - 回到当前日期 | Back to current time
 - SelfAuth 路径 | SelfAuth Path
-- 该话题最新帖子在前 | This thread show latest posts first
+- 该话题最新帖子在前 | Latest updates shown on top
 - 长毛象 | Mastodon
 - 转到 | View on
 - 重新发送 | Send Again